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