diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index 870369dc..f97a3ef8 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -80,6 +80,14 @@ public class App extends Application { ViewManager.getInstance().initialStartView(primaryStage); } + private static void runDiscoveryServer(){ + try{ + new DiscoveryServer(); + } + catch (Exception e){ + runDiscoveryServer(); + } + } public static void main(String[] args) throws Exception { try { @@ -92,7 +100,7 @@ public class App extends Application { launch(args); } else{ - new DiscoveryServer(); + runDiscoveryServer(); } } } diff --git a/src/main/java/seng302/discoveryServer/DiscoveryServerClient.java b/src/main/java/seng302/discoveryServer/DiscoveryServerClient.java index 0081b767..79df1c2f 100644 --- a/src/main/java/seng302/discoveryServer/DiscoveryServerClient.java +++ b/src/main/java/seng302/discoveryServer/DiscoveryServerClient.java @@ -2,15 +2,19 @@ package seng302.discoveryServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import seng302.discoveryServer.util.ServerListing; +import seng302.discoveryServer.util.ServerRepoStreamParser; import seng302.gameServer.messages.Message; import seng302.gameServer.messages.RoomCodeRequest; import seng302.gameServer.messages.ServerRegistrationMessage; import seng302.model.stream.packets.PacketType; -import seng302.discoveryServer.util.ServerListing; -import seng302.discoveryServer.util.ServerRepoStreamParser; +import seng302.visualiser.controllers.ViewManager; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; import java.net.Socket; +import java.net.URL; import java.util.Timer; import java.util.TimerTask; @@ -20,9 +24,28 @@ public class DiscoveryServerClient { private static String roomCode = null; private Timer serverListingUpdateTimer; private Logger logger = LoggerFactory.getLogger(DiscoveryServerClient.class); + private String ip = ""; + private Boolean isInInvalidState = false; public DiscoveryServerClient() { + try { + ip = getInetIpAddr(); + } catch (Exception e) { + failError(); + } + } + public String getInetIp(){ + return ip; + } + + private void failError() { + isInInvalidState = true; + ViewManager.getInstance().showErrorSnackBar("You do not appear to be able to connect to the internet. Matchmaking will be unavailable."); + } + + public boolean didFail(){ + return isInInvalidState; } /** @@ -30,6 +53,8 @@ public class DiscoveryServerClient { * @param serverListing The listing to register */ public void register(ServerListing serverListing){ + if (isInInvalidState) return; + if (serverListingUpdateTimer != null){ serverListingUpdateTimer.cancel(); serverListingUpdateTimer = null; @@ -53,7 +78,8 @@ public class DiscoveryServerClient { * Stop updating the server registration updates */ public void unregister(){ - serverListingUpdateTimer.cancel(); + if (serverListingUpdateTimer != null) + serverListingUpdateTimer.cancel(); } /** @@ -143,5 +169,27 @@ public class DiscoveryServerClient { public static String getRoomCode(){ return roomCode; } + + public static String getInetIpAddr() throws Exception { + URL myIp = new URL("http://checkip.amazonaws.com"); + BufferedReader in = null; + try { + in = new BufferedReader(new InputStreamReader( + myIp.openStream())); + String ip = in.readLine(); + return ip; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + + } diff --git a/src/main/java/seng302/discoveryServer/util/ServerTable.java b/src/main/java/seng302/discoveryServer/util/ServerTable.java index ba6e1101..395a4e89 100644 --- a/src/main/java/seng302/discoveryServer/util/ServerTable.java +++ b/src/main/java/seng302/discoveryServer/util/ServerTable.java @@ -48,7 +48,7 @@ public class ServerTable { updateTtlForServer(server); return; } - logger.debug("Added new server - " + server.getServerName()); + logger.debug("Added new server - " + server.getServerName() + " at address: " + server.getAddress() + ":" + server.getPortNumber()); servers.add(server); } diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 677659ec..d2b35222 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -1,11 +1,5 @@ package seng302.gameServer; -import java.io.IOException; -import java.net.ServerSocket; -import java.util.ArrayList; -import java.util.Random; -import java.util.Timer; -import java.util.TimerTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import seng302.gameServer.messages.Message; @@ -18,6 +12,13 @@ import seng302.model.stream.xml.parser.RaceXMLData; import seng302.model.stream.xml.parser.RegattaXMLData; import seng302.utilities.GeoUtility; +import java.io.IOException; +import java.net.ServerSocket; +import java.util.ArrayList; +import java.util.Random; +import java.util.Timer; +import java.util.TimerTask; + /** * A class describing the overall server, which creates and collects server threads for each client * Created by wmu16 on 13/07/17. @@ -158,6 +159,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { } private void sendSetupMessages() { + MessageFactory.updateBoats(new ArrayList<>(GameState.getYachts().values())); + broadcastMessage(MessageFactory.getRaceXML()); broadcastMessage(MessageFactory.getRegattaXML()); broadcastMessage(MessageFactory.getBoatXML()); @@ -253,16 +256,26 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { } }); } else { - serverToClientThread.addConnectionListener(this::sendSetupMessages); - MessageFactory.updateBoats(new ArrayList<>(GameState.getYachts().values())); + //serverToClientThread.addConnectionListener(this::sendSetupMessages); } serverToClientThreads.add(serverToClientThread); - serverToClientThread.addDisconnectListener(this::clientDisconnected); + try { ServerAdvertiser.getInstance().setNumberOfPlayers(GameState.getNumberOfPlayers()); } catch (IOException e) { logger.warn("Couldn't update advertisement"); } + + while (regattaXMLData == null && raceXMLData == null){ + try { + Thread.sleep(50); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + serverToClientThread.addConnectionListener(this::sendSetupMessages); + serverToClientThread.addDisconnectListener(this::clientDisconnected); } /** @@ -283,6 +296,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { serverToClientThread.sendSetupMessages(); } } + serverToClientThreads.remove(closedConnection); try { diff --git a/src/main/java/seng302/gameServer/MessageFactory.java b/src/main/java/seng302/gameServer/MessageFactory.java index 619268af..254b6e22 100644 --- a/src/main/java/seng302/gameServer/MessageFactory.java +++ b/src/main/java/seng302/gameServer/MessageFactory.java @@ -1,18 +1,6 @@ package seng302.gameServer; -import java.util.ArrayList; -import java.util.List; -import seng302.gameServer.messages.BoatLocationMessage; -import seng302.gameServer.messages.BoatSubMessage; -import seng302.gameServer.messages.RaceStartNotificationType; -import seng302.gameServer.messages.RaceStartStatusMessage; -import seng302.gameServer.messages.RaceStatus; -import seng302.gameServer.messages.RaceStatusMessage; -import seng302.gameServer.messages.RaceType; -import seng302.gameServer.messages.XMLMessage; -import seng302.gameServer.messages.XMLMessageSubType; -import seng302.gameServer.messages.YachtEventCodeMessage; -import seng302.gameServer.messages.YachtEventType; +import seng302.gameServer.messages.*; import seng302.model.Player; import seng302.model.ServerYacht; import seng302.model.stream.xml.generator.RaceXMLTemplate; @@ -20,9 +8,11 @@ import seng302.model.stream.xml.generator.RegattaXMLTemplate; import seng302.model.stream.xml.parser.RaceXMLData; import seng302.model.stream.xml.parser.RegattaXMLData; import seng302.model.token.Token; -import seng302.model.token.TokenType; import seng302.utilities.XMLGenerator; +import java.util.ArrayList; +import java.util.List; + /** * A Class for interfacing between the data we have in the GameState to the messages we need to send * through the MainServerThread. diff --git a/src/main/java/seng302/gameServer/ServerAdvertiser.java b/src/main/java/seng302/gameServer/ServerAdvertiser.java index 479ffca6..a98ee0f0 100644 --- a/src/main/java/seng302/gameServer/ServerAdvertiser.java +++ b/src/main/java/seng302/gameServer/ServerAdvertiser.java @@ -1,7 +1,7 @@ package seng302.gameServer; -import seng302.discoveryServer.util.ServerListing; import seng302.discoveryServer.DiscoveryServerClient; +import seng302.discoveryServer.util.ServerListing; import javax.jmdns.JmDNS; import javax.jmdns.ServiceInfo; @@ -133,7 +133,7 @@ public class ServerAdvertiser { } }, 0); - ServerListing serverListing = new ServerListing(serverName, props.get("map"), getLocalHostIp(), portNo, Integer.parseInt(props.get("capacity"))); + ServerListing serverListing = new ServerListing(serverName, props.get("map"), new DiscoveryServerClient().getInetIp(), portNo, Integer.parseInt(props.get("capacity"))); repositoryClient.register(serverListing); } diff --git a/src/main/java/seng302/gameServer/ServerToClientThread.java b/src/main/java/seng302/gameServer/ServerToClientThread.java index 0df0e0fc..f83eb540 100644 --- a/src/main/java/seng302/gameServer/ServerToClientThread.java +++ b/src/main/java/seng302/gameServer/ServerToClientThread.java @@ -1,6 +1,21 @@ package seng302.gameServer; +import javafx.beans.property.SimpleObjectProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import seng302.gameServer.messages.*; +import seng302.model.Player; +import seng302.model.ServerYacht; +import seng302.model.stream.packets.PacketType; +import seng302.model.stream.packets.StreamPacket; +import seng302.model.stream.xml.parser.RaceXMLData; +import seng302.model.stream.xml.parser.RegattaXMLData; +import seng302.utilities.StreamParser; +import seng302.utilities.XMLGenerator; +import seng302.utilities.XMLParser; +import seng302.visualiser.fxObjects.assets_3D.BoatMeshType; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -12,26 +27,6 @@ import java.util.Arrays; import java.util.List; import java.util.zip.CRC32; import java.util.zip.Checksum; -import javafx.beans.property.SimpleObjectProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import seng302.gameServer.messages.BoatAction; -import seng302.gameServer.messages.ChatterMessage; -import seng302.gameServer.messages.ClientType; -import seng302.gameServer.messages.CustomizeRequestType; -import seng302.gameServer.messages.Message; -import seng302.gameServer.messages.RegistrationResponseMessage; -import seng302.gameServer.messages.RegistrationResponseStatus; -import seng302.model.Player; -import seng302.model.ServerYacht; -import seng302.model.stream.packets.PacketType; -import seng302.model.stream.packets.StreamPacket; -import seng302.model.stream.xml.parser.RaceXMLData; -import seng302.model.stream.xml.parser.RegattaXMLData; -import seng302.utilities.StreamParser; -import seng302.utilities.XMLGenerator; -import seng302.visualiser.fxObjects.assets_3D.BoatMeshType; -import seng302.utilities.XMLParser; /** * A class describing a single connection to a Client for the purposes of sending and receiving on @@ -196,6 +191,7 @@ public class ServerToClientThread implements Runnable { // TODO: 17/08/2017 ajm412: Send a response packet here, not really necessary until we do shapes. break; case RACE_XML: + System.out.println("Got raceXML from client"); raceXMLProperty.set( XMLParser.parseRace( StreamParser.extractXmlMessage(packet) diff --git a/src/main/java/seng302/visualiser/ClientToServerThread.java b/src/main/java/seng302/visualiser/ClientToServerThread.java index f7d7695b..38120aa1 100644 --- a/src/main/java/seng302/visualiser/ClientToServerThread.java +++ b/src/main/java/seng302/visualiser/ClientToServerThread.java @@ -1,36 +1,22 @@ package seng302.visualiser; +import javafx.util.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import seng302.gameServer.messages.*; +import seng302.model.stream.packets.PacketType; +import seng302.model.stream.packets.StreamPacket; +import seng302.utilities.XMLParser; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Queue; -import java.util.Timer; -import java.util.TimerTask; +import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.zip.CRC32; import java.util.zip.Checksum; -import javafx.util.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import seng302.gameServer.messages.BoatAction; -import seng302.gameServer.messages.BoatActionMessage; -import seng302.gameServer.messages.ChatterMessage; -import seng302.gameServer.messages.ClientType; -import seng302.gameServer.messages.CustomizeRequestMessage; -import seng302.gameServer.messages.CustomizeRequestType; -import seng302.gameServer.messages.Message; -import seng302.gameServer.messages.RegistrationRequestMessage; -import seng302.gameServer.messages.RegistrationResponseStatus; -import seng302.gameServer.messages.XMLMessage; -import seng302.gameServer.messages.XMLMessageSubType; -import seng302.model.stream.packets.PacketType; -import seng302.model.stream.packets.StreamPacket; -import seng302.utilities.XMLParser; /** * A class describing a single connection to a Server for the purposes of sending and receiving on @@ -137,8 +123,10 @@ public class ClientToServerThread implements Runnable { else { if (clientId == -1) continue; // Do not continue if not registered streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload)); - for (ClientSocketListener csl : listeners) - csl.newPacket(); + synchronized (this) { + for (ClientSocketListener csl : listeners) + csl.newPacket(); + } } } } else { @@ -322,7 +310,9 @@ public class ClientToServerThread implements Runnable { } public void addStreamObserver (ClientSocketListener streamListener) { - listeners.add(streamListener); + synchronized (this){ + listeners.add(streamListener); + } } public void removeStreamObserver (ClientSocketListener streamListener) { @@ -330,11 +320,15 @@ public class ClientToServerThread implements Runnable { } public void addDisconnectionListener (DisconnectedFromHostListener listener) { - disconnectionListeners.add(listener); + synchronized (this){ + disconnectionListeners.add(listener); + } } public void removeDisconnectionListener (DisconnectedFromHostListener listener) { - disconnectionListeners.remove(listener); + synchronized (this){ + disconnectionListeners.remove(listener); + } } private int readByte() throws ByteReadException { diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index a7f8d5dc..57c2ff38 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -1,15 +1,5 @@ package seng302.visualiser; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -48,6 +38,12 @@ import seng302.visualiser.controllers.LobbyController; import seng302.visualiser.controllers.RaceViewController; import seng302.visualiser.controllers.ViewManager; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.*; + /** * This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated * with a JavaFX Pane to insert itself into. @@ -114,7 +110,7 @@ public class GameClient { this.lobbyController = ViewManager.getInstance().goToLobby(true); } catch (IOException ioe) { - showConnectionError("Unable to find server"); + ViewManager.getInstance().showErrorSnackBar("Unable to find server"); } } diff --git a/src/main/java/seng302/visualiser/controllers/LobbyController.java b/src/main/java/seng302/visualiser/controllers/LobbyController.java index 9f9548f7..610ce041 100644 --- a/src/main/java/seng302/visualiser/controllers/LobbyController.java +++ b/src/main/java/seng302/visualiser/controllers/LobbyController.java @@ -2,12 +2,6 @@ package seng302.visualiser.controllers; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXDialog; -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 javafx.application.Platform; import javafx.collections.ListChangeListener; import javafx.fxml.FXML; @@ -19,6 +13,7 @@ import javafx.scene.layout.AnchorPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; +import seng302.discoveryServer.DiscoveryServerClient; import seng302.gameServer.GameStages; import seng302.gameServer.GameState; import seng302.model.ClientYacht; @@ -28,12 +23,17 @@ import seng302.model.RaceState; import seng302.model.mark.CompoundMark; import seng302.model.mark.Corner; import seng302.model.stream.xml.parser.RaceXMLData; -import seng302.discoveryServer.DiscoveryServerClient; import seng302.utilities.Sounds; import seng302.visualiser.MapPreview; import seng302.visualiser.controllers.cells.PlayerCell; import seng302.visualiser.controllers.dialogs.BoatCustomizeController; -import seng302.visualiser.controllers.dialogs.DirectConnectController; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; public class LobbyController implements Initializable { @@ -91,6 +91,17 @@ public class LobbyController implements Initializable { serverName.setText(ViewManager.getInstance().getProperty("serverName")); mapName.setText(ViewManager.getInstance().getProperty("mapName")); + int tries = 0; + + while (DiscoveryServerClient.getRoomCode() == null && tries <= 10){ + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + tries ++; + } + if (DiscoveryServerClient.getRoomCode() != null){ setRoomCode(DiscoveryServerClient.getRoomCode()); } diff --git a/src/main/java/seng302/visualiser/controllers/ServerListController.java b/src/main/java/seng302/visualiser/controllers/ServerListController.java index aa82dc81..f7245ffe 100644 --- a/src/main/java/seng302/visualiser/controllers/ServerListController.java +++ b/src/main/java/seng302/visualiser/controllers/ServerListController.java @@ -5,17 +5,11 @@ import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXDialog.DialogTransition; import com.jfoenix.controls.JFXTextField; import com.jfoenix.validation.RequiredFieldValidator; -import java.io.IOException; -import java.net.URL; -import java.util.Arrays; -import java.util.List; -import java.util.ResourceBundle; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.geometry.Pos; -import javafx.scene.control.Alert; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.input.KeyCode; @@ -23,19 +17,21 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import seng302.discoveryServer.DiscoveryServer; -import seng302.gameServer.ServerDescription; -import seng302.discoveryServer.util.ServerListing; import seng302.discoveryServer.DiscoveryServerClient; -import seng302.gameServer.messages.RoomCodeRequest; +import seng302.discoveryServer.util.ServerListing; +import seng302.gameServer.ServerDescription; +import seng302.gameServer.messages.ServerRegistrationMessage; import seng302.utilities.Sounds; import seng302.visualiser.ServerListener; import seng302.visualiser.ServerListenerDelegate; import seng302.visualiser.controllers.cells.ServerCell; import seng302.visualiser.controllers.dialogs.DirectConnectController; -import seng302.visualiser.validators.HostNameFieldValidator; -import seng302.visualiser.validators.NumberRangeValidator; -import seng302.visualiser.validators.ValidationTools; + +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.List; +import java.util.ResourceBundle; public class ServerListController implements Initializable, ServerListenerDelegate { @@ -90,6 +86,8 @@ public class ServerListController implements Initializable, ServerListenerDelega Sounds.playButtonClick(); }); + directConnectDialog = createDirectConnectDialog(); + for (JFXTextField textField : Arrays.asList(roomNumber)) { // Event for pressing enter to submit direct connection textField.setOnKeyPressed(event -> { @@ -105,26 +103,26 @@ public class ServerListController implements Initializable, ServerListenerDelega } autoSelectGame.setOnMouseReleased(e -> { - try { - ServerListing listing = new DiscoveryServerClient().getRandomServer(); + ServerListing listing; + DiscoveryServerClient client = new DiscoveryServerClient(); - if (listing == null){ - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Error finding game"); - alert.setContentText("No servers are up"); - alert.showAndWait(); - } - else{ - ViewManager.getInstance().getGameClient().runAsClient(listing.getAddress(), listing.getPortNumber()); - } + try { + listing = client.getRandomServer(); } catch (Exception e1) { - e1.printStackTrace(); - logger.error("Error getting listing"); - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Error finding game"); - alert.setContentText("Couldn't contact matchmaking server"); - alert.showAndWait(); + ViewManager.getInstance().showErrorSnackBar("Unable to connect to matchmaking server. Are you connected to the internet?"); + return; } + + if (client.didFail()){ + return; + } + + if (listing == null || listing.equals(ServerRegistrationMessage.getEmptyRegistration())) { + ViewManager.getInstance().showErrorSnackBar("There are currently no servers available for you to connect to."); + return; + } + + ViewManager.getInstance().getGameClient().runAsClient(listing.getAddress(), listing.getPortNumber()); }); /* @@ -186,9 +184,6 @@ public class ServerListController implements Initializable, ServerListenerDelega e.printStackTrace(); logger.warn("Could not create Server Creation Dialog."); } - - directConnectDialog = createDirectConnectDialog(); - }); } @@ -235,20 +230,30 @@ public class ServerListController implements Initializable, ServerListenerDelega } private void connectToRoomCode(String roomCode){ + DiscoveryServerClient client = new DiscoveryServerClient(); + ServerListing serverListing; + + if (client.didFail()){ + return; + } + + try { + serverListing = client.getServerForRoomCode(roomCode); + } catch (Exception e) { + ViewManager.getInstance().showErrorSnackBar("Error connecting to matchmaking server. Please try again later."); + return; + } + + if (serverListing == null || serverListing.equals(new ServerListing("","","", 0, 0))){ + ViewManager.getInstance().showErrorSnackBar("No servers could be found with that room code."); + return; + } + try { - ServerListing serverListing = new DiscoveryServerClient().getServerForRoomCode(roomCode); ViewManager.getInstance().getGameClient().runAsClient(serverListing.getAddress(), serverListing.getPortNumber()); } - catch (java.net.ConnectException e){ - //TODO Add proper dialog - logger.warn("Couldn't connect to discovery server"); - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Couldn't connect to discovery server"); - alert.setContentText("Couldn't connect to " + DiscoveryServer.DISCOVERY_SERVER); - alert.showAndWait(); - } catch (Exception e) { - logger.warn("Error discovering room code"); + ViewManager.getInstance().showErrorSnackBar("Error connecting to matchmaking service."); } } diff --git a/src/main/java/seng302/visualiser/controllers/ViewManager.java b/src/main/java/seng302/visualiser/controllers/ViewManager.java index 26d5dc8b..edc288e1 100644 --- a/src/main/java/seng302/visualiser/controllers/ViewManager.java +++ b/src/main/java/seng302/visualiser/controllers/ViewManager.java @@ -6,16 +6,10 @@ import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXDialog.DialogTransition; import com.jfoenix.controls.JFXSnackbar; import com.jfoenix.svg.SVGGlyph; -import java.io.IOException; -import java.util.HashMap; import javafx.application.Platform; import javafx.collections.ObservableList; import javafx.fxml.FXMLLoader; -import javafx.scene.Cursor; -import javafx.scene.Node; -import javafx.scene.Parent; -import javafx.scene.Scene; -import javafx.scene.SceneAntialiasing; +import javafx.scene.*; import javafx.scene.image.Image; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; @@ -28,6 +22,9 @@ import seng302.utilities.Sounds; import seng302.visualiser.GameClient; import seng302.visualiser.controllers.dialogs.KeyBindingDialogController; +import java.io.IOException; +import java.util.HashMap; + public class ViewManager { private static ViewManager instance; @@ -369,6 +366,14 @@ public class ViewManager { return loader.getController(); } + public void showErrorSnackBar(String msg){ + decorator.getStylesheets() + .add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm()); + + JFXSnackbar bar = new JFXSnackbar(decorator); + bar.enqueue(new JFXSnackbar.SnackbarEvent(msg)); + } + public Stage getStage() { return stage; }