diff --git a/src/main/java/seng302/client/ClientPacketParser.java b/src/main/java/seng302/client/ClientPacketParser.java index 2cae4857..4a62b8d1 100644 --- a/src/main/java/seng302/client/ClientPacketParser.java +++ b/src/main/java/seng302/client/ClientPacketParser.java @@ -36,8 +36,6 @@ public class ClientPacketParser { public static ConcurrentHashMap> markLocations = new ConcurrentHashMap<>(); public static ConcurrentHashMap> boatLocations = new ConcurrentHashMap<>(); - private String threadName; - private Thread t; private static boolean newRaceXmlReceived = false; private static boolean raceStarted = false; private static XMLParser xmlObject; @@ -48,11 +46,10 @@ public class ClientPacketParser { private static Map boatsPos = new ConcurrentSkipListMap<>(); private static double windDirection = 0; private static Double windSpeed = 0d; - private static Long currentTimeLong; + private static Long currentTimeLong; private static String currentTimeString; private static boolean appRunning; - //CONVERSION CONSTANTS private static final Double MS_TO_KNOTS = 1.94384; @@ -121,7 +118,7 @@ public class ClientPacketParser { */ private static void extractHeartBeat(StreamPacket packet) { long heartbeat = bytesToLong(packet.getPayload()); - System.out.println("heartbeat = " + heartbeat); + System.out.println("[CLIENT] Received heartbeat = " + heartbeat); } private static String getTimeZoneString() { @@ -200,6 +197,9 @@ public class ClientPacketParser { Long estTimeAtFinish = bytesToLong( Arrays.copyOfRange(payload, 38 + (i * 20), 44 + (i * 20))); boat.setEstimateTimeAtFinish(estTimeAtFinish); + +// FOR DEBUGGING: + // boatsPos.put(estTimeAtFinish, boat); // String boatStatus = "SourceID: " + boatStatusSourceID; // boatStatus += "\nBoat Status: " + (int)payload[28 + (i * 20)]; diff --git a/src/main/java/seng302/client/ClientState.java b/src/main/java/seng302/client/ClientState.java new file mode 100644 index 00000000..ab870beb --- /dev/null +++ b/src/main/java/seng302/client/ClientState.java @@ -0,0 +1,46 @@ +package seng302.client; + +import com.sun.org.apache.xpath.internal.operations.Bool; + +/** + * Created by zyt10 on 21/07/17. + */ +public class ClientState { + + private static String hostIp = ""; + private static Boolean isHost = false; + private static Boolean raceStarted = false; + private static Boolean connectedToHost = false; + + public static String getHostIp() { + return hostIp; + } + + public static void setHostIp(String hostIp) { + ClientState.hostIp = hostIp; + } + + public static Boolean isHost() { + return isHost; + } + + public static void setHost(Boolean isHost) { + ClientState.isHost = isHost; + } + + public static Boolean isRaceStarted() { + return raceStarted; + } + + public static void setRaceStarted(Boolean raceStarted) { + ClientState.raceStarted = raceStarted; + } + + public static Boolean isConnectedToHost() { + return connectedToHost; + } + + public static void setConnectedToHost(Boolean connectedToHost) { + ClientState.connectedToHost = connectedToHost; + } +} diff --git a/src/main/java/seng302/client/ClientStateQueryingRunnable.java b/src/main/java/seng302/client/ClientStateQueryingRunnable.java new file mode 100644 index 00000000..d2fb9220 --- /dev/null +++ b/src/main/java/seng302/client/ClientStateQueryingRunnable.java @@ -0,0 +1,28 @@ +package seng302.client; + +import java.util.List; +import java.util.Observable; + +/** + * Created by zyt10 on 21/07/17. + */ +public class ClientStateQueryingRunnable extends Observable implements Runnable { + + private Boolean terminate = false; + + public ClientStateQueryingRunnable() {} + + @Override + public void run() { + while(!terminate) { + if (ClientState.isRaceStarted() && ClientState.isConnectedToHost()) { + setChanged(); + notifyObservers(); + } + } + } + + public void terminate() { + terminate = true; + } +} diff --git a/src/main/java/seng302/client/ClientToServerThread.java b/src/main/java/seng302/client/ClientToServerThread.java index e2c1cff9..628e07f5 100644 --- a/src/main/java/seng302/client/ClientToServerThread.java +++ b/src/main/java/seng302/client/ClientToServerThread.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; +import java.net.UnknownHostException; import java.util.zip.CRC32; import java.util.zip.Checksum; @@ -25,14 +26,10 @@ public class ClientToServerThread extends Thread { private Boolean updateClient = true; private ByteArrayOutputStream crcBuffer; - public ClientToServerThread(String ipAddress, Integer portNumber){ - try { + public ClientToServerThread(String ipAddress, Integer portNumber) throws Exception{ socket = new Socket(ipAddress, portNumber); is = socket.getInputStream(); os = socket.getOutputStream(); - } catch (IOException e) { - e.printStackTrace(); - } } @@ -46,7 +43,7 @@ public class ClientToServerThread extends Thread { int sync1; int sync2; // TODO: 14/07/17 wmu16 - Work out how to fix this while loop - while(true) { + while(ClientState.isConnectedToHost()) { try { //Perform a write if it is time to as delegated by the MainServerThread if (updateClient) { diff --git a/src/main/java/seng302/controllers/LobbyController.java b/src/main/java/seng302/controllers/LobbyController.java index 565812cc..f63b8d68 100644 --- a/src/main/java/seng302/controllers/LobbyController.java +++ b/src/main/java/seng302/controllers/LobbyController.java @@ -6,7 +6,10 @@ import java.net.InetAddress; import java.net.NetworkInterface; import java.net.URL; import java.util.Enumeration; +import java.util.Observable; +import java.util.Observer; import java.util.ResourceBundle; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; @@ -17,6 +20,7 @@ import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.scene.text.Text; +import seng302.client.ClientStateQueryingRunnable; import seng302.gameServer.GameStages; import seng302.gameServer.GameState; @@ -24,7 +28,7 @@ import seng302.gameServer.GameState; * A class describing the actions of the lobby screen * Created by wmu16 on 10/07/17. */ -public class LobbyController implements Initializable{ +public class LobbyController implements Initializable, Observer{ @FXML private ListView competitorsListView; @@ -34,6 +38,7 @@ public class LobbyController implements Initializable{ private Text lobbyIpText; private static ObservableList competitors; + private ClientStateQueryingRunnable clientStateQueryingRunnable; private void setContentPane(String jfxUrl) { try { @@ -53,11 +58,27 @@ public class LobbyController implements Initializable{ @Override public void initialize(URL location, ResourceBundle resources) { lobbyIpText.setText("Lobby Host IP: " + getLocalHostIp()); - } - - public void initialize() { competitors = FXCollections.observableArrayList(); competitorsListView.setItems(competitors); + + // set up client state query thread, so that when it receives the race-started packet + // it can switch to the race view + ClientStateQueryingRunnable clientStateQueryingRunnable = new ClientStateQueryingRunnable(); + clientStateQueryingRunnable.addObserver(this); + Thread clientStateQueryingThread = new Thread(clientStateQueryingRunnable, "Client State querying thread"); + clientStateQueryingThread.setDaemon(true); + clientStateQueryingThread.start(); + } + + @Override + public void update(Observable o, Object arg) { + Platform.runLater(new Runnable() { + @Override + public void run() { + switchToRaceView(); + clientStateQueryingRunnable.terminate(); + } + }); } private String getLocalHostIp() { @@ -94,16 +115,16 @@ public class LobbyController implements Initializable{ public void leaveLobbyButtonPressed() { // TODO: 10/07/17 wmu16 - Finish function! setContentPane("/views/StartScreenView.fxml"); - System.out.println("Leaving lobby!"); GameState.setCurrentStage(GameStages.CANCELLED); // TODO: 20/07/17 wmu16 - Implement some way of terminating the game } - @FXML public void readyButtonPressed() { GameState.setCurrentStage(GameStages.RACING); - setContentPane("/views/RaceView.fxml"); + } + private void switchToRaceView() { + setContentPane("/views/RaceView.fxml"); } } diff --git a/src/main/java/seng302/controllers/RaceViewController.java b/src/main/java/seng302/controllers/RaceViewController.java index 0fa8b17c..eb49f09c 100644 --- a/src/main/java/seng302/controllers/RaceViewController.java +++ b/src/main/java/seng302/controllers/RaceViewController.java @@ -96,12 +96,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel startingBoats = new ArrayList<>(ClientPacketParser.getBoats().values()); includedCanvasController.setup(this); - includedCanvasController.initializeCanvas(); +// includedCanvasController.initializeCanvas(); initializeUpdateTimer(); initialiseFPSCheckBox(); initialiseAnnotationSlider(); initialiseBoatSelectionComboBox(); - includedCanvasController.timer.start(); +// includedCanvasController.timer.start(); selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView()); } @@ -283,7 +283,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel event -> { updateRaceTime(); updateWindDirection(); - updateOrder(); +// updateOrder(); updateBoatSelectionComboBox(); }) ); diff --git a/src/main/java/seng302/controllers/StartScreenController.java b/src/main/java/seng302/controllers/StartScreenController.java index 6f9a094c..03c8c730 100644 --- a/src/main/java/seng302/controllers/StartScreenController.java +++ b/src/main/java/seng302/controllers/StartScreenController.java @@ -2,10 +2,13 @@ package seng302.controllers; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; import javafx.scene.control.TextField; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; +import seng302.client.ClientState; import seng302.client.ClientToServerThread; import seng302.gameServer.GameState; import seng302.gameServer.MainServerThread; @@ -23,6 +26,8 @@ public class StartScreenController { @FXML private TextField ipTextField; @FXML + private TextField portTextField; + @FXML private GridPane startScreen2; private Controller controller; @@ -68,26 +73,32 @@ public class StartScreenController { // new GameServerThread("Fuck you"); // get the lobby controller so that we can pass the game server thread to it setContentPane("/views/LobbyView.fxml"); - - } catch (UnknownHostException e) { - System.err.println("COULD NOT FIND YOUR IP ADDRESS!"); + } catch (Exception e) { + Alert alert = new Alert(AlertType.ERROR); + alert.setHeaderText("Cannot host"); + alert.setContentText("Oops, failed to host, try to restart."); + alert.showAndWait(); e.printStackTrace(); } - } - @FXML public void connectButtonPressed() { // TODO: 10/07/17 wmu16 - Finish function - String ipAddress = ipTextField.getText().trim().toLowerCase(); try { - ClientToServerThread clientToServerThread = new ClientToServerThread(ipAddress, 4950); + String ipAddress = ipTextField.getText().trim().toLowerCase(); + Integer port = Integer.valueOf(portTextField.getText().trim()); + + ClientToServerThread clientToServerThread = new ClientToServerThread(ipAddress, port); controller.setClientToServerThread(clientToServerThread); clientToServerThread.start(); + ClientState.setConnectedToHost(true); setContentPane("/views/LobbyView.fxml"); - } catch (Exception e){ - e.printStackTrace(); + } catch (Exception e) { + Alert alert = new Alert(AlertType.ERROR); + alert.setHeaderText("Cannot reach the host"); + alert.setContentText("Please check your host IP address."); + alert.showAndWait(); } } diff --git a/src/main/java/seng302/gameServer/GameState.java b/src/main/java/seng302/gameServer/GameState.java index 20aaaf4f..304fea55 100644 --- a/src/main/java/seng302/gameServer/GameState.java +++ b/src/main/java/seng302/gameServer/GameState.java @@ -1,5 +1,6 @@ package seng302.gameServer; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -28,6 +29,7 @@ public class GameState { public GameState(String hostIpAddress) { GameState.hostIpAddress = hostIpAddress; players = new ArrayList<>(); + yachts = new HashMap<>(); currentStage = GameStages.LOBBYING; isRaceStarted = false; //set this when game stage changes to prerace diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 5149eee5..fc7e1d07 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -32,7 +32,7 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl try { serverSocket = new ServerSocket(PORT); } catch (IOException e) { - System.out.println("IO error in server thread handler upon trying to make new server socket"); + serverLog("IO error in server thread handler upon trying to make new server socket", 0); } packetBuffer = new PriorityBlockingQueue<>(); @@ -73,7 +73,6 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl updateClients(); while (!packetBuffer.isEmpty()){ - System.out.println("WHATUPPP"); try { StreamPacket packet = packetBuffer.take(); ClientPacketParser.parsePacket(packet); @@ -83,9 +82,6 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl } } - System.out.println("WHOOPSIES"); - - // TODO: 14/07/17 wmu16 - Send out disconnect packet to clients try { serverSocket.close(); @@ -111,7 +107,6 @@ public class MainServerThread extends Thread implements PacketBufferDelegate, Cl @Override public boolean addToBuffer(StreamPacket streamPacket) { - System.out.println("HEY HI"); return packetBuffer.add(streamPacket); } diff --git a/src/main/java/seng302/gameServer/ServerToClientThread.java b/src/main/java/seng302/gameServer/ServerToClientThread.java index 14b98db8..483f40a8 100644 --- a/src/main/java/seng302/gameServer/ServerToClientThread.java +++ b/src/main/java/seng302/gameServer/ServerToClientThread.java @@ -50,7 +50,7 @@ public class ServerToClientThread extends Thread { GameState.addPlayer(new Player(socket)); Random rand = new Random(); sourceId = rand.nextInt(100000); - GameState.addYacht(sourceId, new Yacht("Kappa", "Kap", new GeoPoint(0.0, 0.0), 0.0)); +// GameState.addYacht(sourceId, new Yacht("Kappa", "Kap", new GeoPoint(0.0, 0.0), 0.0)); } public void run() { @@ -58,14 +58,13 @@ public class ServerToClientThread extends Thread { int sync2; // TODO: 14/07/17 wmu16 - Work out how to fix this while loop while(true) { - //System.out.print("."); try { //Perform a write if it is time to as delegated by the MainServerThread if (updateClient) { // TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream - ChatterMessage chatterMessage = new ChatterMessage(4, 14, "Hello, it's me"); - sendMessage(chatterMessage); + //ChatterMessage chatterMessage = new ChatterMessage(4, 14, "Chatter message"); + //sendMessage(chatterMessage); // try { // GameState.outputState(os); diff --git a/src/main/resources/views/LobbyView.fxml b/src/main/resources/views/LobbyView.fxml index 4e413c61..11830847 100644 --- a/src/main/resources/views/LobbyView.fxml +++ b/src/main/resources/views/LobbyView.fxml @@ -55,9 +55,9 @@ - + - + diff --git a/src/main/resources/views/StartScreenView.fxml b/src/main/resources/views/StartScreenView.fxml index 295faef8..a03d6829 100644 --- a/src/main/resources/views/StartScreenView.fxml +++ b/src/main/resources/views/StartScreenView.fxml @@ -15,8 +15,8 @@ - - + + @@ -33,10 +33,13 @@ + + + @@ -44,5 +47,13 @@ + + + + + + + +