Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Alistair McIntyre
2017-07-26 20:13:09 +12:00
11 changed files with 145 additions and 72 deletions
@@ -59,6 +59,7 @@ public class ClientPacketParser {
*/ */
public ClientPacketParser() { public ClientPacketParser() {
} }
/** /**
* Looks at the type of the packet then sends it to the appropriate parser to extract the * Looks at the type of the packet then sends it to the appropriate parser to extract the
* specific data associated with that packet type * specific data associated with that packet type
@@ -108,7 +109,7 @@ public class ClientPacketParser {
} }
} catch (NullPointerException e) { } catch (NullPointerException e) {
System.out.println("Error parsing packet"); System.out.println("Error parsing packet");
e.printStackTrace(); // e.printStackTrace();
} }
} }
@@ -185,7 +186,6 @@ public class ClientPacketParser {
int noBoats = payload[22]; int noBoats = payload[22];
int raceType = payload[23]; int raceType = payload[23];
clientStateBoats = ClientState.getBoats();
for (int i = 0; i < noBoats; i++) { for (int i = 0; i < noBoats; i++) {
long boatStatusSourceID = bytesToLong( long boatStatusSourceID = bytesToLong(
Arrays.copyOfRange(payload, 24 + (i * 20), 28 + (i * 20))); Arrays.copyOfRange(payload, 24 + (i * 20), 28 + (i * 20)));
@@ -206,7 +206,9 @@ public class ClientPacketParser {
boat.setEstimateTimeAtNextMark(estTimeAtNextMark); boat.setEstimateTimeAtNextMark(estTimeAtNextMark);
boat.setEstimateTimeAtFinish(estTimeAtFinish); boat.setEstimateTimeAtFinish(estTimeAtFinish);
Yacht clientBoat = clientStateBoats.get((int) boatStatusSourceID); // Update Client State boats when receive race status packet.
// Potentially could replace boats in ClientPacketParser.
Yacht clientBoat = ClientState.getBoats().get((int) boatStatusSourceID);
clientBoat.setBoatStatus((boatStatus)); clientBoat.setBoatStatus((boatStatus));
setBoatLegPosition(clientBoat, boatLegNumber); setBoatLegPosition(clientBoat, boatLegNumber);
clientBoat.setPenaltiesAwarded(boatPenaltyAwarded); clientBoat.setPenaltiesAwarded(boatPenaltyAwarded);
@@ -215,26 +217,32 @@ public class ClientPacketParser {
clientBoat.setEstimateTimeAtFinish(estTimeAtFinish); clientBoat.setEstimateTimeAtFinish(estTimeAtFinish);
} }
// 3 is race started // 3 is race started.
// ClientState race started flag will be set to true if race started, else set false.
if (raceStatus == 3) { if (raceStatus == 3) {
ClientState.setRaceStarted(true); ClientState.setRaceStarted(true);
} else {
ClientState.setRaceStarted(false);
} }
} }
private static void setBoatLegPosition(Yacht updatingBoat, Integer leg){ private static void setBoatLegPosition(Yacht updatingBoat, Integer leg){
Integer placing = 1; Integer placing = 1;
if (leg != updatingBoat.getLegNumber() && (raceStarted || raceFinished)) {
if (/* TODO implement when we are getting this data /TODO leg != updatingBoat.getLegNumber() && */(raceStarted || raceFinished)) {
for (Yacht boat : boats.values()) { for (Yacht boat : boats.values()) {
placing = boat.getSourceId();
/* See above to-do
if (boat.getLegNumber() != null && leg <= boat.getLegNumber()){ if (boat.getLegNumber() != null && leg <= boat.getLegNumber()){
placing += 1; placing += 1;
} }*/
} }
updatingBoat.setPosition(placing.toString()); updatingBoat.setPosition(placing.toString());
updatingBoat.setLegNumber(leg); updatingBoat.setLegNumber(leg);
boatsPos.putIfAbsent(placing, updatingBoat); boatsPos.putIfAbsent(placing, updatingBoat);
boatsPos.replace(placing, updatingBoat); boatsPos.replace(placing, updatingBoat);
} else if(updatingBoat.getLegNumber() == null){ } else if(updatingBoat.getLegNumber() == null){
updatingBoat.setPosition("1"); updatingBoat.setPosition("-");
updatingBoat.setLegNumber(leg); updatingBoat.setLegNumber(leg);
} }
} }
@@ -286,8 +294,10 @@ public class ClientPacketParser {
xmlObject.constructXML(doc, messageType); xmlObject.constructXML(doc, messageType);
if (messageType == 7) { //7 is the boat XML if (messageType == 7) { //7 is the boat XML
boats = xmlObject.getBoatXML().getCompetingBoats(); boats = xmlObject.getBoatXML().getCompetingBoats();
// Set/Update the ClientState boats after receiving new boat xml.
// Flag boatsUpdated in ClientState to true.
ClientState.setBoats(xmlObject.getBoatXML().getCompetingBoats()); ClientState.setBoats(xmlObject.getBoatXML().getCompetingBoats());
ClientState.setDirtyState(true); ClientState.setBoatsUpdated(true);
} }
if (messageType == 6) { //6 is race info xml if (messageType == 6) { //6 is race info xml
newRaceXmlReceived = true; newRaceXmlReceived = true;
@@ -1,14 +1,12 @@
package seng302.client; package seng302.client;
import com.sun.org.apache.xpath.internal.operations.Bool;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import seng302.models.Yacht; import seng302.models.Yacht;
/** /**
* Used by the client to store static variables to be used in game. * Used by the client to store static variables, which other threads and classes
* observer so that they can update their status accordingly.
*/ */
public class ClientState { public class ClientState {
@@ -17,7 +15,7 @@ public class ClientState {
private static Boolean raceStarted = false; private static Boolean raceStarted = false;
private static Boolean connectedToHost = false; private static Boolean connectedToHost = false;
private static Map<Integer, Yacht> boats = new ConcurrentHashMap<>(); private static Map<Integer, Yacht> boats = new ConcurrentHashMap<>();
private static Boolean dirtyState = true; private static Boolean boatsUpdated = true;
private static String clientSourceId = ""; private static String clientSourceId = "";
public static String getHostIp() { public static String getHostIp() {
@@ -56,12 +54,12 @@ public class ClientState {
return boats; return boats;
} }
public static Boolean isDirtyState() { public static Boolean isBoatsUpdated() {
return dirtyState; return boatsUpdated;
} }
public static void setDirtyState(Boolean dirtyState) { public static void setBoatsUpdated(Boolean boatsUpdated) {
ClientState.dirtyState = dirtyState; ClientState.boatsUpdated = boatsUpdated;
} }
public static String getClientSourceId() { public static String getClientSourceId() {
@@ -12,6 +12,12 @@ public class ClientStateQueryingRunnable extends Observable implements Runnable
public ClientStateQueryingRunnable() {} public ClientStateQueryingRunnable() {}
/**
* Notifies observers(the lobby controller) that "game started" if ClientState
* raceStarted flag is true and terminates itself. Also, it notifies observers
* to add/remove players if ClientState boatsUpdated flag is true, then resets
* the flag to false;
*/
@Override @Override
public void run() { public void run() {
while(!terminate) { while(!terminate) {
@@ -29,14 +35,19 @@ public class ClientStateQueryingRunnable extends Observable implements Runnable
terminate(); terminate();
} }
if (ClientState.isDirtyState()) { if (ClientState.isBoatsUpdated()) {
setChanged(); setChanged();
notifyObservers("update players"); notifyObservers("update players");
ClientState.setDirtyState(false); ClientState.setBoatsUpdated(false);
} }
} }
} }
/**
* Used to terminate the thread.
*
* Currently called by the main while loop when game started is detected.
*/
public void terminate() { public void terminate() {
terminate = true; terminate = true;
} }
@@ -15,7 +15,8 @@ import seng302.server.messages.BoatActionMessage;
import seng302.server.messages.Message; import seng302.server.messages.Message;
/** /**
* Created by kre39 on 13/07/17. * A class describing a single connection to a Server for the purposes of sending and receiving on
* its own thread.
*/ */
public class ClientToServerThread implements Runnable { public class ClientToServerThread implements Runnable {
@@ -30,8 +31,19 @@ public class ClientToServerThread implements Runnable {
private OutputStream os; private OutputStream os;
private Boolean updateClient = true; private Boolean updateClient = true;
private ByteArrayOutputStream crcBuffer; private ByteArrayOutputStream crcBuffer;
/**
* Constructor for ClientToServerThread which takes in ipAddress and portNumber and attempts to
* connect to the specified ipAddress and port.
*
* Upon successful socket connection, threeWayHandshake will be preformed and the instance will
* be put on a thread and run immediately.
*
* @param ipAddress a string of ip address to be connected to
* @param portNumber an integer port number
* @throws Exception SocketConnection if fail to connect to ip address and port number combination
*/
public ClientToServerThread(String ipAddress, Integer portNumber) throws Exception{ public ClientToServerThread(String ipAddress, Integer portNumber) throws Exception{
socket = new Socket(ipAddress, portNumber); socket = new Socket(ipAddress, portNumber);
is = socket.getInputStream(); is = socket.getInputStream();
@@ -40,7 +52,7 @@ public class ClientToServerThread implements Runnable {
Integer allocatedID = threeWayHandshake(); Integer allocatedID = threeWayHandshake();
if (allocatedID != null) { if (allocatedID != null) {
ourID = allocatedID; ourID = allocatedID;
clientLog("Successful handshake. Allocated ID: " + ourID, 1); clientLog("Successful handshake. Allocated ID: " + ourID, 0);
ClientState.setClientSourceId(String.valueOf(ourID)); ClientState.setClientSourceId(String.valueOf(ourID));
} else { } else {
clientLog("Unsuccessful handshake", 1); clientLog("Unsuccessful handshake", 1);
@@ -50,31 +62,31 @@ public class ClientToServerThread implements Runnable {
thread = new Thread(this); thread = new Thread(this);
thread.start(); thread.start();
} }
/**
* Prints out log messages and the time happened.
* Only perform task if log level is below LOG_LEVEL variable.
*
* @param message a string of message to be printed out
* @param logLevel an int for log level
*/
static void clientLog(String message, int logLevel){ static void clientLog(String message, int logLevel){
if(logLevel <= LOG_LEVEL){ if(logLevel <= LOG_LEVEL){
System.out.println("[CLIENT " + LocalDateTime.now().toLocalTime().toString() + "] " + message); System.out.println("[CLIENT " + LocalDateTime.now().toLocalTime().toString() + "] " + message);
} }
} }
/**
* Perform the thread loop. It exits the loop if ClientState connected to host
* variable is false.
*/
public void run() { public void run() {
int sync1; int sync1;
int sync2; int sync2;
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop // TODO: 14/07/17 wmu16 - Work out how to fix this while loop
while(ClientState.isConnectedToHost()) { while(ClientState.isConnectedToHost()) {
try { 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
// try {
// GameState.outputState(os);
// } catch (IOException e) {
// System.out.println("IO error in server thread upon writing to output stream");
// }
updateClient = false;
}
crcBuffer = new ByteArrayOutputStream(); crcBuffer = new ByteArrayOutputStream();
sync1 = readByte(); sync1 = readByte();
sync2 = readByte(); sync2 = readByte();
@@ -93,7 +105,6 @@ public class ClientToServerThread implements Runnable {
if (computedCrc == packetCrc) { if (computedCrc == packetCrc) {
ClientPacketParser ClientPacketParser
.parsePacket(new StreamPacket(type, payloadLength, timeStamp, payload)); .parsePacket(new StreamPacket(type, payloadLength, timeStamp, payload));
// TODO: 17/07/17 wmu16 - Fix this or maybe we dont need to go through the main server at all!?!?
// packetBufferDelegate.addToBuffer(new StreamPacket(type, payloadLength, timeStamp, payload)); // packetBufferDelegate.addToBuffer(new StreamPacket(type, payloadLength, timeStamp, payload));
} else { } else {
clientLog("Packet has been dropped", 1); clientLog("Packet has been dropped", 1);
@@ -101,8 +112,7 @@ public class ClientToServerThread implements Runnable {
} }
} catch (Exception e) { } catch (Exception e) {
closeSocket(); closeSocket();
System.err.println("SERVER DISCONNECTED"); clientLog("Disconnected from server", 1);
// e.printStackTrace();
return; return;
} }
} }
@@ -112,7 +122,7 @@ public class ClientToServerThread implements Runnable {
/** /**
* Listens for an allocated sourceID and returns it to the server if recieved * Listens for an allocated sourceID and returns it to the server
* @return the sourceID allocated to us by the server * @return the sourceID allocated to us by the server
*/ */
private Integer threeWayHandshake() { private Integer threeWayHandshake() {
@@ -121,14 +131,15 @@ public class ClientToServerThread implements Runnable {
try { try {
ourSourceID = is.read(); ourSourceID = is.read();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); clientLog("Three way handshake failed", 1);
} }
if (ourSourceID != null) { if (ourSourceID != null) {
try { try {
os.write(ourSourceID); os.write(ourSourceID);
return ourSourceID; return ourSourceID;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); clientLog("Three way handshake failed", 1);
return null; return null;
} }
} }
@@ -144,8 +155,7 @@ public class ClientToServerThread implements Runnable {
try { try {
os.write(boatActionMessage.getBuffer()); os.write(boatActionMessage.getBuffer());
} catch (IOException e) { } catch (IOException e) {
clientLog("COULD NOT WRITE TO SERVER", 0); clientLog("Could not write to server", 1);
e.printStackTrace();
} }
} }
@@ -154,7 +164,7 @@ public class ClientToServerThread implements Runnable {
try { try {
socket.close(); socket.close();
} catch (IOException e) { } catch (IOException e) {
clientLog("Failed to close the socket", 0); clientLog("Failed to close the socket", 1);
} }
} }
@@ -165,7 +175,7 @@ public class ClientToServerThread implements Runnable {
currentByte = is.read(); currentByte = is.read();
crcBuffer.write(currentByte); crcBuffer.write(currentByte);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); clientLog("Read byte failed", 1);
} }
if (currentByte == -1){ if (currentByte == -1){
throw new Exception(); throw new Exception();
@@ -75,7 +75,7 @@ public class CanvasController {
private List<MarkGroup> markGroups = new ArrayList<>(); private List<MarkGroup> markGroups = new ArrayList<>();
private List<BoatGroup> boatGroups = new ArrayList<>(); private List<BoatGroup> boatGroups = new ArrayList<>();
private Text FPSdisplay = new Text(); private Text FPSDisplay = new Text();
private Polygon raceBorder = new Polygon(); private Polygon raceBorder = new Polygon();
//FRAME RATE //FRAME RATE
@@ -120,10 +120,10 @@ public class CanvasController {
gc.setGlobalAlpha(0.5); gc.setGlobalAlpha(0.5);
fitMarksToCanvas(); fitMarksToCanvas();
drawGoogleMap(); drawGoogleMap();
FPSdisplay.setLayoutX(5); FPSDisplay.setLayoutX(5);
FPSdisplay.setLayoutY(20); FPSDisplay.setLayoutY(20);
FPSdisplay.setStrokeWidth(2); FPSDisplay.setStrokeWidth(2);
group.getChildren().add(FPSdisplay); group.getChildren().add(FPSDisplay);
group.getChildren().add(raceBorder); group.getChildren().add(raceBorder);
initializeMarks(); initializeMarks();
initializeBoats(); initializeBoats();
@@ -407,10 +407,10 @@ public class CanvasController {
private void drawFps(int fps){ private void drawFps(int fps){
if (raceViewController.isDisplayFps()){ if (raceViewController.isDisplayFps()){
FPSdisplay.setVisible(true); FPSDisplay.setVisible(true);
FPSdisplay.setText(String.format("%d FPS", fps)); FPSDisplay.setText(String.format("%d FPS", fps));
} else { } else {
FPSdisplay.setVisible(false); FPSDisplay.setVisible(false);
} }
} }
@@ -112,6 +112,7 @@ public class LobbyController implements Initializable, Observer{
readyButton.setDisable(true); readyButton.setDisable(true);
} }
// put all javafx objects in lists, so we can iterate though conveniently
imageViews = new ArrayList<>(); imageViews = new ArrayList<>();
Collections.addAll(imageViews, firstImageView, secondImageView, thirdImageView, fourthImageView, Collections.addAll(imageViews, firstImageView, secondImageView, thirdImageView, fourthImageView,
fifthImageView, sixthImageView, seventhImageView, eighthImageView); fifthImageView, sixthImageView, seventhImageView, eighthImageView);
@@ -134,6 +135,13 @@ public class LobbyController implements Initializable, Observer{
clientStateQueryingThread.start(); clientStateQueryingThread.start();
} }
/**
* Observers "ClientStateQueryingRunnable".
* When the clients state has been marked to "race start", the querying thread
* will notify this lobby to change the view
* @param o
* @param arg
*/
@Override @Override
public void update(Observable o, Object arg) { public void update(Observable o, Object arg) {
Platform.runLater(new Runnable() { Platform.runLater(new Runnable() {
@@ -149,6 +157,9 @@ public class LobbyController implements Initializable, Observer{
}); });
} }
/**
* Reset all ListViews and ImageViews according to the current competitors
*/
private void initialiseListView() { private void initialiseListView() {
listViews.forEach(listView -> listView.getItems().clear()); listViews.forEach(listView -> listView.getItems().clear());
imageViews.forEach(gif -> gif.setVisible(false)); imageViews.forEach(gif -> gif.setVisible(false));
@@ -162,6 +173,9 @@ public class LobbyController implements Initializable, Observer{
} }
} }
/**
* Loads preset images into imageViews
*/
private void initialiseImageView() { private void initialiseImageView() {
for (int i = 0; i < MAX_NUM_PLAYERS; i++) { for (int i = 0; i < MAX_NUM_PLAYERS; i++) {
imageViews.get(i).setImage(new Image(getClass().getResourceAsStream("/pics/sail.png"))); imageViews.get(i).setImage(new Image(getClass().getResourceAsStream("/pics/sail.png")));
@@ -195,14 +209,11 @@ public class LobbyController implements Initializable, Observer{
@FXML @FXML
public void readyButtonPressed() { public void readyButtonPressed() {
// setContentPane("/views/RaceView.fxml");
GameState.setCurrentStage(GameStages.RACING); GameState.setCurrentStage(GameStages.RACING);
mainServerThread.startGame(); mainServerThread.startGame();
} }
private void switchToRaceView() { private void switchToRaceView() {
if (!switchedPane) { if (!switchedPane) {
switchedPane = true; switchedPane = true;
@@ -287,6 +287,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
updateWindDirection(); updateWindDirection();
// updateOrder(); // updateOrder();
updateBoatSelectionComboBox(); updateBoatSelectionComboBox();
updateOrder();
}) })
); );
@@ -383,9 +384,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
} }
if (ClientPacketParser.isRaceStarted()) { if (ClientPacketParser.isRaceStarted()) {
/*
for (Yacht boat : ClientPacketParser.getBoatsPos().values()) { for (Yacht boat : ClientPacketParser.getBoatsPos().values()) {
if (participantIDs.contains(boat.getSourceId())) { // check if the boat is racing System.out.println("Hi tjere" + boat.getBoatName());
if (boat.getBoatStatus() == 3) { // 3 is finish status if (participantIDs.contains(boat.getSourceId()) || true
) { // check if the boat is racing
if (boat.getBoatStatus() == 69) { // 3 is finish status
Text textToAdd = new Text(boat.getPosition() + ". " + Text textToAdd = new Text(boat.getPosition() + ". " +
boat.getShortName() + " (Finished)"); boat.getShortName() + " (Finished)");
textToAdd.setFill(Paint.valueOf("#d3d3d3")); textToAdd.setFill(Paint.valueOf("#d3d3d3"));
@@ -397,9 +401,17 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
textToAdd.setFill(Paint.valueOf("#d3d3d3")); textToAdd.setFill(Paint.valueOf("#d3d3d3"));
textToAdd.setStyle(""); textToAdd.setStyle("");
positionVbox.getChildren().add(textToAdd); positionVbox.getChildren().add(textToAdd);
System.out.println("Adding " + textToAdd.getText());
} }
} }
} }
*/
for (Yacht boat : ClientPacketParser.getBoats().values()){
Text textToAdd = new Text(boat.getSourceId() + ". " + boat.getShortName() + " ");
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
textToAdd.setStyle("");
positionVbox.getChildren().add(textToAdd);
}
} else { } else {
for (Yacht boat : ClientPacketParser.getBoats().values()) { for (Yacht boat : ClientPacketParser.getBoats().values()) {
if (participantIDs.contains(boat.getSourceId())) { // check if the boat is racing if (participantIDs.contains(boat.getSourceId())) { // check if the boat is racing
@@ -27,6 +27,9 @@ public class GameState implements Runnable {
private static Boolean isRaceStarted; private static Boolean isRaceStarted;
private static GameStages currentStage; private static GameStages currentStage;
private static long startTime = System.currentTimeMillis();
public GameState(String hostIpAddress) { public GameState(String hostIpAddress) {
windDirection = 180d; windDirection = 180d;
windSpeed = 10000d; windSpeed = 10000d;
@@ -80,9 +83,17 @@ public class GameState implements Runnable {
} }
public static void setCurrentStage(GameStages currentStage) { public static void setCurrentStage(GameStages currentStage) {
if (currentStage == GameStages.RACING){
startTime = System.currentTimeMillis();
}
GameState.currentStage = currentStage; GameState.currentStage = currentStage;
} }
public static long getStartTime(){
return startTime;
}
public static Double getWindDirection() { public static Double getWindDirection() {
return windDirection; return windDirection;
} }
@@ -11,7 +11,10 @@ import java.io.IOException;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.PriorityBlockingQueue;
import java.util.logging.Logger;
/** /**
* A class describing the overall server, which creates and collects server threads for each client * A class describing the overall server, which creates and collects server threads for each client
@@ -133,8 +136,16 @@ public class MainServerThread extends Observable implements Runnable, ClientConn
} }
public void startGame() { public void startGame() {
for (ServerToClientThread serverToClientThread : serverToClientThreads) { Timer t = new Timer();
serverToClientThread.sendRaceStatusMessage();
} t.schedule(new TimerTask() {
@Override
public void run() {
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
serverToClientThread.sendRaceStatusMessage();
}
}
}, 0, 500);
} }
} }
@@ -340,8 +340,7 @@ public class ServerToClientThread implements Runnable, Observer {
public void sendRaceStatusMessage() { public void sendRaceStatusMessage() {
// variables taken from GameServerThread // variables taken from GameServerThread
int TIME_TILL_RACE_START = 20 * 1000;
long startTime = System.currentTimeMillis() + TIME_TILL_RACE_START;
List<BoatSubMessage> boatSubMessages = new ArrayList<>(); List<BoatSubMessage> boatSubMessages = new ArrayList<>();
BoatStatus boatStatus; BoatStatus boatStatus;
@@ -369,7 +368,7 @@ public class ServerToClientThread implements Runnable, Observer {
raceStatus = RaceStatus.WARNING; raceStatus = RaceStatus.WARNING;
} }
sendMessage(new RaceStatusMessage(1, raceStatus, startTime, GameState.getWindDirection(), sendMessage(new RaceStatusMessage(1, raceStatus, GameState.getStartTime(), GameState.getWindDirection(),
GameState.getWindSpeedMMS().longValue(), GameState.getPlayers().size(), GameState.getWindSpeedMMS().longValue(), GameState.getPlayers().size(),
RaceType.MATCH_RACE, 1, boatSubMessages)); RaceType.MATCH_RACE, 1, boatSubMessages));
} }
+9 -9
View File
@@ -20,12 +20,12 @@
<children> <children>
<AnchorPane prefHeight="960.0" prefWidth="250.0" style="-fx-background-color: #2C2c36;" GridPane.rowSpan="3"> <AnchorPane prefHeight="960.0" prefWidth="250.0" style="-fx-background-color: #2C2c36;" GridPane.rowSpan="3">
<children> <children>
<Label layoutX="11.0" layoutY="259.0" text="Team Position" textFill="WHITE" /> <Label layoutX="11.0" layoutY="283.0" text="Team Position" textFill="WHITE" />
<Label layoutX="13.0" layoutY="432.0" text="Settings" textFill="WHITE" /> <Label layoutX="13.0" layoutY="432.0" text="Settings" textFill="WHITE" />
<Label layoutX="11.0" layoutY="14.0" text="Timer" textFill="WHITE" /> <Label layoutX="11.0" layoutY="41.0" text="Timer" textFill="WHITE" />
<Label layoutX="11.0" layoutY="88.0" text="Wind direction" textFill="WHITE" /> <Label layoutX="11.0" layoutY="112.0" text="Wind direction" textFill="WHITE" />
<Circle fx:id="windBackgroundCircle" blendMode="DARKEN" fill="#3dcdc8" layoutX="110.0" layoutY="166.0" radius="35.0" stroke="#d7d7d7" strokeType="INSIDE" strokeWidth="3.0" /> <Circle fx:id="windBackgroundCircle" blendMode="DARKEN" fill="#3dcdc8" layoutX="110.0" layoutY="190.0" radius="35.0" stroke="#d7d7d7" strokeType="INSIDE" strokeWidth="3.0" />
<Text fx:id="windArrowText" fill="#a8a8a8" layoutX="86.0" layoutY="186.0" strokeType="OUTSIDE" strokeWidth="0.0" text="↓"> <Text fx:id="windArrowText" fill="#a8a8a8" layoutX="86.0" layoutY="210.0" strokeType="OUTSIDE" strokeWidth="0.0" text="↓">
<font> <font>
<Font name="AdobeArabic-Regular" size="55.0" /> <Font name="AdobeArabic-Regular" size="55.0" />
</font> </font>
@@ -35,16 +35,16 @@
<Font name="System Bold" size="13.0" /> <Font name="System Bold" size="13.0" />
</font> </font>
</Text> </Text>
<Text fx:id="windSpeedText" fill="#d3d3d3" layoutX="12.0" layoutY="213.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0 Knot" textAlignment="RIGHT"> <Text fx:id="windSpeedText" fill="#d3d3d3" layoutX="12.0" layoutY="237.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0 Knot" textAlignment="RIGHT">
<font> <font>
<Font name="System Bold" size="13.0" /> <Font name="System Bold" size="13.0" />
</font> </font>
</Text> </Text>
<CheckBox fx:id="toggleFps" focusTraversable="false" graphicTextGap="0.0" layoutX="21.0" layoutY="453.0" mnemonicParsing="false" prefHeight="18.0" prefWidth="143.0" selected="true" styleClass="ui-checkbox" text="Show FPS" textFill="WHITE" /> <CheckBox fx:id="toggleFps" focusTraversable="false" graphicTextGap="0.0" layoutX="21.0" layoutY="453.0" mnemonicParsing="false" prefHeight="18.0" prefWidth="143.0" selected="true" styleClass="ui-checkbox" text="Show FPS" textFill="WHITE" />
<VBox fx:id="positionVbox" layoutX="12.0" layoutY="280.0" prefHeight="140.0" prefWidth="200.0" styleClass="text-white" /> <VBox fx:id="positionVbox" layoutX="12.0" layoutY="304.0" prefHeight="116.0" prefWidth="200.0" styleClass="text-white" />
<Pane layoutX="11.0" layoutY="30.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="51.0" prefWidth="193.0"> <Pane layoutX="11.0" layoutY="39.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="51.0" prefWidth="193.0">
<children> <children>
<Text fx:id="timerLabel" fill="#f8f8f8" layoutX="-26.0" layoutY="34.0" strokeType="OUTSIDE" strokeWidth="0.0" text="00:00" textAlignment="CENTER" wrappingWidth="246.0"> <Text fx:id="timerLabel" fill="#f8f8f8" layoutX="-26.0" layoutY="51.0" strokeType="OUTSIDE" strokeWidth="0.0" text="00:00" textAlignment="CENTER" wrappingWidth="246.0">
<font> <font>
<Font size="25.0" /> <Font size="25.0" />
</font> </font>