diff --git a/racevisionGame/src/main/java/mock/app/ConnectionAcceptor.java b/racevisionGame/src/main/java/mock/app/ConnectionAcceptor.java index 6425b081..a02b9c40 100644 --- a/racevisionGame/src/main/java/mock/app/ConnectionAcceptor.java +++ b/racevisionGame/src/main/java/mock/app/ConnectionAcceptor.java @@ -37,6 +37,8 @@ public class ConnectionAcceptor implements Runnable { */ private ServerSocket serverSocket; + private Socket mockSocket = null; + /** * List of client connections. @@ -114,7 +116,7 @@ public class ConnectionAcceptor implements Runnable { * Run the Acceptor */ @Override - public void run() { + public void run(){ while(clientConnections.remainingCapacity() > 0) { @@ -124,7 +126,9 @@ public class ConnectionAcceptor implements Runnable { break; } - Socket mockSocket = serverSocket.accept(); + try { + this.mockSocket = serverSocket.accept(); + } catch (Exception e){} Logger.getGlobal().log(Level.INFO, String.format("Client connected. client ip/port = %s. Local ip/port = %s.", mockSocket.getRemoteSocketAddress(), mockSocket.getLocalSocketAddress())); diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index d44295fc..bba2306b 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -157,9 +157,9 @@ public class Event { } public void endEvent() throws IOException { - this.connectionThread.interrupt(); - this.connectionAcceptor.closeConnection(); - this.raceThread.interrupt(); + this.connectionThread.interrupt(); + this.connectionAcceptor.closeConnection(); + this.raceThread.interrupt(); } diff --git a/racevisionGame/src/main/java/mock/app/MockOutput.java b/racevisionGame/src/main/java/mock/app/MockOutput.java index 9536507b..406d1c1c 100644 --- a/racevisionGame/src/main/java/mock/app/MockOutput.java +++ b/racevisionGame/src/main/java/mock/app/MockOutput.java @@ -103,6 +103,8 @@ public class MockOutput implements RunnableWithFramePeriod { Logger.getGlobal().log(Level.WARNING, "MockOutput.run() interrupted while putting message in queue.", e); Thread.currentThread().interrupt(); return; + } catch (Exception e) { + e.printStackTrace(); } } diff --git a/racevisionGame/src/main/java/mock/model/HeartBeatService.java b/racevisionGame/src/main/java/mock/model/HeartBeatService.java index 0028a575..88544340 100644 --- a/racevisionGame/src/main/java/mock/model/HeartBeatService.java +++ b/racevisionGame/src/main/java/mock/model/HeartBeatService.java @@ -78,7 +78,7 @@ public class HeartBeatService implements RunnableWithFramePeriod { * Puts a HeartBeat message on the message queue. * @throws InterruptedException Thrown if the thread is interrupted. */ - private void sendHeartBeat() throws InterruptedException { + private void sendHeartBeat() throws Exception { HeartBeat heartBeat = createHeartbeatMessage(); @@ -92,13 +92,17 @@ public class HeartBeatService implements RunnableWithFramePeriod { while (!Thread.interrupted()) { long currentFrameTime = System.currentTimeMillis(); - waitForFramePeriod(lastHeartbeatTime, currentFrameTime, heartbeatPeriod); + try { + waitForFramePeriod(lastHeartbeatTime, currentFrameTime, heartbeatPeriod); + } catch (Exception e) { + e.printStackTrace(); + } lastHeartbeatTime = currentFrameTime; try { sendHeartBeat(); - } catch (InterruptedException e) { + } catch (Exception e) { Logger.getGlobal().log(Level.WARNING, "HeartBeatService: " + this + " sendHeartBeat() was interrupted on thread: " + Thread.currentThread(), e); Thread.currentThread().interrupt(); return; diff --git a/racevisionGame/src/main/java/mock/model/RaceLogic.java b/racevisionGame/src/main/java/mock/model/RaceLogic.java index 49321904..3895dfaf 100644 --- a/racevisionGame/src/main/java/mock/model/RaceLogic.java +++ b/racevisionGame/src/main/java/mock/model/RaceLogic.java @@ -43,9 +43,17 @@ public class RaceLogic implements RunnableWithFramePeriod { public void run() { race.initialiseBoats(); - countdown(); + try { + countdown(); + } catch (Exception e) { + e.printStackTrace(); + } - raceLoop(); + try { + raceLoop(); + } catch (Exception e) { + e.printStackTrace(); + } } public void boolFalse(){ @@ -56,7 +64,7 @@ public class RaceLogic implements RunnableWithFramePeriod { /** * Countdown timer until race starts. */ - private void countdown() { + private void countdown() throws Exception { long previousFrameTime = System.currentTimeMillis(); @@ -95,7 +103,7 @@ public class RaceLogic implements RunnableWithFramePeriod { /** * Timer that runs for the duration of the race, until all boats finish. */ - private void raceLoop() { + private void raceLoop() throws Exception { long previousFrameTime = System.currentTimeMillis(); diff --git a/racevisionGame/src/main/java/network/StreamRelated/MessageSerialiser.java b/racevisionGame/src/main/java/network/StreamRelated/MessageSerialiser.java index 84bddf78..de165402 100644 --- a/racevisionGame/src/main/java/network/StreamRelated/MessageSerialiser.java +++ b/racevisionGame/src/main/java/network/StreamRelated/MessageSerialiser.java @@ -93,7 +93,11 @@ public class MessageSerialiser implements RunnableWithFramePeriod { long currentFrameTime = System.currentTimeMillis(); - waitForFramePeriod(previousFrameTime, currentFrameTime, 16); + try { + waitForFramePeriod(previousFrameTime, currentFrameTime, 16); + } catch (Exception e) { + e.printStackTrace(); + } previousFrameTime = currentFrameTime; diff --git a/racevisionGame/src/main/java/shared/model/RunnableWithFramePeriod.java b/racevisionGame/src/main/java/shared/model/RunnableWithFramePeriod.java index fd5827f0..10667eca 100644 --- a/racevisionGame/src/main/java/shared/model/RunnableWithFramePeriod.java +++ b/racevisionGame/src/main/java/shared/model/RunnableWithFramePeriod.java @@ -20,7 +20,7 @@ public interface RunnableWithFramePeriod extends Runnable { * @param currentFrameTime The timestamp of the current frame. * @param minimumFramePeriod The minimum period the frame must be. */ - default void waitForFramePeriod(long previousFrameTime, long currentFrameTime, long minimumFramePeriod) { + default void waitForFramePeriod(long previousFrameTime, long currentFrameTime, long minimumFramePeriod) throws Exception { //This is the time elapsed, in milliseconds, since the last server "frame". @@ -39,10 +39,10 @@ public interface RunnableWithFramePeriod extends Runnable { } catch (InterruptedException e) { //If we get interrupted, exit the function. - Logger.getGlobal().log(Level.SEVERE, "RunnableWithFramePeriod.waitForFramePeriod().sleep(framePeriod) was interrupted on thread: " + Thread.currentThread(), e); + /*Logger.getGlobal().log(Level.SEVERE, "RunnableWithFramePeriod.waitForFramePeriod().sleep(framePeriod) was interrupted on thread: " + Thread.currentThread(), e); //Re-set the interrupt flag. Thread.currentThread().interrupt(); - return; + return;*/ } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/ConnectionController.java b/racevisionGame/src/main/java/visualiser/Controllers/ConnectionController.java index a8caad09..9efc7b65 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/ConnectionController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/ConnectionController.java @@ -122,7 +122,7 @@ public class ConnectionController extends Controller { Socket socket = new Socket(connection.getHostname(), connection.getPort()); socket.setKeepAlive(true); connectionWrapper.setVisible(false); - parent.enterLobby(socket); + //parent.enterLobby(socket); } catch (IOException e) { /* Never reached */ } } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/HostController.java b/racevisionGame/src/main/java/visualiser/Controllers/HostController.java index 7d7bed2e..2246b0e1 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/HostController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/HostController.java @@ -71,7 +71,7 @@ public class HostController extends Controller { try{ Socket socket = new Socket(address, port); hostWrapper.setVisible(false); - parent.enterLobby(socket); + parent.enterLobby(socket, true); } catch (IOException e) { /* Never reached */ } } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java index 5ae51d35..f089842d 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java @@ -87,7 +87,7 @@ public class LobbyController extends Controller { RaceConnection connection = lobbyTable.getSelectionModel().getSelectedItem(); Socket socket = new Socket(connection.getHostname(), connection.getPort()); lobbyWrapper.setVisible(false); - parent.enterLobby(socket); + parent.enterLobby(socket, false); } catch (IOException e) { /* Never reached */ e.printStackTrace(); } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/MainController.java b/racevisionGame/src/main/java/visualiser/Controllers/MainController.java index f9ec4589..78c59052 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/MainController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/MainController.java @@ -41,8 +41,8 @@ public class MainController extends Controller { * @param visualiserRace The object modelling the race. * @param controllerClient Socket Client that manipulates the controller. */ - public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient) { - raceController.startRace(visualiserRace, controllerClient); + public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) { + raceController.startRace(visualiserRace, controllerClient, isHost); } public void endEvent() throws IOException { hostController.endEvent(); } @@ -51,8 +51,8 @@ public class MainController extends Controller { * Transitions from the server selection screen to the pre-race lobby for a given server. * @param socket The server to read data from. */ - public void enterLobby(Socket socket) { - startController.enterLobby(socket); + public void enterLobby(Socket socket, Boolean isHost) { + startController.enterLobby(socket, isHost); } /** @@ -67,11 +67,7 @@ public class MainController extends Controller { * Transitions into the title screen */ public void enterTitle() { - try { - App.loadStart(App.getStage()); - } catch (IOException e) { - e.printStackTrace(); - } + titleController.enterTitle(); } /** diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java index 50f9f1e7..d2e39e59 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java @@ -20,6 +20,7 @@ import javafx.scene.layout.StackPane; import javafx.util.Callback; import network.Messages.Enums.RaceStatusEnum; import shared.model.Leg; +import visualiser.app.App; import visualiser.gameController.ControllerClient; import visualiser.gameController.Keys.ControlKey; import visualiser.gameController.Keys.KeyFactory; @@ -28,6 +29,7 @@ import visualiser.network.ServerConnection; import java.io.IOException; import java.net.URL; +import java.util.Optional; import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; @@ -52,7 +54,7 @@ public class RaceController extends Controller { private ControllerClient controllerClient; - + private boolean isHost; /** * The canvas that draws the race. @@ -123,16 +125,34 @@ public class RaceController extends Controller { Logger.getGlobal().log(Level.WARNING, "RaceController was interrupted on thread: " + Thread.currentThread() + "while sending: " + controlKey, e); } } - if(event.getCode() == KeyCode.ESCAPE){ - race.setVisible(false); + if(event.getCode() == KeyCode.ESCAPE) { + try { - parent.endEvent(); + if (isHost) { + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle("Exit Race"); + alert.setContentText("Do you wish to quit the race? You are the host"); + Optional result = alert.showAndWait(); + if (result.get() == ButtonType.OK) { + parent.endEvent(); + race.setVisible(false); + App.app.loadStart(App.getStage()); + } + } else { + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle("Exit Race"); + alert.setContentText("Do you wish to quit the race?"); + Optional result = alert.showAndWait(); + if (result.get() == ButtonType.OK) { + race.setVisible(false); + App.app.loadStart(App.getStage()); + } + } } catch (IOException e) { e.printStackTrace(); } - parent.enterTitle(); } - }); + }); } @@ -371,10 +391,11 @@ public class RaceController extends Controller { * @param visualiserRace Object modelling the race. * @param controllerClient Socket Client that manipulates the controller. */ - public void startRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient) { + public void startRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) { this.visualiserRace = visualiserRace; this.controllerClient = controllerClient; + this.isHost = isHost; initialiseRace(); @@ -438,7 +459,12 @@ public class RaceController extends Controller { //Return to main screen if we lose connection. if (!visualiserRace.getServerConnection().isAlive()) { race.setVisible(false); - parent.enterTitle(); + //parent.enterTitle(); + try { + App.app.loadStart(App.getStage()); + } catch (IOException e) { + e.printStackTrace(); + } //TODO currently this doesn't work correctly - the title screen remains visible after clicking join game //TODO we should display an error to the user //TODO also need to "reset" any state (race, connections, etc...). diff --git a/racevisionGame/src/main/java/visualiser/Controllers/StartController.java b/racevisionGame/src/main/java/visualiser/Controllers/StartController.java index b2d6b2b7..0fadf6c0 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/StartController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/StartController.java @@ -82,7 +82,7 @@ public class StartController extends Controller { */ private ControllerClient controllerClient; - + private boolean isHost; @@ -238,7 +238,7 @@ public class StartController extends Controller { startWrapper.setVisible(false); //start.setVisible(false);//TODO is this needed? - parent.beginRace(visualiserRaceEvent, controllerClient); + parent.beginRace(visualiserRaceEvent, controllerClient, isHost); } } @@ -250,10 +250,13 @@ public class StartController extends Controller { /** * Show starting information for a race given a socket. * @param socket network source of information + * @param isHost */ - public void enterLobby(Socket socket) { + public void enterLobby(Socket socket, Boolean isHost) { try { + this.isHost = isHost; + this.visualiserRaceEvent = new VisualiserRaceEvent(socket, RequestToJoinEnum.PARTICIPANT); this.controllerClient = visualiserRaceEvent.getControllerClient(); diff --git a/racevisionGame/src/main/java/visualiser/app/App.java b/racevisionGame/src/main/java/visualiser/app/App.java index 20376028..40e1e2f2 100644 --- a/racevisionGame/src/main/java/visualiser/app/App.java +++ b/racevisionGame/src/main/java/visualiser/app/App.java @@ -15,7 +15,7 @@ import java.io.IOException; public class App extends Application { private static Stage stage; - private static App app; + public static App app; /** * Entry point for running the programme @@ -45,7 +45,7 @@ public class App extends Application { loadStart(App.stage); } - public static void loadStart(Stage stage) throws IOException { + public void loadStart(Stage stage) throws IOException { FXMLLoader loader = new FXMLLoader(App.class.getResource("/visualiser/scenes/main.fxml")); Parent root = loader.load(); stage.setResizable(false); diff --git a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceService.java b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceService.java index 21be26d9..e08f1463 100644 --- a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceService.java +++ b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceService.java @@ -69,7 +69,11 @@ public class VisualiserRaceService implements RunnableWithFramePeriod { long currentFrameTime = System.currentTimeMillis(); - waitForFramePeriod(previousFrameTime, currentFrameTime, 16); + try { + waitForFramePeriod(previousFrameTime, currentFrameTime, 16); + } catch (Exception e) { + e.printStackTrace(); + } previousFrameTime = currentFrameTime; diff --git a/racevisionGame/src/main/java/visualiser/network/ServerConnection.java b/racevisionGame/src/main/java/visualiser/network/ServerConnection.java index ed540566..b0266962 100644 --- a/racevisionGame/src/main/java/visualiser/network/ServerConnection.java +++ b/racevisionGame/src/main/java/visualiser/network/ServerConnection.java @@ -330,7 +330,11 @@ public class ServerConnection implements RunnableWithFramePeriod { while (!Thread.interrupted()) { long currentFrameTime = System.currentTimeMillis(); - waitForFramePeriod(previousFrameTime, currentFrameTime, 100); + try { + waitForFramePeriod(previousFrameTime, currentFrameTime, 100); + } catch (Exception e) { + e.printStackTrace(); + } previousFrameTime = currentFrameTime;