Merge branch 'master' into MapWindRotation

# Conflicts:
#	racevisionGame/src/main/java/mock/app/Event.java
#	racevisionGame/src/main/java/mock/model/MockRace.java
#	racevisionGame/src/main/java/mock/model/commandFactory/CommandFactory.java
#	racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java
#	racevisionGame/src/main/java/shared/model/CompoundMark.java
#	racevisionGame/src/main/java/shared/model/Mark.java
#	racevisionGame/src/main/java/visualiser/Controllers/ConnectionController.java
#	racevisionGame/src/main/java/visualiser/Controllers/HostController.java
#	racevisionGame/src/main/java/visualiser/app/VisualiserInput.java
#	racevisionGame/src/main/java/visualiser/gameController/ControllerServer.java
#	racevisionGame/src/main/java/visualiser/model/VisualiserRace.java
This commit is contained in:
Joseph Gardner
2017-08-17 11:46:09 +12:00
115 changed files with 7745 additions and 2288 deletions
@@ -4,7 +4,6 @@ package visualiser.Controllers;
import javafx.application.Platform;
import javafx.beans.property.Property;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
@@ -12,7 +11,6 @@ import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import shared.model.Bearing;
import shared.model.Wind;
import visualiser.model.VisualiserRace;
/**
* Controller for the arrow.fxml view.
@@ -22,6 +22,7 @@ import java.net.URL;
import java.net.UnknownHostException;
import java.util.ResourceBundle;
//TODO it appears this view/controller was replaced by Lobby.fxml. Remove?
/**
* Controls the connection that the VIsualiser can connect to.
*/
@@ -85,11 +86,6 @@ public class ConnectionController extends Controller {
private ObservableList<RaceConnection> connections;
/**
* Represents whether the client is currently hosting a game already - this is to ensure they don't launch multiple servers.
*/
private boolean currentlyHostingGame = false;
@Override
public void initialize(URL location, ResourceBundle resources) {
@@ -147,40 +143,5 @@ public class ConnectionController extends Controller {
}
}
/**
* Sets up a new host
*/
public void addLocal() {
try {
//We don't want to host more than one game.
if (!currentlyHostingGame) {
Event game = Event.getEvent();
urlField.textProperty().set(game.getAddress());
portField.textProperty().set(Integer.toString(game.getPort()));
game.start();
addConnection();
currentlyHostingGame = true;
}
} catch (InvalidRaceDataException e) {
e.printStackTrace();
} catch (XMLReaderException e) {
e.printStackTrace();
} catch (InvalidBoatDataException e) {
e.printStackTrace();
} catch (InvalidRegattaDataException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
}
@@ -7,6 +7,7 @@ import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import mock.app.Event;
import org.xml.sax.SAXException;
import mock.exceptions.EventConstructionException;
import shared.exceptions.InvalidBoatDataException;
import shared.exceptions.InvalidRaceDataException;
import shared.exceptions.InvalidRegattaDataException;
@@ -20,6 +21,8 @@ import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Controller for Hosting a game.
@@ -47,23 +50,12 @@ public class HostController extends Controller {
*/
public void hostGamePressed() throws IOException{
try {
Event game = Event.getEvent();
Event game = new Event(false);
game.start();
connectSocket("localhost", 4942);
} catch (InvalidRaceDataException e) {
e.printStackTrace();
} catch (XMLReaderException e) {
e.printStackTrace();
} catch (InvalidBoatDataException e) {
e.printStackTrace();
} catch (InvalidRegattaDataException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (EventConstructionException e) {
Logger.getGlobal().log(Level.SEVERE, "Could not create Event.", e);
throw new RuntimeException(e);
}
}
@@ -89,7 +81,6 @@ public class HostController extends Controller {
*/
public void hostGame(){
hostWrapper.setVisible(true);
System.out.println("Reacted hostGame");
}
}
@@ -58,7 +58,6 @@ public class LobbyController extends Controller {
}
else {
joinGameBtn.setDisable(true);
System.out.println(curr.statusProperty().getValue());
}
});
joinGameBtn.setDisable(true);
@@ -70,11 +69,6 @@ public class LobbyController extends Controller {
public void refreshBtnPressed(){
for(RaceConnection connection: connections) {
connection.check();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
if (lobbyTable.getSelectionModel().getSelectedItem().statusProperty().getValue().equals("Ready")) {
@@ -3,15 +3,15 @@ package visualiser.Controllers;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.layout.AnchorPane;
import visualiser.app.VisualiserInput;
import visualiser.gameController.ControllerClient;
import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRace;
import visualiser.model.VisualiserRaceEvent;
import java.net.Socket;
import java.net.URL;
import java.util.ResourceBundle;
/**
* Controller that everything is overlayed onto. This makes it so that changing scenes does not resize your stage.
*/
@@ -36,12 +36,11 @@ public class MainController extends Controller {
/**
* Transitions from the StartController screen (displays pre-race information) to the RaceController (displays the actual race).
* @param visualiserInput The object used to read packets from the race server.
* @param visualiserRace The object modelling the race.
* @param controllerClient Socket Client that manipulates the controller.
*/
public void beginRace(VisualiserInput visualiserInput, VisualiserRace visualiserRace, ControllerClient controllerClient) {
raceController.startRace(visualiserInput, visualiserRace, controllerClient);
public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient) {
raceController.startRace(visualiserRace, controllerClient);
}
/**
@@ -103,10 +102,15 @@ public class MainController extends Controller {
AnchorPane.setLeftAnchor(startController.startWrapper(), 0.0);
AnchorPane.setRightAnchor(startController.startWrapper(), 0.0);
AnchorPane.setTopAnchor(connectionController.startWrapper(), 0.0);
AnchorPane.setBottomAnchor(connectionController.startWrapper(), 0.0);
AnchorPane.setLeftAnchor(connectionController.startWrapper(), 0.0);
AnchorPane.setRightAnchor(connectionController.startWrapper(), 0.0);
AnchorPane.setTopAnchor(lobbyController.startWrapper(), 0.0);
AnchorPane.setBottomAnchor(lobbyController.startWrapper(), 0.0);
AnchorPane.setLeftAnchor(lobbyController.startWrapper(), 0.0);
AnchorPane.setRightAnchor(lobbyController.startWrapper(), 0.0);
AnchorPane.setTopAnchor(hostController.startWrapper(), 0.0);
AnchorPane.setBottomAnchor(hostController.startWrapper(), 0.0);
AnchorPane.setLeftAnchor(hostController.startWrapper(), 0.0);
AnchorPane.setRightAnchor(hostController.startWrapper(), 0.0);
AnchorPane.setTopAnchor(finishController.finishWrapper, 0.0);
AnchorPane.setBottomAnchor(finishController.finishWrapper, 0.0);
@@ -4,7 +4,9 @@ package visualiser.Controllers;
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import javafx.fxml.FXML;
import javafx.scene.chart.LineChart;
import javafx.scene.control.*;
@@ -17,35 +19,38 @@ import javafx.scene.layout.StackPane;
import javafx.util.Callback;
import network.Messages.Enums.RaceStatusEnum;
import shared.model.Leg;
import visualiser.app.VisualiserInput;
import visualiser.gameController.ControllerClient;
import visualiser.gameController.Keys.ControlKey;
import visualiser.gameController.Keys.KeyFactory;
import visualiser.model.*;
import visualiser.network.ServerConnection;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Controller used to display a running race.
*/
public class RaceController extends Controller {
/**
* The object used to read packets from the connected server.
*/
private VisualiserInput visualiserInput;
/**
* The race object which describes the currently occurring race.
*/
private VisualiserRace visualiserRace;
private VisualiserRaceEvent visualiserRace;
/**
* An additional observable list of boats. This is used by the table view, to allow it to sort boats without effecting the race's own list of boats.
* Service for sending keystrokes to server
*/
private ObservableList<VisualiserBoat> tableBoatList;
private ControllerClient controllerClient;
/**
* The canvas that draws the race.
@@ -62,10 +67,6 @@ public class RaceController extends Controller {
*/
@FXML private ArrowController arrowController;
/**
* Service for sending keystrokes to server
*/
private ControllerClient controllerClient;
@FXML private GridPane canvasBase;
@@ -115,8 +116,9 @@ public class RaceController extends Controller {
controllerClient.sendKey(controlKey);
controlKey.onAction(); // Change key state if applicable
event.consume();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Logger.getGlobal().log(Level.WARNING, "RaceController was interrupted on thread: " + Thread.currentThread() + "while sending: " + controlKey, e);
}
}
});
@@ -159,7 +161,7 @@ public class RaceController extends Controller {
* Initialises the frame rate functionality. This allows for toggling the frame rate, and connect the fps label to the race's fps property.
* @param visualiserRace The race to connect the fps label to.
*/
private void initialiseFps(VisualiserRace visualiserRace) {
private void initialiseFps(VisualiserRaceEvent visualiserRace) {
//On/off toggle.
initialiseFpsToggle();
@@ -189,9 +191,9 @@ public class RaceController extends Controller {
* Initialises the fps label to update when the race fps changes.
* @param visualiserRace The race to monitor the frame rate of.
*/
private void initialiseFpsLabel(VisualiserRace visualiserRace) {
private void initialiseFpsLabel(VisualiserRaceEvent visualiserRace) {
visualiserRace.fpsProperty().addListener((observable, oldValue, newValue) -> {
visualiserRace.getFrameRateProperty().addListener((observable, oldValue, newValue) -> {
Platform.runLater(() -> this.FPS.setText("FPS: " + newValue.toString()));
});
@@ -203,14 +205,21 @@ public class RaceController extends Controller {
* Initialises the information table view to listen to a given race.
* @param race Race to listen to.
*/
public void initialiseInfoTable(VisualiserRace race) {
public void initialiseInfoTable(VisualiserRaceEvent race) {
//Copy list of boats.
this.tableBoatList = FXCollections.observableArrayList(race.getBoats());
ObservableList<VisualiserBoat> boats = FXCollections.observableArrayList(race.getVisualiserRaceState().getBoats());
SortedList<VisualiserBoat> sortedBoats = new SortedList<>(boats);
sortedBoats.comparatorProperty().bind(boatInfoTable.comparatorProperty());
//Update copy when original changes.
race.getVisualiserRaceState().getBoats().addListener((ListChangeListener.Change<? extends VisualiserBoat> c) -> Platform.runLater(() -> {
boats.setAll(race.getVisualiserRaceState().getBoats());
}));
//Set up table.
boatInfoTable.setItems(this.tableBoatList);
boatInfoTable.setItems(sortedBoats);
//Set up each column.
@@ -290,12 +299,12 @@ public class RaceController extends Controller {
/**
* Initialises the {@link Sparkline}, and listens to a specified {@link VisualiserRace}.
* Initialises the {@link Sparkline}, and listens to a specified {@link VisualiserRaceEvent}.
* @param race The race to listen to.
*/
private void initialiseSparkline(VisualiserRace race) {
private void initialiseSparkline(VisualiserRaceEvent race) {
//The race.getBoats() we are passing in is sorted by position in race inside the race class.
this.sparkline = new Sparkline(this.visualiserRace, this.sparklineChart);
this.sparkline = new Sparkline(this.visualiserRace.getVisualiserRaceState(), this.sparklineChart);
}
@@ -303,7 +312,7 @@ public class RaceController extends Controller {
* Initialises the {@link ResizableRaceCanvas}, provides the race to read data from.
* @param race Race to read data from.
*/
private void initialiseRaceCanvas(VisualiserRace race) {
private void initialiseRaceCanvas(VisualiserRaceEvent race) {
//Create canvas.
raceCanvas = new ResizableRaceCanvas(race);
@@ -326,18 +335,18 @@ public class RaceController extends Controller {
* Intialises the race time zone label with the race's time zone.
* @param race The race to get time zone from.
*/
private void initialiseRaceTimezoneLabel(VisualiserRace race) {
timeZone.setText(race.getRaceClock().getTimeZone());
private void initialiseRaceTimezoneLabel(VisualiserRaceEvent race) {
timeZone.setText(race.getVisualiserRaceState().getRaceClock().getTimeZone());
}
/**
* Initialises the race clock to listen to the specified race.
* @param race The race to listen to.
*/
private void initialiseRaceClock(VisualiserRace race) {
private void initialiseRaceClock(VisualiserRaceEvent race) {
//RaceClock.duration isn't necessarily being changed in the javaFX thread, so we need to runlater the update.
race.getRaceClock().durationProperty().addListener((observable, oldValue, newValue) -> {
race.getVisualiserRaceState().getRaceClock().durationProperty().addListener((observable, oldValue, newValue) -> {
Platform.runLater(() -> {
timer.setText(newValue);
});
@@ -348,13 +357,11 @@ public class RaceController extends Controller {
/**
* Displays a specified race.
* @param visualiserInput Object used to read packets from server.
* @param visualiserRace Object modelling the race.
* @param controllerClient Socket Client that manipulates the controller.
*/
public void startRace(VisualiserInput visualiserInput, VisualiserRace visualiserRace, ControllerClient controllerClient) {
public void startRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient) {
this.visualiserInput = visualiserInput;
this.visualiserRace = visualiserRace;
this.controllerClient = controllerClient;
@@ -372,7 +379,7 @@ public class RaceController extends Controller {
* Transition from the race view to the finish view.
* @param boats boats there are in the race.
*/
public void finishRace(ObservableList<VisualiserBoat> boats){
public void finishRace(ObservableList<VisualiserBoat> boats) {
race.setVisible(false);
parent.enterFinish(boats);
}
@@ -382,8 +389,8 @@ public class RaceController extends Controller {
* Initialises the arrow controller with data from the race to observe.
* @param race The race to observe.
*/
private void initialiseArrow(VisualiserRace race) {
arrowController.setWindProperty(race.windProperty());
private void initialiseArrow(VisualiserRaceEvent race) {
arrowController.setWindProperty(race.getVisualiserRaceState().windProperty());
}
@@ -396,7 +403,7 @@ public class RaceController extends Controller {
public void handle(long arg0) {
//Get the current race status.
RaceStatusEnum raceStatus = visualiserRace.getRaceStatusEnum();
RaceStatusEnum raceStatus = visualiserRace.getVisualiserRaceState().getRaceStatusEnum();
//If the race has finished, go to finish view.
@@ -405,7 +412,7 @@ public class RaceController extends Controller {
stop();
//Hide this, and display the finish controller.
finishRace(visualiserRace.getBoats());
finishRace(visualiserRace.getVisualiserRaceState().getBoats());
} else {
//Otherwise, render the canvas.
@@ -417,6 +424,15 @@ public class RaceController extends Controller {
}
//Return to main screen if we lose connection.
if (!visualiserRace.getServerConnection().isAlive()) {
race.setVisible(false);
parent.enterTitle();
//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...).
}
}
}.start();
}
@@ -9,8 +9,9 @@ import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import mock.model.commandFactory.CompositeCommand;
import network.Messages.Enums.RaceStatusEnum;
import network.Messages.Enums.RequestToJoinEnum;
import network.Messages.LatestMessages;
import shared.dataInput.*;
import shared.enums.XMLFileType;
@@ -18,20 +19,24 @@ import shared.exceptions.InvalidBoatDataException;
import shared.exceptions.InvalidRaceDataException;
import shared.exceptions.InvalidRegattaDataException;
import shared.exceptions.XMLReaderException;
import visualiser.app.VisualiserInput;
import visualiser.gameController.ControllerClient;
import visualiser.model.VisualiserRaceState;
import visualiser.network.ServerConnection;
import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRace;
import visualiser.model.VisualiserRaceEvent;
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Controller to for waiting for the race to start.
*/
public class StartController extends Controller implements Observer {
public class StartController extends Controller {
@FXML private GridPane start;
@FXML private AnchorPane startWrapper;
@@ -66,33 +71,21 @@ public class StartController extends Controller implements Observer {
@FXML private Label raceStatusLabel;
/**
* The race + connection to server.
*/
private VisualiserRaceEvent visualiserRaceEvent;
/**
* The object used to read packets from the connected server.
* Writes BoatActions to outgoing message queue.
*/
private VisualiserInput visualiserInput;
/**
* The race object which describes the currently occurring race.
*/
private VisualiserRace visualiserRace;
private ControllerClient controllerClient;
/**
* An array of colors used to assign colors to each boat - passed in to the VisualiserRace constructor.
*/
List<Color> colors = new ArrayList<>(Arrays.asList(
Color.BLUEVIOLET,
Color.BLACK,
Color.RED,
Color.ORANGE,
Color.DARKOLIVEGREEN,
Color.LIMEGREEN,
Color.PURPLE,
Color.DARKGRAY,
Color.YELLOW
));
@@ -109,33 +102,17 @@ public class StartController extends Controller implements Observer {
/**
* Starts the race.
* Called once we have received all XML files from the server.
* @param latestMessages The set of latest race messages to use for race.
* @throws XMLReaderException Thrown if XML file cannot be parsed.
* @throws InvalidRaceDataException Thrown if XML file cannot be parsed.
* @throws InvalidBoatDataException Thrown if XML file cannot be parsed.
* @throws InvalidRegattaDataException Thrown if XML file cannot be parsed.
*/
private void startRace(LatestMessages latestMessages) throws XMLReaderException, InvalidRaceDataException, InvalidBoatDataException, InvalidRegattaDataException {
//Create data sources from latest messages for the race.
RaceDataSource raceDataSource = new RaceXMLReader(latestMessages.getRaceXMLMessage().getXmlMessage(), XMLFileType.Contents);
BoatDataSource boatDataSource = new BoatXMLReader(latestMessages.getBoatXMLMessage().getXmlMessage(), XMLFileType.Contents);
RegattaDataSource regattaDataSource = new RegattaXMLReader(latestMessages.getRegattaXMLMessage().getXmlMessage(), XMLFileType.Contents);
//Create race.
this.visualiserRace = new VisualiserRace(boatDataSource, raceDataSource, regattaDataSource, latestMessages, this.colors);
new Thread(this.visualiserRace).start();
private void startRace() {
//Initialise the boat table.
initialiseBoatTable(this.visualiserRace);
initialiseBoatTable(this.visualiserRaceEvent.getVisualiserRaceState());
//Initialise the race name.
initialiseRaceName(this.visualiserRace);
initialiseRaceName(this.visualiserRaceEvent.getVisualiserRaceState());
//Initialises the race clock.
initialiseRaceClock(this.visualiserRace);
initialiseRaceClock(this.visualiserRaceEvent.getVisualiserRaceState());
//Starts the race countdown timer.
countdownTimer();
@@ -153,7 +130,7 @@ public class StartController extends Controller implements Observer {
* Initialises the boat table that is to be shown on the pane.
* @param visualiserRace The race to get data from.
*/
private void initialiseBoatTable(VisualiserRace visualiserRace) {
private void initialiseBoatTable(VisualiserRaceState visualiserRace) {
//Get the boats.
ObservableList<VisualiserBoat> boats = visualiserRace.getBoats();
@@ -168,7 +145,7 @@ public class StartController extends Controller implements Observer {
* Initialises the race name which is shown on the pane.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceName(VisualiserRace visualiserRace) {
private void initialiseRaceName(VisualiserRaceState visualiserRace) {
raceTitleLabel.setText(visualiserRace.getRegattaName());
@@ -178,7 +155,7 @@ public class StartController extends Controller implements Observer {
* Initialises the race clock/timer labels for the start time, current time, and remaining time.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceClock(VisualiserRace visualiserRace) {
private void initialiseRaceClock(VisualiserRaceState visualiserRace) {
//Start time.
initialiseRaceClockStartTime(visualiserRace);
@@ -196,7 +173,7 @@ public class StartController extends Controller implements Observer {
* Initialises the race current time label.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceClockStartTime(VisualiserRace visualiserRace) {
private void initialiseRaceClockStartTime(VisualiserRaceState visualiserRace) {
raceStartLabel.setText(visualiserRace.getRaceClock().getStartingTimeString());
@@ -213,7 +190,7 @@ public class StartController extends Controller implements Observer {
* Initialises the race current time label.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceClockCurrentTime(VisualiserRace visualiserRace) {
private void initialiseRaceClockCurrentTime(VisualiserRaceState visualiserRace) {
visualiserRace.getRaceClock().currentTimeProperty().addListener((observable, oldValue, newValue) -> {
Platform.runLater(() -> {
@@ -227,7 +204,7 @@ public class StartController extends Controller implements Observer {
* Initialises the race duration label.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceClockDuration(VisualiserRace visualiserRace) {
private void initialiseRaceClockDuration(VisualiserRaceState visualiserRace) {
visualiserRace.getRaceClock().durationProperty().addListener((observable, oldValue, newValue) -> {
Platform.runLater(() -> {
@@ -245,13 +222,13 @@ public class StartController extends Controller implements Observer {
@Override
public void handle(long arg0) {
//TODO instead of having an AnimationTimer checking the race status, we could provide a Property<RaceStatusEnum>, and connect a listener to that.
//Get the current race status.
RaceStatusEnum raceStatus = visualiserRace.getRaceStatusEnum();
RaceStatusEnum raceStatus = visualiserRaceEvent.getVisualiserRaceState().getRaceStatusEnum();
//Display it.
raceStatusLabel.setText("Race Status: " + raceStatus.name());
//If the race has reached the preparatory phase, or has started...
if (raceStatus == RaceStatusEnum.PREPARATORY || raceStatus == RaceStatusEnum.STARTED) {
//Stop this timer.
@@ -259,9 +236,10 @@ public class StartController extends Controller implements Observer {
//Hide this, and display the race controller.
startWrapper.setVisible(false);
start.setVisible(false);
//start.setVisible(false);//TODO is this needed?
parent.beginRace(visualiserRaceEvent, controllerClient);
parent.beginRace(visualiserInput, visualiserRace, controllerClient);
}
}
}.start();
@@ -269,57 +247,25 @@ public class StartController extends Controller implements Observer {
/**
* Function to handle changes in objects we observe.
* We observe LatestMessages.
* @param o The observed object.
* @param arg The {@link Observable#notifyObservers(Object)} parameter.
*/
@Override
public void update(Observable o, Object arg) {
//Check that we actually have LatestMessages.
if (o instanceof LatestMessages) {
LatestMessages latestMessages = (LatestMessages) o;
//If we've received all of the xml files, start the race. Only start it if it hasn't already been created.
if (latestMessages.hasAllXMLMessages() && this.visualiserRace == null) {
//Need to handle it in the javafx thread.
Platform.runLater(() -> {
try {
this.startRace(latestMessages);
} catch (XMLReaderException | InvalidBoatDataException | InvalidRaceDataException | InvalidRegattaDataException e) {
//We currently don't handle this in meaningful way, as it should never occur.
//If we reach this point it means that malformed XML files were sent.
e.printStackTrace();
}
});
}
}
}
/**
* Show starting information for a race given a socket.
* @param socket network source of information
*/
public void enterLobby(Socket socket) {
startWrapper.setVisible(true);
try {
//Begin reading packets from the socket/server.
this.visualiserInput = new VisualiserInput(socket);
//Send controller input to server
this.controllerClient = new ControllerClient(socket);
//Store a reference to latestMessages so that we can observe it.
LatestMessages latestMessages = this.visualiserInput.getLatestMessages();
latestMessages.addObserver(this);
new Thread(this.visualiserInput).start();
this.visualiserRaceEvent = new VisualiserRaceEvent(socket, RequestToJoinEnum.PARTICIPANT);
this.controllerClient = visualiserRaceEvent.getControllerClient();
startWrapper.setVisible(true);
startRace();
} catch (IOException e) {
e.printStackTrace();
//TODO should probably let this propagate, so that we only enter this scene if everything works
Logger.getGlobal().log(Level.WARNING, "Could not connect to server.", e);
}
}