From 95ad7a484065d3310ed8bcd8d4f343626a88b46a Mon Sep 17 00:00:00 2001 From: Michael Rausch Date: Thu, 21 Sep 2017 22:48:33 +1200 Subject: [PATCH] Finished implementing room codes. - Fixed bug where room code wasn't parsed correctly - Added room code selection to server list screen. - Added room code to hosts lobby. - Implemented communication protocols on the game client. Tags: #story[1281] --- .../seng302/gameServer/ServerAdvertiser.java | 10 +++- .../messages/ServerRegistrationMessage.java | 20 +++++++ .../ServerRepoStreamParser.java | 4 +- .../serverRepository/ServerRepository.java | 25 ++++---- .../ServerRepositoryClient.java | 59 +++++++++++++++---- .../controllers/LobbyController.java | 14 +++-- .../controllers/ServerListController.java | 26 ++++++++ .../visualiser/controllers/ViewManager.java | 5 +- src/main/resources/css/ServerListView.css | 12 ++-- src/main/resources/views/ServerListView.fxml | 45 +++++++++----- 10 files changed, 167 insertions(+), 53 deletions(-) diff --git a/src/main/java/seng302/gameServer/ServerAdvertiser.java b/src/main/java/seng302/gameServer/ServerAdvertiser.java index 938ddd83..b32dc0de 100644 --- a/src/main/java/seng302/gameServer/ServerAdvertiser.java +++ b/src/main/java/seng302/gameServer/ServerAdvertiser.java @@ -3,6 +3,8 @@ package seng302.gameServer; import com.sun.org.apache.xpath.internal.operations.Bool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import seng302.serverRepository.ServerListing; +import seng302.serverRepository.ServerRepositoryClient; import javax.jmdns.JmDNS; import javax.jmdns.ServiceInfo; @@ -31,17 +33,20 @@ public class ServerAdvertiser { */ private static String SERVICE = "_partyatsea"; private static String PROTOCOL = "_tcp"; - public static String SERVICE_TYPE = SERVICE + "." + PROTOCOL + ".homekit.bonjour.michaelrausch.nz."; + public static String SERVICE_TYPE = SERVICE + "." + PROTOCOL + ".local."; private static ServerAdvertiser instance = null; private static JmDNS jmdnsInstance = null; private ServiceInfo serviceInfo; // Note: Whenever this is changed, our service will be re-registered on the network. + private ServerRepositoryClient repositoryClient; private Hashtable props; private ServerAdvertiser() throws IOException{ jmdnsInstance = JmDNS.create(InetAddress.getByName(getLocalHostIp())); + repositoryClient = new ServerRepositoryClient(); + props = new Hashtable<>(); props.put("map", ""); props.put("spacesLeft", "0"); @@ -130,6 +135,9 @@ public class ServerAdvertiser { } } }, 0); + + ServerListing serverListing = new ServerListing(serverName, props.get("map"), getLocalHostIp(), portNo, Integer.parseInt(props.get("capacity"))); + repositoryClient.register(serverListing); } /** diff --git a/src/main/java/seng302/gameServer/messages/ServerRegistrationMessage.java b/src/main/java/seng302/gameServer/messages/ServerRegistrationMessage.java index 03b9a443..ab083147 100644 --- a/src/main/java/seng302/gameServer/messages/ServerRegistrationMessage.java +++ b/src/main/java/seng302/gameServer/messages/ServerRegistrationMessage.java @@ -1,13 +1,32 @@ package seng302.gameServer.messages; +import seng302.serverRepository.ServerListing; + public class ServerRegistrationMessage extends Message { private int size; + + public ServerRegistrationMessage(ServerListing serverListing) { + String serverName = serverListing.getServerName(); + String mapName = serverListing.getMapName(); + String address = serverListing.getAddress(); + int port = serverListing.getPortNumber(); + int players = serverListing.getPortNumber(); + int capacity = serverListing.getCapacity(); + String roomCode = serverListing.getRoomCode(); + + createMessage(serverName, mapName, address, port, players, capacity, roomCode); + } + @Override public int getSize() { return size; } public ServerRegistrationMessage(String serverName, String mapName, String address, int port, int players, int capacity, String roomCode){ + createMessage(serverName, mapName, address, port, players, capacity, roomCode); + } + + private void createMessage(String serverName, String mapName, String address, int port, int players, int capacity, String roomCode){ size = serverName.getBytes().length + mapName.length() + address.length() + roomCode.length() + 36; setHeader(new Header(MessageType.REPO_REGISTRATION_REQUEST, 0x01, (short) getSize())); @@ -37,4 +56,5 @@ public class ServerRegistrationMessage extends Message { writeCRC(); rewind(); } + } diff --git a/src/main/java/seng302/serverRepository/ServerRepoStreamParser.java b/src/main/java/seng302/serverRepository/ServerRepoStreamParser.java index da7a5521..80e374b0 100644 --- a/src/main/java/seng302/serverRepository/ServerRepoStreamParser.java +++ b/src/main/java/seng302/serverRepository/ServerRepoStreamParser.java @@ -57,9 +57,9 @@ public class ServerRepoStreamParser { } private String parseRoomCodeRequest(byte[] payload) { - int roomCodeLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 0 ,4)); + int roomCodeLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 0 ,6)); - return new String(Arrays.copyOfRange(payload, 4, 4+roomCodeLength)); + return new String(Arrays.copyOfRange(payload, 6, 6+roomCodeLength)); } public static ServerListing parseServerRegistration(byte[] payload) { diff --git a/src/main/java/seng302/serverRepository/ServerRepository.java b/src/main/java/seng302/serverRepository/ServerRepository.java index 1770273b..0ba7c49e 100644 --- a/src/main/java/seng302/serverRepository/ServerRepository.java +++ b/src/main/java/seng302/serverRepository/ServerRepository.java @@ -20,17 +20,20 @@ public class ServerRepository { ServerSocket serverSocket = new ServerSocket(9999); - // TODO Remove later, this is for testing - new Timer().schedule(new TimerTask() { - @Override - public void run() { - try { - new ServerRepositoryClient(); - } catch (Exception e) { - e.printStackTrace(); - } - } - }, 5000); +// // TODO Remove later, this is for testing +// new Timer().schedule(new TimerTask() { +// @Override +// public void run() { +// try { +// System.out.println("Starting repo client"); +// new ServerRepositoryClient(); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// }, 5000); + + while (true){ Socket clientSocket = serverSocket.accept(); diff --git a/src/main/java/seng302/serverRepository/ServerRepositoryClient.java b/src/main/java/seng302/serverRepository/ServerRepositoryClient.java index 4eca3f54..85d8135a 100644 --- a/src/main/java/seng302/serverRepository/ServerRepositoryClient.java +++ b/src/main/java/seng302/serverRepository/ServerRepositoryClient.java @@ -1,36 +1,67 @@ package seng302.serverRepository; -import com.sun.xml.internal.ws.api.message.Packet; import seng302.gameServer.messages.Message; +import seng302.gameServer.messages.RoomCodeRequest; import seng302.gameServer.messages.ServerRegistrationMessage; import seng302.model.stream.packets.PacketType; -import java.io.IOException; import java.net.Socket; import java.util.Timer; import java.util.TimerTask; public class ServerRepositoryClient { - private String roomCode = "0"; + private static String roomCode = null; + private Timer serverListingUpdateTimer; - public ServerRepositoryClient() throws Exception { - new Timer().schedule(new TimerTask() { + public ServerRepositoryClient() { + + } + + public void register(ServerListing serverListing){ + serverListingUpdateTimer = new Timer(); + + serverListingUpdateTimer.schedule(new TimerTask() { @Override public void run() { try { - sendUpdate(); + sendRegistrationUpdate(serverListing); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace();//todo proper error handling } } }, 0, 5000); } - private void sendUpdate() throws Exception { + public void unregister(){ + serverListingUpdateTimer.cancel(); + } + + public ServerListing getServerForRoomCode(String roomCode) throws Exception { + // TODO replace localhost with server Socket socket = new Socket("localhost", 9999); ServerRepoStreamParser parser = new ServerRepoStreamParser(socket.getInputStream()); - Message req = new ServerRegistrationMessage("asdf", "Asdf", "asdf", 6969, 1, 20, "4949"); + + Message request = new RoomCodeRequest(roomCode); //roomCode); + socket.getOutputStream().write(request.getBuffer()); + + PacketType packetType = parser.parse(); + + if (packetType != PacketType.SERVER_REGISTRATION){ + System.out.println("Wrong packet type"); + return null; + } + + socket.close(); + + return parser.getServerListing(); + } + + private void sendRegistrationUpdate(ServerListing serverListing) throws Exception { + Socket socket = new Socket("localhost", 9999); + ServerRepoStreamParser parser = new ServerRepoStreamParser(socket.getInputStream()); + + Message req = new ServerRegistrationMessage(serverListing); socket.getOutputStream().write(req.getBuffer()); @@ -42,13 +73,15 @@ public class ServerRepositoryClient { String roomCode = parser.getRoomCode(); - if (roomCode.equals("0")){ - return; + if (roomCode.length() != 0){ + ServerRepositoryClient.roomCode = roomCode; } - this.roomCode = roomCode; - socket.close(); } + + public static String getRoomCode(){ + return roomCode; + } } diff --git a/src/main/java/seng302/visualiser/controllers/LobbyController.java b/src/main/java/seng302/visualiser/controllers/LobbyController.java index bbb39f75..a00c4610 100644 --- a/src/main/java/seng302/visualiser/controllers/LobbyController.java +++ b/src/main/java/seng302/visualiser/controllers/LobbyController.java @@ -22,6 +22,7 @@ import seng302.model.RaceState; import seng302.model.mark.CompoundMark; import seng302.model.mark.Corner; import seng302.model.stream.xml.parser.RaceXMLData; +import seng302.serverRepository.ServerRepositoryClient; import seng302.utilities.Sounds; import seng302.visualiser.GameView; import seng302.visualiser.controllers.cells.PlayerCell; @@ -29,10 +30,7 @@ import seng302.visualiser.controllers.dialogs.BoatCustomizeController; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.ResourceBundle; +import java.util.*; public class LobbyController implements Initializable { @@ -85,6 +83,10 @@ public class LobbyController implements Initializable { serverName.setText(ViewManager.getInstance().getProperty("serverName")); mapName.setText(ViewManager.getInstance().getProperty("mapName")); + if (ServerRepositoryClient.getRoomCode() != null){ + setRoomCode(ServerRepositoryClient.getRoomCode()); + } + ViewManager.getInstance().getPlayerList().addListener((ListChangeListener) c -> Platform.runLater(this::refreshPlayerList)); ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted()); @@ -242,4 +244,8 @@ public class LobbyController implements Initializable { public void closeCustomizationDialog() { customizationDialog.close(); } + + public void setRoomCode(String roomCode) { + serverName.setText(serverName.getText() + " ( " + roomCode +" )"); + } } diff --git a/src/main/java/seng302/visualiser/controllers/ServerListController.java b/src/main/java/seng302/visualiser/controllers/ServerListController.java index 3d457bd4..a21b8ad4 100644 --- a/src/main/java/seng302/visualiser/controllers/ServerListController.java +++ b/src/main/java/seng302/visualiser/controllers/ServerListController.java @@ -23,6 +23,8 @@ import javafx.scene.layout.VBox; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import seng302.gameServer.ServerDescription; +import seng302.serverRepository.ServerListing; +import seng302.serverRepository.ServerRepositoryClient; import seng302.utilities.Sounds; import seng302.visualiser.ServerListener; import seng302.visualiser.ServerListenerDelegate; @@ -51,6 +53,10 @@ public class ServerListController implements Initializable, ServerListenerDelega private JFXTextField serverHostName; @FXML private JFXTextField serverPortNumber; + @FXML + private JFXButton roomConnectButton; + @FXML + private JFXTextField roomNumber; //---------FXML END---------// private Label noServersFound; @@ -64,6 +70,17 @@ public class ServerListController implements Initializable, ServerListenerDelega // Set Event Bindings connectButton.setOnMouseEntered(event -> Sounds.playHoverSound()); serverListHostButton.setOnMouseEntered(event -> Sounds.playHoverSound()); + + roomConnectButton.setOnMouseReleased(event -> { + connectToRoomCode(roomNumber.getText()); + Sounds.playButtonClick(); + }); + roomNumber.setOnKeyPressed(event -> { + if (event.getCode().equals(KeyCode.ENTER)) { + connectToRoomCode(roomNumber.getText()); + } + }); + connectButton.setOnMouseReleased(event -> { attemptToDirectConnect(); Sounds.playButtonClick(); @@ -150,6 +167,15 @@ public class ServerListController implements Initializable, ServerListenerDelega return hostNameValid && portNumberValid; } + private void connectToRoomCode(String roomCode){ + try { + ServerListing serverListing = new ServerRepositoryClient().getServerForRoomCode(roomCode); + ViewManager.getInstance().getGameClient().runAsClient(serverListing.getAddress(), serverListing.getPortNumber()); + } catch (Exception e) { + e.printStackTrace(); + } + } + /** * Connects the user to a lobby via the Direct Connect form. */ diff --git a/src/main/java/seng302/visualiser/controllers/ViewManager.java b/src/main/java/seng302/visualiser/controllers/ViewManager.java index 165d0c39..23942294 100644 --- a/src/main/java/seng302/visualiser/controllers/ViewManager.java +++ b/src/main/java/seng302/visualiser/controllers/ViewManager.java @@ -20,6 +20,7 @@ import javafx.stage.Stage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import seng302.gameServer.ServerAdvertiser; +import seng302.serverRepository.ServerRepositoryClient; import seng302.utilities.BonjourInstallChecker; import seng302.utilities.Sounds; import seng302.visualiser.GameClient; @@ -233,8 +234,9 @@ public class ViewManager { logger.error("Could not load lobby view"); } + LobbyController lobbyController = loader.getController(); + if (disableReadyButton) { - LobbyController lobbyController = loader.getController(); lobbyController.disableReadyButton(); } @@ -245,7 +247,6 @@ public class ViewManager { * Sets up the view for the race. Creating a new decorator and destroying the old one. * @return A RaceViewController for the race view screen. */ - public RaceViewController loadRaceView() { FXMLLoader loader = loadFxml("/views/RaceView.fxml"); // have to create a new stage and set the race view maximized as JFoenix decorator has diff --git a/src/main/resources/css/ServerListView.css b/src/main/resources/css/ServerListView.css index 3bf15eb8..c865b2fa 100644 --- a/src/main/resources/css/ServerListView.css +++ b/src/main/resources/css/ServerListView.css @@ -38,30 +38,30 @@ -fx-font-size: 23px; } -#connectButton { +#connectButton, #roomConnectButton { -fx-background-color: -fx-pp-light-text-color; /* inverted */ -fx-text-fill: -fx-pp-theme-color; /* inverted */ -fx-font-size: 20px; - -fx-pref-height: 65px; + -fx-pref-height: 45px; } -#connectButton:hover { +#connectButton:hover, #roomConnectButton:hover { -fx-font-size: 23px; } -#connectLabel, #serverPortNumber, #serverHostName { +#connectLabel, #connectLabel1, #serverPortNumber, #roomNumber, #serverHostName { -fx-text-fill: -fx-pp-light-text-color; -fx-font-size: 18px; } -#serverHostName, #serverPortNumber { +#serverHostName, #serverPortNumber, #roomNumber { -jfx-focus-color: -fx-pp-light-text-color; -jfx-unfocus-color: -fx-pp-light-text-color; -fx-prompt-text-fill: -fx-pp-light-text-color; } -#serverHostName .error-label, #serverPortNumber .error-label { +#serverHostName .error-label, #serverPortNumber .error-label, #roomNumber .error-label { -fx-font-size: 12px; -fx-text-fill: lightblue; } diff --git a/src/main/resources/views/ServerListView.fxml b/src/main/resources/views/ServerListView.fxml index 928aa025..4a9493b5 100644 --- a/src/main/resources/views/ServerListView.fxml +++ b/src/main/resources/views/ServerListView.fxml @@ -1,5 +1,11 @@ + + + + + + @@ -12,35 +18,48 @@ + - + - + - + - @@ -51,6 +70,7 @@ + @@ -76,12 +96,9 @@ - + - + @@ -100,10 +117,10 @@ - + - +