diff --git a/src/main/java/inf112/fiasko/roborally/elementproperties/GameState.java b/src/main/java/inf112/fiasko/roborally/elementproperties/GameState.java
index 4280dd0..bcc5102 100644
--- a/src/main/java/inf112/fiasko/roborally/elementproperties/GameState.java
+++ b/src/main/java/inf112/fiasko/roborally/elementproperties/GameState.java
@@ -37,10 +37,6 @@ public enum GameState {
* Indicates that the game is won by a player
*/
GAME_IS_WON,
- /**
- * Indicates that the game is currently waiting for something
- */
- LOADING,
/**
* Indicates that the game is no longer running
*/
diff --git a/src/main/java/inf112/fiasko/roborally/gamewrapper/RoboRallyWrapper.java b/src/main/java/inf112/fiasko/roborally/gamewrapper/RoboRallyWrapper.java
index c1cde41..3212404 100644
--- a/src/main/java/inf112/fiasko/roborally/gamewrapper/RoboRallyWrapper.java
+++ b/src/main/java/inf112/fiasko/roborally/gamewrapper/RoboRallyWrapper.java
@@ -18,6 +18,8 @@ public class RoboRallyWrapper extends Game {
public RoboRallyGame roboRallyGame;
public RoboRallyServer server;
public RoboRallyClient client;
+ public int defaultTCPPort = 54555;
+ public int discoverUDPPort = 54777;
@Override
public void create() {
diff --git a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/IPAddressScreen.java b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/IPAddressScreen.java
index ea5899b..f3382e3 100644
--- a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/IPAddressScreen.java
+++ b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/IPAddressScreen.java
@@ -1,22 +1,25 @@
package inf112.fiasko.roborally.gamewrapper.screens;
import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.SelectBox;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.viewport.FitViewport;
-import com.badlogic.gdx.utils.viewport.Viewport;
import inf112.fiasko.roborally.gamewrapper.RoboRallyWrapper;
import inf112.fiasko.roborally.networking.RoboRallyClient;
import javax.swing.*;
import java.io.IOException;
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
/**
* This screen allows the user to enter the ip address to connect to
@@ -38,6 +41,20 @@ public class IPAddressScreen extends AbstractScreen {
TextButton joinButton = new TextButton("Join", skin);
joinButton.setSize(300, 60);
joinButton.setPosition(applicationWidth / 2f - joinButton.getWidth() / 2f, 300);
+ roboRallyWrapper.client = new RoboRallyClient(roboRallyWrapper);
+ List lanServers = roboRallyWrapper.client.getLanServers();
+ Set validHosts = new HashSet<>();
+ for (InetAddress address : lanServers) {
+ validHosts.add(address.getHostAddress());
+ }
+ final SelectBox selectBox = new SelectBox<>(skin);
+ selectBox.setItems(validHosts.toArray(new String[0]));
+ selectBox.setPosition(-80 + (applicationWidth - selectBox.getWidth()) / 2f, 200);
+ selectBox.setSize(200, 50);
+
+ stage.addActor(selectBox);
+
+
joinButton.addListener(new ClickListener() {
@Override
public boolean touchDown(InputEvent e, float x, float y, int point, int button) {
@@ -47,10 +64,16 @@ public class IPAddressScreen extends AbstractScreen {
@Override
public void touchUp(InputEvent e, float x, float y, int point, int button) {
try {
- roboRallyWrapper.client = new RoboRallyClient(textInput.getText(), roboRallyWrapper);
+ String serverIp;
+ String writtenIP = textInput.getText();
+ if (writtenIP.isEmpty()) {
+ serverIp = selectBox.getSelected();
+ } else {
+ serverIp = writtenIP;
+ }
+ roboRallyWrapper.client.connect(serverIp, roboRallyWrapper.defaultTCPPort, roboRallyWrapper.discoverUDPPort);
roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getUsernameScreen(roboRallyWrapper));
} catch (IOException ex) {
- ex.printStackTrace();
JOptionPane.showMessageDialog(null, "Could not connect to the server."
+ " Please make sure the ip address you typed is correct, and that the server is online.");
}
@@ -80,7 +103,8 @@ public class IPAddressScreen extends AbstractScreen {
roboRallyWrapper.batch.setProjectionMatrix(camera.combined);
roboRallyWrapper.batch.begin();
- roboRallyWrapper.font.draw(roboRallyWrapper.batch, "Enter IP address and click the button to join a server",
+ roboRallyWrapper.font.draw(roboRallyWrapper.batch, "Enter or select IP address and click the button to " +
+ "join a server",
applicationWidth / 2f - 380 / 2f, applicationHeight / 2f + 100, 380, 1,
true);
roboRallyWrapper.batch.end();
diff --git a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/LoadingScreen.java b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/LoadingScreen.java
index 296a79e..9164c8d 100644
--- a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/LoadingScreen.java
+++ b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/LoadingScreen.java
@@ -44,9 +44,7 @@ public class LoadingScreen extends AbstractScreen {
if (roboRallyWrapper.roboRallyGame != null) {
GameState gameState = roboRallyWrapper.roboRallyGame.getGameState();
- if (gameState != GameState.LOADING) {
- handleScreenChange(gameState);
- }
+ handleScreenChange(gameState);
}
}
@@ -73,12 +71,12 @@ public class LoadingScreen extends AbstractScreen {
roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getPowerDownScreen(this.roboRallyWrapper));
break;
case SKIP_POWER_DOWN_SCREEN:
- roboRallyWrapper.roboRallyGame.setGameState(GameState.LOADING);
+ roboRallyWrapper.roboRallyGame.setGameState(GameState.WAITING_FOR_OTHER_PLAYERS_PROGRAMS);
roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getLoadingScreen(this.roboRallyWrapper));
roboRallyWrapper.client.sendElement(new ProgramAndPowerdownRequest(false, new ArrayList<>()));
break;
default:
- System.out.println("The loading screen doesn't know what to do with " + gameState);
+ //Ignored
break;
}
}
diff --git a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/PowerDownScreen.java b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/PowerDownScreen.java
index 4f121b9..b917871 100644
--- a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/PowerDownScreen.java
+++ b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/PowerDownScreen.java
@@ -56,9 +56,9 @@ public class PowerDownScreen extends AbstractScreen {
roboRallyWrapper.batch.setProjectionMatrix(camera.combined);
String descriptionText;
if (roboRallyWrapper.roboRallyGame.getGameState() == GameState.CHOOSING_POWER_DOWN) {
- descriptionText = "Click the button to enter power down next round";
+ descriptionText = "Click the button to enter power down next turn";
} else {
- descriptionText = "Click the button to continue your power down the next round";
+ descriptionText = "Click the button to continue your power down the next turn";
}
int elapsedTime = (int) Math.floor((System.currentTimeMillis() - startTime) / 1000f);
@@ -90,7 +90,7 @@ public class PowerDownScreen extends AbstractScreen {
roboRallyWrapper.client.sendElement(bool);
break;
case CHOOSING_POWER_DOWN:
- roboRallyWrapper.roboRallyGame.setGameState(GameState.LOADING);
+ roboRallyWrapper.roboRallyGame.setGameState(GameState.WAITING_FOR_OTHER_PLAYERS_PROGRAMS);
roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getLoadingScreen(this.roboRallyWrapper));
roboRallyWrapper.client.sendElement(new ProgramAndPowerdownRequest(bool,
roboRallyWrapper.roboRallyGame.getProgram()));
diff --git a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/StartMenuScreen.java b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/StartMenuScreen.java
index 57b08db..621e883 100644
--- a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/StartMenuScreen.java
+++ b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/StartMenuScreen.java
@@ -39,11 +39,11 @@ public class StartMenuScreen extends AbstractScreen {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
try {
- roboRallyWrapper.server = new RoboRallyServer();
- roboRallyWrapper.client = new RoboRallyClient("127.0.0.1", roboRallyWrapper);
+ roboRallyWrapper.server = new RoboRallyServer(roboRallyWrapper.defaultTCPPort, roboRallyWrapper.discoverUDPPort);
+ roboRallyWrapper.client = new RoboRallyClient(roboRallyWrapper);
+ roboRallyWrapper.client.connect("127.0.0.1", roboRallyWrapper.defaultTCPPort, roboRallyWrapper.discoverUDPPort);
roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getUsernameScreen(roboRallyWrapper));
} catch (IOException e) {
- e.printStackTrace();
//Hard fail
roboRallyWrapper.quit("Server could not be started");
}
diff --git a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/UsernameScreen.java b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/UsernameScreen.java
index d12a1f5..d1980af 100644
--- a/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/UsernameScreen.java
+++ b/src/main/java/inf112/fiasko/roborally/gamewrapper/screens/UsernameScreen.java
@@ -1,7 +1,6 @@
package inf112.fiasko.roborally.gamewrapper.screens;
import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
@@ -47,12 +46,12 @@ public class UsernameScreen extends AbstractScreen {
JOptionPane.showMessageDialog(null, "Username cannot be empty.");
return;
}
- roboRallyWrapper.client.sendElement(userName);
if (roboRallyWrapper.server == null) {
roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getLoadingScreen(roboRallyWrapper));
} else {
roboRallyWrapper.setScreen(roboRallyWrapper.screenManager.getLobbyScreen(roboRallyWrapper));
}
+ roboRallyWrapper.client.sendElement(userName);
}
});
textInput = new TextField("", skin);
diff --git a/src/main/java/inf112/fiasko/roborally/networking/RoboRallyClient.java b/src/main/java/inf112/fiasko/roborally/networking/RoboRallyClient.java
index 7d212ca..e23564c 100644
--- a/src/main/java/inf112/fiasko/roborally/networking/RoboRallyClient.java
+++ b/src/main/java/inf112/fiasko/roborally/networking/RoboRallyClient.java
@@ -5,27 +5,48 @@ import inf112.fiasko.roborally.gamewrapper.RoboRallyWrapper;
import inf112.fiasko.roborally.utility.NetworkUtil;
import java.io.IOException;
+import java.net.InetAddress;
+import java.util.List;
/**
* This class represents a client capable of connecting to a Robo Rally server
*/
public class RoboRallyClient {
private final Client client;
+ private RoboRallyWrapper wrapper;
/**
* Instantiates a new Robo Rally client
*
- * @param ipAddress The ip address of the server to connect to
- * @param wrapper The Robo Rally wrapper to be used
- * @throws IOException If the server cannot be reached
+ * @param wrapper The Robo Rally wrapper to be used
*/
- public RoboRallyClient(String ipAddress, RoboRallyWrapper wrapper) throws IOException {
+ public RoboRallyClient(RoboRallyWrapper wrapper) {
+ this.wrapper = wrapper;
client = new Client();
client.start();
NetworkUtil.registerClasses(client.getKryo());
- client.connect(5000, ipAddress, 54555);
client.addListener(new RoboRallyClientListener(wrapper));
+ }
+ /**
+ * Connects to a Robo Rally server
+ *
+ * @param ipAddress The ip address of the server to join
+ * @param TCPPort The TCP port to connect to
+ * @param UDPPort The UDP port to connect to
+ * @throws IOException If the server cannot be connected to
+ */
+ public void connect(String ipAddress, int TCPPort, int UDPPort) throws IOException {
+ client.connect(5000, ipAddress, TCPPort, UDPPort);
+ }
+
+ /**
+ * Gets a list of addresses of local Robo Rally servers
+ *
+ * @return A list of server ip addresses
+ */
+ public List getLanServers() {
+ return client.discoverHosts(wrapper.discoverUDPPort, 1000);
}
/**
diff --git a/src/main/java/inf112/fiasko/roborally/networking/RoboRallyClientListener.java b/src/main/java/inf112/fiasko/roborally/networking/RoboRallyClientListener.java
index 53a90c8..0c496e7 100644
--- a/src/main/java/inf112/fiasko/roborally/networking/RoboRallyClientListener.java
+++ b/src/main/java/inf112/fiasko/roborally/networking/RoboRallyClientListener.java
@@ -46,6 +46,7 @@ class RoboRallyClientListener extends Listener {
GameStartInfoResponse info = (GameStartInfoResponse) object;
wrapper.roboRallyGame = new RoboRallyGame(info.getPlayerList(), info.getBoardName(),
wrapper.server != null, info.getPlayerName(), wrapper.server);
+ new Thread(() -> wrapper.roboRallyGame.runTurn()).start();
} else if (object instanceof ProgrammingCardDeck) {
if (((ProgrammingCardDeck) object).isEmpty()) {
wrapper.roboRallyGame.setProgram(new ArrayList<>());
@@ -57,7 +58,7 @@ class RoboRallyClientListener extends Listener {
} else {
wrapper.roboRallyGame.setGameState(GameState.CHOOSING_CARDS);
}
- new Thread(() -> wrapper.roboRallyGame.setPlayerHand((ProgrammingCardDeck) object)).start();
+ wrapper.roboRallyGame.setPlayerHand((ProgrammingCardDeck) object);
} else if (object instanceof ProgramsContainerResponse) {
new Thread(() -> {
try {
diff --git a/src/main/java/inf112/fiasko/roborally/networking/RoboRallyServer.java b/src/main/java/inf112/fiasko/roborally/networking/RoboRallyServer.java
index 4cd3a25..2aa1a08 100644
--- a/src/main/java/inf112/fiasko/roborally/networking/RoboRallyServer.java
+++ b/src/main/java/inf112/fiasko/roborally/networking/RoboRallyServer.java
@@ -6,6 +6,7 @@ import inf112.fiasko.roborally.elementproperties.RobotID;
import inf112.fiasko.roborally.utility.NetworkUtil;
import java.io.IOException;
+import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
@@ -19,13 +20,15 @@ public class RoboRallyServer {
/**
* Instantiates a new Robo Rally server
*
+ * @param TCPPort The TCP port to bind to
+ * @param UDPPort The UDP port to bind to
* @throws IOException If the server cannot be started
*/
- public RoboRallyServer() throws IOException {
+ public RoboRallyServer(int TCPPort, int UDPPort) throws IOException {
server = new Server();
server.start();
NetworkUtil.registerClasses(server.getKryo());
- server.bind(54555);
+ server.bind(TCPPort, UDPPort);
listener = new RoboRallyServerListener(this);
server.addListener(listener);
}
diff --git a/src/main/java/inf112/fiasko/roborally/networking/RoboRallyServerListener.java b/src/main/java/inf112/fiasko/roborally/networking/RoboRallyServerListener.java
index 2e9ef89..84866fe 100644
--- a/src/main/java/inf112/fiasko/roborally/networking/RoboRallyServerListener.java
+++ b/src/main/java/inf112/fiasko/roborally/networking/RoboRallyServerListener.java
@@ -85,7 +85,13 @@ class RoboRallyServerListener extends Listener {
* @return A mapping between connections and robot ids
*/
public Map getPlayerNames() {
- return playerNames;
+ Map alivePlayers = new HashMap<>();
+ for (Connection connection : playerNames.keySet()) {
+ if (!deadPlayers.contains(connection)) {
+ alivePlayers.put(connection, playerNames.get(connection));
+ }
+ }
+ return alivePlayers;
}
/**
diff --git a/src/main/java/inf112/fiasko/roborally/objects/Board.java b/src/main/java/inf112/fiasko/roborally/objects/Board.java
index 3bd87a7..4ab45d4 100644
--- a/src/main/java/inf112/fiasko/roborally/objects/Board.java
+++ b/src/main/java/inf112/fiasko/roborally/objects/Board.java
@@ -643,7 +643,7 @@ public class Board {
* Kills the robot
*
* If the robot steps outside of the board, steps on a hole or takes too much damage, this method should be used to
- * properly dispose of the robot until the next round.
+ * properly dispose of the robot until the next turn.
*
* @param robot The robot to kill
*/
diff --git a/src/main/java/inf112/fiasko/roborally/objects/Player.java b/src/main/java/inf112/fiasko/roborally/objects/Player.java
index 5757020..9d8a682 100644
--- a/src/main/java/inf112/fiasko/roborally/objects/Player.java
+++ b/src/main/java/inf112/fiasko/roborally/objects/Player.java
@@ -114,7 +114,7 @@ public class Player {
/**
* Sets the power down status
*
- * @param powerDownStatus Whether the player is to take power down next round
+ * @param powerDownStatus Whether the player is to take power down next turn
*/
public void setPowerDownNextRound(boolean powerDownStatus) {
this.powerDownNextRound = powerDownStatus;
diff --git a/src/main/java/inf112/fiasko/roborally/objects/RoboRallyGame.java b/src/main/java/inf112/fiasko/roborally/objects/RoboRallyGame.java
index 2d6b00b..4cd9aa9 100644
--- a/src/main/java/inf112/fiasko/roborally/objects/RoboRallyGame.java
+++ b/src/main/java/inf112/fiasko/roborally/objects/RoboRallyGame.java
@@ -24,7 +24,7 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
private final boolean host;
private final String playerName;
private final RoboRallyServer server;
- private final Phase phase;
+ private Phase phase;
private Board gameBoard;
private List> repairTiles;
private Deck mainDeck;
@@ -49,7 +49,6 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
this.playerList = playerList;
this.server = server;
initializeGame(boardName);
- this.phase = new Phase(gameBoard, playerList, 600, this);
}
/**
@@ -187,8 +186,11 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
player.setPowerDownNextRound(powerDowns.getPowerDown().get(player.getName()));
}
}
+ //Respawns robots and registers robots which are dead forever
respawnRobots();
+ //Sends list of dead players to server and removes dead players from the player list
sendAllDeadPlayersToServer();
+ //Resets hasTouchedFlagThisTurn
resetHasTouchedFlagThisTurnForAllRobots();
setGameState(GameState.BEGINNING_OF_GAME);
runTurn();
@@ -227,7 +229,7 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
mainDeck = DeckLoaderUtil.loadProgrammingCardsDeck();
}
- new Thread(this::runTurn).start();
+ phase = new Phase(gameBoard, playerList, 600, this);
} catch (IOException e) {
e.printStackTrace();
}
@@ -249,19 +251,21 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
gameBoard.setBackupPositionOfRobot(robotID, spawnTileContainer.getPosition());
}
-
}
/**
- * Runs all the steps of one turn in the game
+ * Starts a turn in the game
*/
- private void runTurn() {
+ public void runTurn() {
// Sets the power down status to true on robots that have players who planned one this turn.
// Resets players power down for next turn to false.
updateRobotPowerDown();
// Set damage of robots in power down to 0
gameBoard.executePowerDown();
- setGameState(GameState.LOADING);
+ //This check prevents the state from being overwritten if the client has already received the cards
+ if (gameState == GameState.BEGINNING_OF_GAME) {
+ setGameState(GameState.WAITING_FOR_CARDS_FROM_SERVER);
+ }
if (host) {
//Distributes programming cards for all players, and sends a deck to each player
distributeProgrammingCardsToPlayers();
@@ -270,6 +274,8 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
Player player = getPlayerFromName(playerName);
if (player != null && player.getProgrammingCardDeck() != null) {
server.sendToClient(connection, player.getProgrammingCardDeck());
+ } else {
+ throw new IllegalArgumentException("Player " + playerName + " is not part of the game.");
}
}
}
@@ -279,9 +285,6 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
* Sends information about players no longer part of the game to the server
*/
private void sendAllDeadPlayersToServer() {
- if (host) {
- server.setDeadPlayers(gameBoard.getRealDeadRobots());
- }
//Removes dead players from playerList
playerList.removeIf((player) -> gameBoard.getRealDeadRobots().contains(player.getRobotID()));
if (playerList.isEmpty()) {
@@ -292,7 +295,9 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
e.printStackTrace();
}
}
-
+ if (host) {
+ server.setDeadPlayers(gameBoard.getRealDeadRobots());
+ }
}
/**
@@ -406,7 +411,7 @@ public class RoboRallyGame implements DrawableGame, InteractableGame {
}
/**
- * Sets the robot's power down status to the player's "power down next round" status and sets the players status to false
+ * Sets the robot's power down status to the player's "power down next turn" status and sets the players status to false
*/
private void updateRobotPowerDown() {
for (Player player : playerList) {