From a295728e896c41dc82c3220e150f11332b0b1d05 Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Wed, 20 Sep 2017 00:52:06 +1200 Subject: [PATCH 01/24] Created encoder and decoder for BoatState messages (HP packets) - Added new MessageType.BOATSTATE enum to support new message type - Modified EncoderFactory and DecoderFactory to support new enum - Verify that original and decoded messages match #story[1291] --- .../MessageDecoders/BoatStateDecoder.java | 38 +++++++++++++++++++ .../MessageDecoders/DecoderFactory.java | 1 + .../MessageDecoders/MessageDecoder.java | 3 +- .../MessageEncoders/BoatStateEncoder.java | 32 ++++++++++++++++ .../MessageEncoders/EncoderFactory.java | 1 + .../main/java/network/Messages/BoatState.java | 31 +++++++++++++++ .../network/Messages/Enums/MessageType.java | 4 +- .../MessageDecoders/BoatStateDecoderTest.java | 33 ++++++++++++++++ 8 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 racevisionGame/src/main/java/network/MessageDecoders/BoatStateDecoder.java create mode 100644 racevisionGame/src/main/java/network/MessageEncoders/BoatStateEncoder.java create mode 100644 racevisionGame/src/main/java/network/Messages/BoatState.java create mode 100644 racevisionGame/src/test/java/network/MessageDecoders/BoatStateDecoderTest.java diff --git a/racevisionGame/src/main/java/network/MessageDecoders/BoatStateDecoder.java b/racevisionGame/src/main/java/network/MessageDecoders/BoatStateDecoder.java new file mode 100644 index 00000000..e543f464 --- /dev/null +++ b/racevisionGame/src/main/java/network/MessageDecoders/BoatStateDecoder.java @@ -0,0 +1,38 @@ +package network.MessageDecoders; + +import network.Exceptions.InvalidMessageException; +import network.Messages.AC35Data; +import network.Messages.BoatState; + +import java.util.Arrays; + +import static network.Utils.ByteConverter.bytesToInt; + +/** + * Decoder for {@link BoatState} messages + */ +public class BoatStateDecoder implements MessageDecoder { + /** + * Decoded BoatState message + */ + private BoatState message; + + @Override + public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException { + byte[] sourceID = Arrays.copyOfRange(encodedMessage, 0, 4); + byte boatHealth = encodedMessage[4]; + + // Unpack bytes into BoatState + this.message = new BoatState( + bytesToInt(sourceID), + boatHealth + ); + + // Return BoatState + return this.message; + } + + public BoatState getMessage() { + return message; + } +} diff --git a/racevisionGame/src/main/java/network/MessageDecoders/DecoderFactory.java b/racevisionGame/src/main/java/network/MessageDecoders/DecoderFactory.java index 24caf97c..3b8964c0 100644 --- a/racevisionGame/src/main/java/network/MessageDecoders/DecoderFactory.java +++ b/racevisionGame/src/main/java/network/MessageDecoders/DecoderFactory.java @@ -59,6 +59,7 @@ public class DecoderFactory { case BOATACTION: return new BoatActionDecoder(); + case BOATSTATE: return new BoatStateDecoder(); default: throw new InvalidMessageTypeException("Unrecognised message type: " + type); } diff --git a/racevisionGame/src/main/java/network/MessageDecoders/MessageDecoder.java b/racevisionGame/src/main/java/network/MessageDecoders/MessageDecoder.java index c20c653f..ed8ba21f 100644 --- a/racevisionGame/src/main/java/network/MessageDecoders/MessageDecoder.java +++ b/racevisionGame/src/main/java/network/MessageDecoders/MessageDecoder.java @@ -18,6 +18,5 @@ public interface MessageDecoder { * @return The decoded message. * @throws InvalidMessageException Thrown if the encoded message is invalid in some way, or cannot be decoded. */ - public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException; - + AC35Data decode(byte[] encodedMessage) throws InvalidMessageException; } diff --git a/racevisionGame/src/main/java/network/MessageEncoders/BoatStateEncoder.java b/racevisionGame/src/main/java/network/MessageEncoders/BoatStateEncoder.java new file mode 100644 index 00000000..e897f18c --- /dev/null +++ b/racevisionGame/src/main/java/network/MessageEncoders/BoatStateEncoder.java @@ -0,0 +1,32 @@ +package network.MessageEncoders; + +import network.Exceptions.InvalidMessageException; +import network.Messages.AC35Data; +import network.Messages.BoatState; + +import java.nio.ByteBuffer; + +import static network.Utils.ByteConverter.intToBytes; + +/** + * Encoder for {@link BoatState} message + */ +public class BoatStateEncoder implements MessageEncoder { + @Override + public byte[] encode(AC35Data message) throws InvalidMessageException { + // Downcast message + BoatState boatState = (BoatState)message; + + //Serialise message + byte[] sourceID = intToBytes(boatState.getSourceID()); + byte boatHealth = (byte)boatState.getBoatHealth(); + + // Pack bytes into string + ByteBuffer boatStateMessage = ByteBuffer.allocate(5); + boatStateMessage.put(sourceID); + boatStateMessage.put(boatHealth); + + // Return byte string + return boatStateMessage.array(); + } +} diff --git a/racevisionGame/src/main/java/network/MessageEncoders/EncoderFactory.java b/racevisionGame/src/main/java/network/MessageEncoders/EncoderFactory.java index d274f435..42093111 100644 --- a/racevisionGame/src/main/java/network/MessageEncoders/EncoderFactory.java +++ b/racevisionGame/src/main/java/network/MessageEncoders/EncoderFactory.java @@ -59,6 +59,7 @@ public class EncoderFactory { case BOATACTION: return new BoatActionEncoder(); + case BOATSTATE: return new BoatStateEncoder(); default: throw new InvalidMessageTypeException("Unrecognised message type: " + type); } diff --git a/racevisionGame/src/main/java/network/Messages/BoatState.java b/racevisionGame/src/main/java/network/Messages/BoatState.java new file mode 100644 index 00000000..f40a5757 --- /dev/null +++ b/racevisionGame/src/main/java/network/Messages/BoatState.java @@ -0,0 +1,31 @@ +package network.Messages; + +import network.Messages.Enums.MessageType; + +/** + * Represents the information in a BoatState message according to protocol meeting + */ +public class BoatState extends AC35Data { + /** + * Source ID of boat described in message + */ + private int sourceID; + /** + * Health between 0-100 of boat with above source ID + */ + private int boatHealth; + + public BoatState(int sourceID, int boatHealth) { + super(MessageType.BOATSTATE); + this.sourceID = sourceID; + this.boatHealth = boatHealth; + } + + public int getSourceID() { + return sourceID; + } + + public int getBoatHealth() { + return boatHealth; + } +} diff --git a/racevisionGame/src/main/java/network/Messages/Enums/MessageType.java b/racevisionGame/src/main/java/network/Messages/Enums/MessageType.java index 0941fd08..15f9e80e 100644 --- a/racevisionGame/src/main/java/network/Messages/Enums/MessageType.java +++ b/racevisionGame/src/main/java/network/Messages/Enums/MessageType.java @@ -43,6 +43,8 @@ public enum MessageType { HOSTED_GAMES_REQUEST(109), + BOATSTATE(103), + NOTAMESSAGE(0); @@ -56,7 +58,7 @@ public enum MessageType { * Creates a MessageType enum from a given primitive integer value, cast to a byte. * @param value Integer, which is cast to byte, to construct from. */ - private MessageType(int value) { + MessageType(int value) { this.value = (byte)value; } diff --git a/racevisionGame/src/test/java/network/MessageDecoders/BoatStateDecoderTest.java b/racevisionGame/src/test/java/network/MessageDecoders/BoatStateDecoderTest.java new file mode 100644 index 00000000..ee0cb646 --- /dev/null +++ b/racevisionGame/src/test/java/network/MessageDecoders/BoatStateDecoderTest.java @@ -0,0 +1,33 @@ +package network.MessageDecoders; + +import network.Exceptions.InvalidMessageException; +import network.MessageEncoders.RaceVisionByteEncoder; +import network.Messages.BoatState; +import org.junit.Before; +import org.junit.Test; + +import static org.testng.Assert.*; + +/** + * Test for the {@link network.Messages.BoatState} encoder and decoder. + */ +public class BoatStateDecoderTest { + private BoatState originalMessage; + private BoatState decodedMessage; + + @Before + public void setUp() throws InvalidMessageException { + originalMessage = new BoatState(0, 100); + + byte[] encodedMessage = RaceVisionByteEncoder.encode(originalMessage); + BoatStateDecoder decoder = new BoatStateDecoder(); + decoder.decode(encodedMessage); + decodedMessage = decoder.getMessage(); + } + + @Test + public void decodingEqualsOriginal() { + assertEquals(originalMessage.getSourceID(), decodedMessage.getSourceID()); + assertEquals(originalMessage.getBoatHealth(), decodedMessage.getBoatHealth()); + } +} \ No newline at end of file From 50d5dd02a2db032c647293a3692e03de28313718 Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Wed, 20 Sep 2017 14:07:50 +1200 Subject: [PATCH 02/24] BoatState message can be received from mock by visualiser - Basic penalties have been made for out of bounds and collisions - RaceServer packages and sends BoatState messages for each boat - ServerConnection routes BoatState messages instead of dropping by default - VisualiserRaceCommandFactory produces BoatStateCommands #story[1291] --- .../src/main/java/mock/model/MockBoat.java | 6 ++--- .../src/main/java/mock/model/MockRace.java | 5 ++++ .../src/main/java/mock/model/RaceLogic.java | 3 --- .../src/main/java/mock/model/RaceServer.java | 25 ++++++++++++++++++ .../src/main/java/shared/model/Boat.java | 26 +++++++++++++++++++ .../src/main/java/shared/model/Mark.java | 1 + .../BoatStateCommand.java | 23 ++++++++++++++++ .../VisualiserRaceCommandFactory.java | 4 +-- .../visualiser/network/ServerConnection.java | 1 + 9 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java diff --git a/racevisionGame/src/main/java/mock/model/MockBoat.java b/racevisionGame/src/main/java/mock/model/MockBoat.java index a5dc98fe..5bf55d50 100644 --- a/racevisionGame/src/main/java/mock/model/MockBoat.java +++ b/racevisionGame/src/main/java/mock/model/MockBoat.java @@ -27,7 +27,7 @@ public class MockBoat extends Boat { * 1: passed only first check * 2: passed first and second check */ - private Integer roundingStatus = 0; + private int roundingStatus = 0; /** * Stores whether the boat is on autoVMG or not @@ -284,8 +284,8 @@ public class MockBoat extends Boat { (this.isStarboardSide(mark1) && this.isPortSide(mark2)); } - public Integer getRoundingStatus() { - return Integer.valueOf(roundingStatus); + public int getRoundingStatus() { + return roundingStatus; } public void increaseRoundingStatus() { diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 9ede32d1..12e2d476 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -377,6 +377,11 @@ public class MockRace extends RaceState { boat.setTimeSinceTackChange(boat.getTimeSinceTackChange() + updatePeriodMilliseconds); } + // Remove one unit of health for every frame spent outside boundary + if(!finish && checkBearingInsideCourse(boat.getBearing(), boat.getPosition())) { + boat.updateHealth(-1); + } + this.updateEstimatedTime(boat); } diff --git a/racevisionGame/src/main/java/mock/model/RaceLogic.java b/racevisionGame/src/main/java/mock/model/RaceLogic.java index 0110716e..a317dcdf 100644 --- a/racevisionGame/src/main/java/mock/model/RaceLogic.java +++ b/racevisionGame/src/main/java/mock/model/RaceLogic.java @@ -173,12 +173,9 @@ public class RaceLogic implements RunnableWithFramePeriod, Observer { race.updatePosition(boat, framePeriod, race.getRaceClock().getDurationMilli()); if(race.getColliderRegistry().rayCast(boat)){ - //System.out.println("Collision!"); //Add boat to list collisionBoats.add(boat); } - - //System.out.println(race.getColliderRegistry().rayCast(boat)); } diff --git a/racevisionGame/src/main/java/mock/model/RaceServer.java b/racevisionGame/src/main/java/mock/model/RaceServer.java index 7f213a72..c52fbb08 100644 --- a/racevisionGame/src/main/java/mock/model/RaceServer.java +++ b/racevisionGame/src/main/java/mock/model/RaceServer.java @@ -71,6 +71,9 @@ public class RaceServer { //Parse the boat locations. snapshotMessages.addAll(parseBoatLocations()); + //Parse the boat states + snapshotMessages.addAll(parseBoatStates()); + //Parse the marks. snapshotMessages.addAll(parseMarks()); @@ -250,7 +253,29 @@ public class RaceServer { } + /** + * Generates BoatState messages for every boat in the race + * @return list of BoatState messages + */ + private List parseBoatStates() { + List boatStates = new ArrayList<>(); + for(MockBoat boat: race.getBoats()) { + boatStates.add(parseIndividualBoatState(boat)); + } + return boatStates; + } + /** + * Creates a BoatState message for the current state of the given boat + * @param boat to generate message for + * @return BoatState message + */ + private BoatState parseIndividualBoatState(MockBoat boat) { + return new BoatState( + boat.getSourceID(), + boat.getHealth() + ); + } /** * Parses the race status, and returns it. diff --git a/racevisionGame/src/main/java/shared/model/Boat.java b/racevisionGame/src/main/java/shared/model/Boat.java index edbba025..0686d127 100644 --- a/racevisionGame/src/main/java/shared/model/Boat.java +++ b/racevisionGame/src/main/java/shared/model/Boat.java @@ -103,6 +103,11 @@ public class Boat extends Collider { */ private boolean isColliding = false; + /** + * Amount of health boat currently has, between 0 and 100 + */ + private int health; + /** * Constructs a boat object with a given sourceID, name, country/team abbreviation, and polars table. * @@ -113,6 +118,7 @@ public class Boat extends Collider { public Boat(int sourceID, String name, String country) { this.sourceID = sourceID; + this.health = 100; this.setName(name); this.setCountry(country); @@ -419,6 +425,8 @@ public class Boat extends Collider { @Override public void onCollisionEnter(Collision e) { if(e.getBearing().degrees() > 270 || e.getBearing().degrees() < 90) { + // Deplete health + e.getBoat().updateHealth(-5); // Notify observers of collision this.setChanged(); notifyObservers(e); @@ -432,4 +440,22 @@ public class Boat extends Collider { public void setColliding(boolean colliding) { isColliding = colliding; } + + public int getHealth() { + return health; + } + + public void setHealth(int health) { + this.health = health; + } + + /** + * Add a given amount of HP to boat health + * @param delta amount of HP to add + */ + public void updateHealth(int delta) { + health += delta; + if(health < 0) health = 0; + else if(health > 100) health = 100; + } } diff --git a/racevisionGame/src/main/java/shared/model/Mark.java b/racevisionGame/src/main/java/shared/model/Mark.java index fd46112f..83ee1168 100644 --- a/racevisionGame/src/main/java/shared/model/Mark.java +++ b/racevisionGame/src/main/java/shared/model/Mark.java @@ -97,6 +97,7 @@ public class Mark extends Collider{ @Override public void onCollisionEnter(Collision e) { + e.getBoat().updateHealth(-10); this.setChanged(); notifyObservers(e); } diff --git a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java new file mode 100644 index 00000000..e691a35b --- /dev/null +++ b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java @@ -0,0 +1,23 @@ +package visualiser.Commands.VisualiserRaceCommands; + +import mock.model.commandFactory.Command; +import network.Messages.BoatState; +import visualiser.model.VisualiserRaceState; + +/** + * Created by connortaylorbrown on 20/09/17. + */ +public class BoatStateCommand implements Command { + private BoatState boatState; + private VisualiserRaceState visualiserRace; + + public BoatStateCommand(BoatState boatState, VisualiserRaceState visualiserRace) { + this.boatState = boatState; + this.visualiserRace = visualiserRace; + } + + @Override + public void execute() { + System.out.println(boatState.getBoatHealth()); + } +} diff --git a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/VisualiserRaceCommandFactory.java b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/VisualiserRaceCommandFactory.java index 0e2f3d15..825d3397 100644 --- a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/VisualiserRaceCommandFactory.java +++ b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/VisualiserRaceCommandFactory.java @@ -24,7 +24,6 @@ public class VisualiserRaceCommandFactory { switch (message.getType()) { case BOATLOCATION: - //System.out.println("Boat location received"); return new BoatLocationCommand((BoatLocation) message, visualiserRace); case RACESTATUS: return new RaceStatusCommand((RaceStatus) message, visualiserRace); @@ -36,7 +35,8 @@ public class VisualiserRaceCommandFactory { case YACHTEVENTCODE: return new BoatCollisionCommand((YachtEvent) message, visualiserRace); - + case BOATSTATE: + return new BoatStateCommand((BoatState) message, visualiserRace); default: throw new CommandConstructionException("Could not create VisualiserRaceCommand. Unrecognised or unsupported MessageType: " + message.getType()); diff --git a/racevisionGame/src/main/java/visualiser/network/ServerConnection.java b/racevisionGame/src/main/java/visualiser/network/ServerConnection.java index 8780a676..2e97f36d 100644 --- a/racevisionGame/src/main/java/visualiser/network/ServerConnection.java +++ b/racevisionGame/src/main/java/visualiser/network/ServerConnection.java @@ -297,6 +297,7 @@ public class ServerConnection implements RunnableWithFramePeriod { this.messageRouter.addRoute(MessageType.MARKROUNDING, incomingMessages); this.messageRouter.addRoute(MessageType.XMLMESSAGE, incomingMessages); this.messageRouter.addRoute(MessageType.ASSIGN_PLAYER_BOAT, incomingMessages); + this.messageRouter.addRoute(MessageType.BOATSTATE, incomingMessages); this.messageRouter.removeDefaultRoute(); //We no longer want to keep un-routed messages. From 7eb59cdcfc6d6ad44a0565bf02ae8f02908f2e2d Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Wed, 20 Sep 2017 14:18:39 +1200 Subject: [PATCH 03/24] Allowed fractional health deductions per frame - Fixed boundary penalty system #story[1291] --- racevisionGame/src/main/java/mock/model/MockRace.java | 4 ++-- racevisionGame/src/main/java/mock/model/RaceServer.java | 2 +- racevisionGame/src/main/java/shared/model/Boat.java | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/racevisionGame/src/main/java/mock/model/MockRace.java b/racevisionGame/src/main/java/mock/model/MockRace.java index 12e2d476..f8ca3720 100644 --- a/racevisionGame/src/main/java/mock/model/MockRace.java +++ b/racevisionGame/src/main/java/mock/model/MockRace.java @@ -378,8 +378,8 @@ public class MockRace extends RaceState { } // Remove one unit of health for every frame spent outside boundary - if(!finish && checkBearingInsideCourse(boat.getBearing(), boat.getPosition())) { - boat.updateHealth(-1); + if(!finish && !GPSCoordinate.isInsideBoundary(boat.getPosition(), getBoundary())) { + boat.updateHealth(-0.1); } this.updateEstimatedTime(boat); diff --git a/racevisionGame/src/main/java/mock/model/RaceServer.java b/racevisionGame/src/main/java/mock/model/RaceServer.java index c52fbb08..894831fd 100644 --- a/racevisionGame/src/main/java/mock/model/RaceServer.java +++ b/racevisionGame/src/main/java/mock/model/RaceServer.java @@ -273,7 +273,7 @@ public class RaceServer { private BoatState parseIndividualBoatState(MockBoat boat) { return new BoatState( boat.getSourceID(), - boat.getHealth() + (int)boat.getHealth() ); } diff --git a/racevisionGame/src/main/java/shared/model/Boat.java b/racevisionGame/src/main/java/shared/model/Boat.java index 0686d127..99871678 100644 --- a/racevisionGame/src/main/java/shared/model/Boat.java +++ b/racevisionGame/src/main/java/shared/model/Boat.java @@ -106,7 +106,7 @@ public class Boat extends Collider { /** * Amount of health boat currently has, between 0 and 100 */ - private int health; + private double health; /** * Constructs a boat object with a given sourceID, name, country/team abbreviation, and polars table. @@ -441,11 +441,11 @@ public class Boat extends Collider { isColliding = colliding; } - public int getHealth() { + public double getHealth() { return health; } - public void setHealth(int health) { + public void setHealth(double health) { this.health = health; } @@ -453,7 +453,7 @@ public class Boat extends Collider { * Add a given amount of HP to boat health * @param delta amount of HP to add */ - public void updateHealth(int delta) { + public void updateHealth(double delta) { health += delta; if(health < 0) health = 0; else if(health > 100) health = 100; From 0d89574c1fdd86cc3fc99e001e4993fe64606cb3 Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Wed, 20 Sep 2017 14:29:31 +1200 Subject: [PATCH 04/24] RaceViewController listens to health changes on the local player's boat #story[1291] --- .../BoatStateCommand.java | 11 ++++++++-- .../Controllers/RaceViewController.java | 5 +++++ .../java/visualiser/model/VisualiserBoat.java | 21 +++++++++++++++---- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java index e691a35b..1362e647 100644 --- a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java +++ b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java @@ -2,10 +2,12 @@ package visualiser.Commands.VisualiserRaceCommands; import mock.model.commandFactory.Command; import network.Messages.BoatState; +import shared.exceptions.BoatNotFoundException; +import visualiser.model.VisualiserBoat; import visualiser.model.VisualiserRaceState; /** - * Created by connortaylorbrown on 20/09/17. + * Updates boats on visualiser when their health changes */ public class BoatStateCommand implements Command { private BoatState boatState; @@ -18,6 +20,11 @@ public class BoatStateCommand implements Command { @Override public void execute() { - System.out.println(boatState.getBoatHealth()); + try { + VisualiserBoat boat = visualiserRace.getBoat(boatState.getSourceID()); + boat.setHealth(boatState.getBoatHealth()); + } catch (BoatNotFoundException e) { + e.printStackTrace(); + } } } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java index c2153c1f..54491e35 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java @@ -334,6 +334,11 @@ public class RaceViewController extends Controller { boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr))); boat.hasCollidedProperty().addListener((o, prev, curr) -> Platform.runLater(() -> showCollision(boat, shockwave))); + if(boat.getSourceID() == race.getVisualiserRaceState().getPlayerBoatID()) { + boat.healthProperty().addListener((o, prev, curr) -> { + System.out.println(curr); + }); + } } // Fix initial bird's-eye position view3D.updatePivot(new Translate(250, 0, 210)); diff --git a/racevisionGame/src/main/java/visualiser/model/VisualiserBoat.java b/racevisionGame/src/main/java/visualiser/model/VisualiserBoat.java index 1184197c..26ae085d 100644 --- a/racevisionGame/src/main/java/visualiser/model/VisualiserBoat.java +++ b/racevisionGame/src/main/java/visualiser/model/VisualiserBoat.java @@ -1,9 +1,6 @@ package visualiser.model; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.*; import javafx.scene.paint.Color; import network.Messages.Enums.BoatStatusEnum; import shared.model.*; @@ -65,6 +62,7 @@ public class VisualiserBoat extends Boat { private ObjectProperty positionProperty; private ObjectProperty bearingProperty; private BooleanProperty hasCollided; + private IntegerProperty healthProperty; /** @@ -78,6 +76,7 @@ public class VisualiserBoat extends Boat { this.color = color; this.hasCollided = new SimpleBooleanProperty(false); + this.healthProperty = new SimpleIntegerProperty(100); } @@ -281,4 +280,18 @@ public class VisualiserBoat extends Boat { public void setHasCollided(boolean hasCollided) { this.hasCollided.set(hasCollided); } + + public IntegerProperty healthProperty() { + return healthProperty; + } + + @Override + public double getHealth() { + return healthProperty.get(); + } + + @Override + public void setHealth(double healthProperty) { + this.healthProperty.set((int)healthProperty); + } } From 23040ecff4c3a7dfe43133de204884b6ab6fc88a Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Wed, 20 Sep 2017 14:34:22 +1200 Subject: [PATCH 05/24] Created separate listeners for all boats' and player boat health #story[1291] --- .../main/java/visualiser/Controllers/RaceViewController.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java index 54491e35..5e5d7ad5 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java @@ -334,9 +334,12 @@ public class RaceViewController extends Controller { boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr))); boat.hasCollidedProperty().addListener((o, prev, curr) -> Platform.runLater(() -> showCollision(boat, shockwave))); + boat.healthProperty().addListener((o, prev, curr) -> { + System.out.println("Tab view: " + curr); + }); if(boat.getSourceID() == race.getVisualiserRaceState().getPlayerBoatID()) { boat.healthProperty().addListener((o, prev, curr) -> { - System.out.println(curr); + System.out.println("Tomato: " + curr); }); } } From b0bc7f50f233889f6ab5234c94cfa8f48a91f0e5 Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Wed, 20 Sep 2017 18:22:14 +1200 Subject: [PATCH 06/24] Updated FXMLs to add depleting tomato - Tab view now contains health column - BoatStateCommand now fails silently if command is received before race state is set up #story[1291] --- .../BoatStateCommand.java | 2 +- .../Controllers/RaceViewController.java | 22 ++++++----- .../resources/visualiser/images/tomato.png | Bin 0 -> 5610 bytes .../visualiser/scenes/newRaceView.fxml | 37 ++++++++++++------ 4 files changed, 37 insertions(+), 24 deletions(-) create mode 100644 racevisionGame/src/main/resources/visualiser/images/tomato.png diff --git a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java index 1362e647..85a1e00e 100644 --- a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java +++ b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatStateCommand.java @@ -24,7 +24,7 @@ public class BoatStateCommand implements Command { VisualiserBoat boat = visualiserRace.getBoat(boatState.getSourceID()); boat.setHealth(boatState.getBoatHealth()); } catch (BoatNotFoundException e) { - e.printStackTrace(); + // Fail silently } } } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java index 5e5d7ad5..8b8daf4f 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java @@ -85,14 +85,15 @@ public class RaceViewController extends Controller { private @FXML Label timeZone; private @FXML CheckBox showFPS; private @FXML TableView boatInfoTable; - private @FXML TableColumn boatPlacingColumn; private @FXML TableColumn boatTeamColumn; private @FXML TableColumn boatMarkColumn; private @FXML TableColumn boatSpeedColumn; + private @FXML TableColumn boatHealthColumn; private @FXML LineChart sparklineChart; private @FXML Label tutorialText; private @FXML AnchorPane infoWrapper; private @FXML AnchorPane lineChartWrapper; + private @FXML GridPane playerHealthContainer; /** * Displays a specified race. @@ -334,12 +335,9 @@ public class RaceViewController extends Controller { boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr))); boat.hasCollidedProperty().addListener((o, prev, curr) -> Platform.runLater(() -> showCollision(boat, shockwave))); - boat.healthProperty().addListener((o, prev, curr) -> { - System.out.println("Tab view: " + curr); - }); if(boat.getSourceID() == race.getVisualiserRaceState().getPlayerBoatID()) { boat.healthProperty().addListener((o, prev, curr) -> { - System.out.println("Tomato: " + curr); + System.out.println(curr); }); } } @@ -529,13 +527,17 @@ public class RaceViewController extends Controller { // set table data boatInfoTable.setItems(sortedBoats); boatTeamColumn.setCellValueFactory( - cellData -> cellData.getValue().nameProperty()); + cellData -> cellData.getValue().nameProperty() + ); boatSpeedColumn.setCellValueFactory( - cellData -> cellData.getValue().currentSpeedProperty()); + cellData -> cellData.getValue().currentSpeedProperty() + ); boatMarkColumn.setCellValueFactory( - cellData -> cellData.getValue().legProperty()); - boatPlacingColumn.setCellValueFactory( - cellData -> cellData.getValue().placingProperty()); + cellData -> cellData.getValue().legProperty() + ); + boatHealthColumn.setCellValueFactory( + cellData -> cellData.getValue().healthProperty() + ); //Kind of ugly, but allows for formatting an observed speed. boatSpeedColumn.setCellFactory( diff --git a/racevisionGame/src/main/resources/visualiser/images/tomato.png b/racevisionGame/src/main/resources/visualiser/images/tomato.png new file mode 100644 index 0000000000000000000000000000000000000000..92cf4c1d4a3c72091823e525d9a77c9c4d1b0442 GIT binary patch literal 5610 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 E0mGP=vH$=8 literal 0 HcmV?d00001 diff --git a/racevisionGame/src/main/resources/visualiser/scenes/newRaceView.fxml b/racevisionGame/src/main/resources/visualiser/scenes/newRaceView.fxml index 76195416..3a1f61e9 100644 --- a/racevisionGame/src/main/resources/visualiser/scenes/newRaceView.fxml +++ b/racevisionGame/src/main/resources/visualiser/scenes/newRaceView.fxml @@ -3,26 +3,26 @@ - - - - - - - - - + + + + + + + + + @@ -103,6 +103,17 @@