diff --git a/src/main/java/seng302/gameServer/MessageFactory.java b/src/main/java/seng302/gameServer/MessageFactory.java index 7cdd5b15..03840c4c 100644 --- a/src/main/java/seng302/gameServer/MessageFactory.java +++ b/src/main/java/seng302/gameServer/MessageFactory.java @@ -77,9 +77,9 @@ public class MessageFactory { } public static void updateBoats(List yachts) { - for (ServerYacht serverYacht : yachts) { - System.out.println(serverYacht); - } +// for (ServerYacht serverYacht : yachts) { +// System.out.println(serverYacht); +// } xmlGenerator.getRace().setBoats(yachts); String xmlStr = xmlGenerator.getBoatsAsXml(); MessageFactory.boats = new XMLMessage(xmlStr, XMLMessageSubType.BOAT, xmlStr.length()); diff --git a/src/main/java/seng302/gameServer/ServerAdvertiser.java b/src/main/java/seng302/gameServer/ServerAdvertiser.java index a98ee0f0..d0868734 100644 --- a/src/main/java/seng302/gameServer/ServerAdvertiser.java +++ b/src/main/java/seng302/gameServer/ServerAdvertiser.java @@ -1,5 +1,7 @@ package seng302.gameServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import seng302.discoveryServer.DiscoveryServerClient; import seng302.discoveryServer.util.ServerListing; @@ -38,6 +40,7 @@ public class ServerAdvertiser { private DiscoveryServerClient repositoryClient; private Hashtable props; + private Logger logger = LoggerFactory.getLogger(ServerAdvertiser.class); private ServerAdvertiser() throws IOException{ jmdnsInstance = JmDNS.create(InetAddress.getByName(getLocalHostIp())); @@ -128,7 +131,7 @@ public class ServerAdvertiser { try { jmdnsInstance.registerService(serviceInfo); } catch (IOException e) { - System.out.println("Failed"); + logger.warn("Failed to register service info"); } } }, 0); diff --git a/src/main/java/seng302/utilities/StreamParser.java b/src/main/java/seng302/utilities/StreamParser.java index 0b9a210a..73666a1f 100644 --- a/src/main/java/seng302/utilities/StreamParser.java +++ b/src/main/java/seng302/utilities/StreamParser.java @@ -136,7 +136,6 @@ public class StreamParser { long messageLength = bytesToLong(Arrays.copyOfRange(payload, 12, 14)); String xmlMessage = new String( (Arrays.copyOfRange(payload, 14, (int) (14 + messageLength)))).trim(); - System.out.println(xmlMessage); //Create XML document Object DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db; diff --git a/src/main/java/seng302/utilities/XMLParser.java b/src/main/java/seng302/utilities/XMLParser.java index 395555a6..863b23bb 100644 --- a/src/main/java/seng302/utilities/XMLParser.java +++ b/src/main/java/seng302/utilities/XMLParser.java @@ -1,6 +1,7 @@ package seng302.utilities; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -380,7 +381,7 @@ public class XMLParser { /** * This ungodly combination of existing methods and code blocks parses a race definition file. * Look upon it and despair. - * @param url the location of the race def file + * @param url The input file path * @param serverName the name of the server * @param repetitions the repetitions of a segment of the race def file. * @param maxPlayers max number of players. uses the default race max if null or greater than the actual max. @@ -388,14 +389,14 @@ public class XMLParser { * @return a pair which contains regatta string, race string as key, value pair. */ public static Pair parseRaceDef( - String url, String serverName, Integer repetitions, Integer maxPlayers, Boolean tokensEnabled + String url, String serverName, Integer repetitions, Integer maxPlayers, Boolean tokensEnabled ) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db; Document doc = null; try { db = dbf.newDocumentBuilder(); - doc = db.parse(url); + doc = db.parse(XMLParser.class.getResourceAsStream(url)); } catch (ParserConfigurationException | IOException | SAXException e) { e.printStackTrace(); } diff --git a/src/main/java/seng302/visualiser/ClientToServerThread.java b/src/main/java/seng302/visualiser/ClientToServerThread.java index f91a913b..f70bbe3a 100644 --- a/src/main/java/seng302/visualiser/ClientToServerThread.java +++ b/src/main/java/seng302/visualiser/ClientToServerThread.java @@ -57,6 +57,11 @@ public class ClientToServerThread implements Runnable { void notifyDisconnection(String message); } + @FunctionalInterface + public interface ConnectionErrorListener { + void notifyConnectionError(String message); + } + private class ByteReadException extends Exception { private ByteReadException(String message) { super(message); @@ -66,6 +71,7 @@ public class ClientToServerThread implements Runnable { private Queue streamPackets = new ConcurrentLinkedQueue<>(); private List listeners = new ArrayList<>(); private List disconnectionListeners = new ArrayList<>(); + private ConnectionErrorListener connectionErrorListener = null; private Thread thread; private Socket socket; @@ -183,6 +189,18 @@ public class ClientToServerThread implements Runnable { } } + private void handleConnectionError(String message){ + if (connectionErrorListener != null){ + connectionErrorListener.notifyConnectionError(message); + } + + try { + this.socket.close(); + } catch (IOException e) { + logger.error("Couldn't close socket"); + } + } + /** * Sends a request to the server asking for a source ID */ @@ -212,6 +230,7 @@ public class ClientToServerThread implements Runnable { return; } + logger.error("Server Denied Connection, Exiting"); final String alertErrorText; @@ -222,6 +241,7 @@ public class ClientToServerThread implements Runnable { else{ alertErrorText = "Could not connect to server"; } + handleConnectionError("Server no longer available."); notifyDisconnectListeners(alertErrorText); closeSocket(); } @@ -351,6 +371,12 @@ public class ClientToServerThread implements Runnable { } } + public void setConnectionErrorListener(ConnectionErrorListener listener){ + synchronized (this){ + connectionErrorListener = listener; + } + } + private int readByte() throws ByteReadException { int currentByte = -1; try { @@ -365,6 +391,7 @@ public class ClientToServerThread implements Runnable { notifyDisconnectListeners("Cannot read from server."); closeSocket(); logger.warn("InputStream reach end of stream", 1); + handleConnectionError("Could not connect to server. Server is no longer available."); } return currentByte; } diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index bfcb599f..58ebc400 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -119,13 +119,23 @@ public class GameClient { ViewManager.getInstance().setProperty("serverName", regattaData.getRegattaName()); ViewManager.getInstance().setProperty("mapName", regattaData.getCourseName()); + getServerThread().setConnectionErrorListener((eMessage) -> { + ViewManager.getInstance().showErrorSnackBar(eMessage); + destroyClientToServerThread(); + }); + this.lobbyController = ViewManager.getInstance().goToLobby(true); } catch (IOException ioe) { - ViewManager.getInstance().showErrorSnackBar("Unable to find server"); + ViewManager.getInstance().showErrorSnackBar("There are no servers currently available."); } } + private void destroyClientToServerThread() { + socketThread.closeSocket(); + socketThread = null; + } + /** * Connect to a game as the host at the given address and starts the visualiser. * @param ipAddress IP to connect to. @@ -224,7 +234,6 @@ public class GameClient { break; case RACE_XML: - System.out.println("HEY I GOT A RACE MANG AND I AM CLIENT " + ((Boolean) (server==null)).toString()); RaceXMLData raceXMLData = XMLParser.parseRace( StreamParser.extractXmlMessage(packet) ); diff --git a/src/main/java/seng302/visualiser/MapMaker.java b/src/main/java/seng302/visualiser/MapMaker.java index 9425bf0a..5eeb73e1 100644 --- a/src/main/java/seng302/visualiser/MapMaker.java +++ b/src/main/java/seng302/visualiser/MapMaker.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javafx.scene.Node; import javafx.util.Pair; @@ -34,6 +35,8 @@ public class MapMaker { private int index = 0; private XMLGenerator xmlGenerator = new XMLGenerator(); + private List maps = new ArrayList<>(Arrays.asList("default.xml", "horseshoe.xml")); + public static MapMaker getInstance() { if (instance == null) { instance = new MapMaker(); @@ -42,46 +45,49 @@ public class MapMaker { } private MapMaker() { - File dir = new File(MapMaker.class.getResource("/maps/").getPath()); - File[] directoryListing = dir.listFiles(); - if (directoryListing != null) { - for (File child : directoryListing) { - Pair regattaRace = XMLParser.parseRaceDef( - child.getAbsolutePath(), "", 1, null, false - ); - filePaths.add(child.getAbsolutePath()); - RegattaXMLTemplate regattaTemplate = regattaRace.getKey(); - regattas.add(new RegattaXMLData( + for (String mapPath : maps){ + String path = ("/maps/" + mapPath); + + Pair regattaRace = XMLParser.parseRaceDef( + path, "", 1, null, false + ); + + RegattaXMLTemplate regattaTemplate = regattaRace.getKey(); + + filePaths.add(path); + + regattas.add(new RegattaXMLData( regattaTemplate.getRegattaId(), regattaTemplate.getName(), regattaTemplate.getCourseName(), regattaTemplate.getLatitude(), regattaTemplate.getLongitude(), regattaTemplate.getUtcOffset() - )); + )); - RaceXMLTemplate raceTemplate = regattaRace.getValue(); - xmlGenerator.setRaceTemplate(raceTemplate); - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db; - Document doc = null; - try { - db = dbf.newDocumentBuilder(); - doc = db.parse(new InputSource(new StringReader(xmlGenerator.getRaceAsXml()))); - } catch (ParserConfigurationException | IOException | SAXException e) { - e.printStackTrace(); - } + RaceXMLTemplate raceTemplate = regattaRace.getValue(); + xmlGenerator.setRaceTemplate(raceTemplate); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db; + Document doc = null; + try { + db = dbf.newDocumentBuilder(); + doc = db.parse(new InputSource(new StringReader(xmlGenerator.getRaceAsXml()))); + } catch (ParserConfigurationException | IOException | SAXException e) { + e.printStackTrace(); + } - RaceXMLData race = XMLParser.parseRace(doc); - maxPlayers.add(XMLParser.getMaxPlayers(doc)); + RaceXMLData race = XMLParser.parseRace(doc); + maxPlayers.add(XMLParser.getMaxPlayers(doc)); - mapPreviews.add(new MapPreview( + mapPreviews.add(new MapPreview( new ArrayList<>(race.getCompoundMarks().values()), race.getMarkSequence(), race.getCourseLimit() - )); - races.add(race); - } + )); + + races.add(race); } + } public void next() { diff --git a/src/main/java/seng302/visualiser/controllers/ViewManager.java b/src/main/java/seng302/visualiser/controllers/ViewManager.java index 45dfb069..c82bbaa0 100644 --- a/src/main/java/seng302/visualiser/controllers/ViewManager.java +++ b/src/main/java/seng302/visualiser/controllers/ViewManager.java @@ -272,6 +272,8 @@ public class ViewManager { } private void closeAll() { + if (stage!= null) stage.close(); + try { ServerAdvertiser.getInstance().unregister(); } catch (IOException e1) { diff --git a/src/main/java/seng302/visualiser/controllers/dialogs/DirectConnectController.java b/src/main/java/seng302/visualiser/controllers/dialogs/DirectConnectController.java index 3644702d..2ec15882 100644 --- a/src/main/java/seng302/visualiser/controllers/dialogs/DirectConnectController.java +++ b/src/main/java/seng302/visualiser/controllers/dialogs/DirectConnectController.java @@ -50,6 +50,15 @@ public class DirectConnectController implements Initializable { */ private void connectToServer() { //TODO fix port number validation + + try{ + Integer.parseInt(portNumber.getText()); + } + catch (NumberFormatException e){ + ViewManager.getInstance().showErrorSnackBar("You need to enter a valid port number"); + return; + } + ViewManager.getInstance().getGameClient() .runAsClient(serverAddress.getText(), Integer.parseInt(portNumber.getText())); } diff --git a/src/main/resources/css/dialogs/Snackbar.css b/src/main/resources/css/dialogs/Snackbar.css index 0fbe23b2..2127abc8 100644 --- a/src/main/resources/css/dialogs/Snackbar.css +++ b/src/main/resources/css/dialogs/Snackbar.css @@ -1,4 +1,4 @@ /* a separate file to dynamically change snackbar's color */ .jfx-snackbar-toast { - -fx-text-fill: red !important; + -fx-text-fill: black !important; } \ No newline at end of file