From 0c5d66199504dbab22f415e5e1b8e615a543ac41 Mon Sep 17 00:00:00 2001 From: Michael Rausch Date: Thu, 31 Aug 2017 01:11:17 +1200 Subject: [PATCH] Fixed discovery bug, implemented server list, added server parameters - Resolved DNS bug by updating to a newer version of JmDNS - Added server list, this is populated with new servers as they are discovered - Added map name and spaces remaining to server advertisement Tags: #story[1247] --- pom.xml | 10 ++- src/main/java/seng302/App.java | 9 ++- .../seng302/gameServer/MainServerThread.java | 19 +++++ .../seng302/gameServer/ServerAdvertiser.java | 35 +++++++--- .../seng302/gameServer/ServerDescription.java | 39 +++++++++++ .../java/seng302/visualiser/GameClient.java | 1 + .../seng302/visualiser/ServerListener.java | 46 +++++++++++-- .../visualiser/ServerListenerDelegate.java | 8 ++- .../controllers/StartScreenController.java | 69 ++++++++++++++++++- src/main/resources/views/StartScreenView.fxml | 19 ++--- 10 files changed, 220 insertions(+), 35 deletions(-) create mode 100644 src/main/java/seng302/gameServer/ServerDescription.java diff --git a/pom.xml b/pom.xml index 4ec5f059..7c28e437 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ javax.jmdns jmdns - 3.4.1 + 3.4.2 @@ -159,4 +159,12 @@ + + + + Homer-Core + Homer-core-repo + https://nexus.arcsmed.at/content/repositories/homer.core + + \ No newline at end of file diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index 8c6f85ac..5dbfe4bb 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -14,13 +14,17 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import seng302.gameServer.ServerAdvertiser; import seng302.model.PolarTable; +import seng302.visualiser.ServerListener; + +import java.io.IOException; public class App extends Application { private static Logger logger = LoggerFactory.getLogger(App.class); - public static void parseArgs(String[] args) throws ParseException { + public static void parseArgs(String[] args) throws ParseException, IOException { Options options = new Options(); CommandLineParser parser = new DefaultParser(); CommandLine cmd; @@ -82,6 +86,7 @@ public class App extends Application { primaryStage.setOnCloseRequest(e -> { // ClientPacketParser.appClose(); // ClientPacketParser.appClose(); + System.exit(0); }); @@ -93,6 +98,8 @@ public class App extends Application { parseArgs(args); } catch (ParseException e) { logger.error("Could not parse command line arguments"); + } catch (IOException e) { + e.printStackTrace(); } launch(args); diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 83fb304c..d1e5a23a 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -1,5 +1,8 @@ package seng302.gameServer; +import javafx.application.Platform; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import seng302.gameServer.messages.*; import seng302.model.GeoPoint; import seng302.model.Player; @@ -37,6 +40,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { private ServerSocket serverSocket = null; private ArrayList serverToClientThreads = new ArrayList<>(); + private Logger logger = LoggerFactory.getLogger(MainServerThread.class); public MainServerThread() { new GameState("localhost"); @@ -45,6 +49,15 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { } catch (IOException e) { serverLog("IO error in server thread handler upon trying to make new server socket", 0); } + + // Start advertising server + try{ + ServerAdvertiser.getInstance().registerGame(PORT, "PP Test Server", 10, "Random Map"); + } catch (IOException e) { + logger.warn("Could not register server"); + } + + PolarTable.parsePolarFile(getClass().getResourceAsStream("/config/acc_polars.csv")); GameState.addMarkPassListener(this::broadcastMessage); terminated = false; @@ -206,6 +219,12 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { } public void startGame() { + try { + ServerAdvertiser.getInstance().unregister(); + } catch (IOException e) { + logger.warn("Error unregistering server"); + } + initialiseBoatPositions(); Timer t = new Timer(); diff --git a/src/main/java/seng302/gameServer/ServerAdvertiser.java b/src/main/java/seng302/gameServer/ServerAdvertiser.java index 04a53b46..2d069372 100644 --- a/src/main/java/seng302/gameServer/ServerAdvertiser.java +++ b/src/main/java/seng302/gameServer/ServerAdvertiser.java @@ -4,11 +4,12 @@ import javax.jmdns.JmDNS; import javax.jmdns.ServiceInfo; import java.io.IOException; import java.net.InetAddress; +import java.util.Hashtable; public class ServerAdvertiser { - private static String SERVICE = "_partyatsea_"; + private static String SERVICE = "_partyatsea"; private static String PROTOCOL = "_tcp"; - public static String SERVICE_TYPE = SERVICE + "." + PROTOCOL + ".local"; + public static String SERVICE_TYPE = SERVICE + "." + PROTOCOL + ".local."; private static Integer PROTO_VERSION = 1; @@ -16,7 +17,7 @@ public class ServerAdvertiser { private static JmDNS jmdnsInstance = null; private ServerAdvertiser() throws IOException{ - jmdnsInstance = JmDNS.create(InetAddress.getLocalHost(), InetAddress.getByName(InetAddress.getLocalHost().getHostName()).toString()); + jmdnsInstance = JmDNS.create(InetAddress.getLocalHost()); } public static ServerAdvertiser getInstance() throws IOException { @@ -27,14 +28,30 @@ public class ServerAdvertiser { return instance; } - public void registerGame(Integer portNo, String serverName, Integer spacesLeft, String mapName) throws IOException { - String serviceData = packageServerData(spacesLeft, mapName, PROTO_VERSION); - ServiceInfo serviceInfo = ServiceInfo.create(SERVICE_TYPE, serverName, portNo, serviceData); + public void registerGame(Integer portNo, String serverName, Integer spacesLeft, String mapName) { + Hashtable props = new Hashtable<>(); - jmdnsInstance.registerService(serviceInfo); + props.put("map", mapName); + props.put("spacesLeft", spacesLeft.toString()); + + ServiceInfo serviceInfo = ServiceInfo.create(SERVICE_TYPE, serverName, portNo, 0, 0, props); + + new java.util.Timer().schedule( + new java.util.TimerTask() { + @Override + public void run() { + try { + jmdnsInstance.registerService(serviceInfo); + } catch (IOException e) { + System.out.println("Failed"); + } + } + }, 0 + ); } - private String packageServerData(Integer spacesLeft, String mapName, Integer version){ - return spacesLeft.toString() + "|" + mapName + "|" + version.toString(); + public void unregister(){ + jmdnsInstance.unregisterAllServices(); + jmdnsInstance = null; } } diff --git a/src/main/java/seng302/gameServer/ServerDescription.java b/src/main/java/seng302/gameServer/ServerDescription.java new file mode 100644 index 00000000..181cde39 --- /dev/null +++ b/src/main/java/seng302/gameServer/ServerDescription.java @@ -0,0 +1,39 @@ +package seng302.gameServer; + +public class ServerDescription { + private String address; + private Integer portNum; + + private String serverName; + private String mapName; + private Integer spacesLeft; + + public ServerDescription(String serverName, String mapName, Integer spacesLeft, String address, Integer portNum){ + this.serverName = serverName; + this.mapName = mapName; + this.spacesLeft = spacesLeft; + this.address = address; + this.portNum = portNum; + } + + + public String getName() { + return serverName; + } + + public String getMapName() { + return mapName; + } + + public Integer portNumber() { + return portNum; + } + + public String getAddress(){ + return address; + } + + public Integer spacesLeft() { + return spacesLeft; + } +} diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index 968d9a92..62d16d88 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -142,6 +142,7 @@ public class GameClient { } private void loadStartScreen() { + socketThread.setSocketToClose(); if (server != null) { server.terminate(); diff --git a/src/main/java/seng302/visualiser/ServerListener.java b/src/main/java/seng302/visualiser/ServerListener.java index 47cdf2d2..2cb79bdb 100644 --- a/src/main/java/seng302/visualiser/ServerListener.java +++ b/src/main/java/seng302/visualiser/ServerListener.java @@ -1,6 +1,7 @@ package seng302.visualiser; import seng302.gameServer.ServerAdvertiser; +import seng302.gameServer.ServerDescription; import javax.jmdns.JmDNS; import javax.jmdns.ServiceEvent; @@ -8,36 +9,67 @@ import javax.jmdns.ServiceListener; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; public class ServerListener{ private static ServerListener instance; private ServerListenerDelegate delegate; private JmDNS jmdns = null; + GameServeMonitor listener; - private class GameServerListener implements ServiceListener { - GameServerListener(){ - System.out.println("Created GSL instance"); + private class GameServeMonitor implements ServiceListener { + private List servers; + + GameServeMonitor(){ + servers = new ArrayList<>(); } @Override public void serviceAdded(ServiceEvent event) { - delegate.serverDetected(event.getName(), "", 123, event.getInfo().getInet4Addresses().toString()); } @Override public void serviceRemoved(ServiceEvent event) { - delegate.serverRemoved(event.getName()); + Integer serverId = -1; + + for (int i = 0; i < servers.size(); i++){ + ServerDescription server = servers.get(i); + if (server.getName().equals(event.getInfo().getName())){ + serverId = i; + break; + } + } + + if (serverId > 0){ + servers.remove(serverId); + } + + delegate.serverRemoved(servers); } @Override public void serviceResolved(ServiceEvent event) { - // Do nothing + String address = event.getInfo().getServer(); + Integer portNum = event.getInfo().getPort(); + + String serverName = event.getInfo().getName(); + String mapName = event.getInfo().getPropertyString("map"); + Integer spacesLeft = Integer.parseInt(event.getInfo().getPropertyString("spacesLeft")); + + ServerDescription serverDescription = new ServerDescription(serverName, mapName, spacesLeft, address, portNum); + servers.add(serverDescription); + + delegate.serverDetected(serverDescription, Collections.unmodifiableList(servers)); } } private ServerListener() throws IOException { jmdns = JmDNS.create(InetAddress.getLocalHost()); - jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, new GameServerListener()); + listener = new GameServeMonitor(); + jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener); } public static ServerListener getInstance() throws IOException { diff --git a/src/main/java/seng302/visualiser/ServerListenerDelegate.java b/src/main/java/seng302/visualiser/ServerListenerDelegate.java index 83694823..15400a86 100644 --- a/src/main/java/seng302/visualiser/ServerListenerDelegate.java +++ b/src/main/java/seng302/visualiser/ServerListenerDelegate.java @@ -1,6 +1,10 @@ package seng302.visualiser; +import seng302.gameServer.ServerDescription; + +import java.util.List; + public interface ServerListenerDelegate { - void serverDetected(String serverName, String mapName, Integer placesLeft, String serverAddress); - void serverRemoved(String serverName); + void serverRemoved(List currentServers); + void serverDetected(ServerDescription serverDescription, List servers); } diff --git a/src/main/java/seng302/visualiser/controllers/StartScreenController.java b/src/main/java/seng302/visualiser/controllers/StartScreenController.java index 1a9db1a1..7d30f493 100644 --- a/src/main/java/seng302/visualiser/controllers/StartScreenController.java +++ b/src/main/java/seng302/visualiser/controllers/StartScreenController.java @@ -1,24 +1,33 @@ package seng302.visualiser.controllers; +import java.io.IOException; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.URL; -import java.util.Enumeration; -import java.util.ResourceBundle; +import java.util.*; + +import com.sun.security.ntlm.Server; +import cucumber.api.java.en.But; import javafx.fxml.FXML; import javafx.fxml.Initializable; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ListView; import javafx.scene.control.TextField; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import seng302.gameServer.GameState; +import seng302.gameServer.ServerDescription; import seng302.visualiser.GameClient; +import seng302.visualiser.ServerListener; +import seng302.visualiser.ServerListenerDelegate; /** * A Class describing the actions of the start screen controller * Created by wmu16 on 10/07/17. */ -public class StartScreenController implements Initializable { +public class StartScreenController implements Initializable, ServerListenerDelegate{ @FXML private TextField ipTextField; @@ -29,10 +38,27 @@ public class StartScreenController implements Initializable { @FXML private AnchorPane holder; + @FXML + private Button joinLobbyButton; + + @FXML + private ListView serverList; + + private List servers = null; + private boolean serverListDirty = false; + GameClient gameClient; public void initialize(URL url, ResourceBundle resourceBundle) { // gameClient = new GameClient(holder); + + try { + ServerListener.getInstance().setDelegate(this); + } catch (IOException e) { + e.printStackTrace(); + } + + joinLobbyButton.setOnAction(event -> joinLobbyClicked()); } // // /** @@ -165,4 +191,41 @@ public class StartScreenController implements Initializable { // ClientState.setHostIp(ipAddress); return ipAddress; } + + private void refreshServerList(List servers){ + this.serverList.getItems().clear(); + + for (ServerDescription server : servers){ + serverList.getItems().add(server.getName() + " - " + server.getMapName() + " - " + server.spacesLeft() + " spaces left"); + } + } + + @Override + public void serverRemoved(List currentServers) { + this.servers = currentServers; + + refreshServerList(currentServers); + } + + @Override + public void serverDetected(ServerDescription serverDescription, List servers) { + this.servers = servers; + + refreshServerList(servers); + } + + private void joinLobbyClicked() { + Integer selectedServer = serverList.getSelectionModel().getSelectedIndex(); + + if (this.servers == null || selectedServer >= this.servers.size()){ + Alert alert = new Alert(Alert.AlertType.ERROR, "Invalid server selected"); + alert.showAndWait(); + return; + } + + ServerDescription server = servers.get(selectedServer); + + gameClient = new GameClient(holder); + gameClient.runAsClient(server.getAddress().trim().toLowerCase(), server.portNumber()); + } } diff --git a/src/main/resources/views/StartScreenView.fxml b/src/main/resources/views/StartScreenView.fxml index 4bd0a808..f04dcf50 100644 --- a/src/main/resources/views/StartScreenView.fxml +++ b/src/main/resources/views/StartScreenView.fxml @@ -1,13 +1,9 @@ - - - - - + @@ -16,17 +12,17 @@ - + - + -