From a295728e896c41dc82c3220e150f11332b0b1d05 Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Wed, 20 Sep 2017 00:52:06 +1200 Subject: [PATCH] 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