mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Fixed some weird bug with the messages package, trying to add some small QoL changes with potential interaction bugs with the customization/lobby menu.
tags : #story[1142]
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by kre39 on 12/07/17.
|
||||
*/
|
||||
public enum BoatAction {
|
||||
|
||||
VMG(1),
|
||||
SAILS_IN(2),
|
||||
SAILS_OUT(3),
|
||||
TACK_GYBE(4),
|
||||
UPWIND(5),
|
||||
DOWNWIND(6),
|
||||
MAINTAIN_HEADING(7);
|
||||
|
||||
private final int type;
|
||||
private static final Map<Integer, BoatAction> intToTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (BoatAction type : BoatAction.values()) {
|
||||
intToTypeMap.put(type.getValue(), type);
|
||||
}
|
||||
}
|
||||
|
||||
BoatAction(int type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static BoatAction getType(int value) {
|
||||
return intToTypeMap.get(value);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* Created by kre39 on 12/07/17.
|
||||
*/
|
||||
public class BoatActionMessage extends Message{
|
||||
private final MessageType MESSAGE_TYPE = MessageType.BOAT_ACTION;
|
||||
private final int MESSAGE_SIZE = 1;
|
||||
private BoatAction actionType;
|
||||
|
||||
public BoatActionMessage(BoatAction actionType) {
|
||||
this.actionType = actionType;
|
||||
setHeader(new Header(MessageType.BOAT_ACTION, 0, (short) 1)); // the second variable is the source id
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
// Write message fields
|
||||
putInt(actionType.getValue(), 1);
|
||||
writeCRC();
|
||||
rewind();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_SIZE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
public class BoatLocationMessage extends Message {
|
||||
|
||||
private final int MESSAGE_SIZE = 56;
|
||||
|
||||
private long messageVersionNumber;
|
||||
private long time;
|
||||
private long sourceId;
|
||||
private long sequenceNum;
|
||||
private DeviceType deviceType;
|
||||
private double latitude;
|
||||
private double longitude;
|
||||
private long altitude;
|
||||
private Double heading;
|
||||
private long pitch;
|
||||
private long roll;
|
||||
private long boatSpeed;
|
||||
private long COG;
|
||||
private long SOG;
|
||||
private long apparentWindSpeed;
|
||||
private long apparentWindAngle;
|
||||
private long trueWindSpeed;
|
||||
private long trueWindDirection;
|
||||
private long trueWindAngle;
|
||||
private long currentDrift;
|
||||
private long currentSet;
|
||||
private long rudderAngle;
|
||||
|
||||
/**
|
||||
* Describes the location, altitude and sensor data from the boat.
|
||||
*
|
||||
* @param sourceId ID of the boat
|
||||
* @param sequenceNum Sequence number of the message
|
||||
* @param latitude The boats latitude
|
||||
* @param longitude The boats longitude
|
||||
* @param heading The boats heading
|
||||
* @param boatSpeed The boats speed
|
||||
*/
|
||||
public BoatLocationMessage(int sourceId, int sequenceNum, double latitude, double longitude,
|
||||
double heading, long boatSpeed) {
|
||||
messageVersionNumber = 1;
|
||||
time = System.currentTimeMillis();
|
||||
this.sourceId = sourceId;
|
||||
this.sequenceNum = sequenceNum;
|
||||
this.deviceType = DeviceType.RACING_YACHT;
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
this.altitude = 0;
|
||||
this.heading = heading;
|
||||
this.pitch = 0;
|
||||
this.roll = 0;
|
||||
this.boatSpeed = boatSpeed;
|
||||
this.COG = 2;
|
||||
this.SOG = boatSpeed;
|
||||
this.apparentWindSpeed = 0;
|
||||
this.apparentWindAngle = 0;
|
||||
this.trueWindSpeed = 0;
|
||||
this.trueWindDirection = 0;
|
||||
this.trueWindAngle = 0;
|
||||
this.currentDrift = 0;
|
||||
this.currentSet = 0;
|
||||
this.rudderAngle = 0;
|
||||
|
||||
setHeader(new Header(MessageType.BOAT_LOCATION, 1, (short) getSize()));
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
long headingToSend = (long) ((heading / 360.0) * 65535.0);
|
||||
|
||||
putByte((byte) messageVersionNumber);
|
||||
putInt(time, 6);
|
||||
putInt((int) sourceId, 4);
|
||||
putUnsignedInt((int) sequenceNum, 4);
|
||||
putByte((byte) deviceType.getCode());
|
||||
putInt((int) latLonToBinaryPackedLong(latitude), 4);
|
||||
putInt((int) latLonToBinaryPackedLong(longitude), 4);
|
||||
putInt((int) altitude, 4);
|
||||
putInt(headingToSend, 2);
|
||||
putInt((int) pitch, 2);
|
||||
putInt((int) roll, 2);
|
||||
putInt((int) boatSpeed, 2);
|
||||
putUnsignedInt((int) COG, 2);
|
||||
putUnsignedInt((int) SOG, 2);
|
||||
putUnsignedInt((int) apparentWindSpeed, 2);
|
||||
putInt((int) apparentWindAngle, 2);
|
||||
putUnsignedInt((int) trueWindSpeed, 2);
|
||||
putUnsignedInt((int) trueWindDirection, 2);
|
||||
putInt((int) trueWindAngle, 2);
|
||||
putUnsignedInt((int) currentDrift, 2);
|
||||
putUnsignedInt((int) currentSet, 2);
|
||||
putInt((int) rudderAngle, 2);
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert binary latitude or longitude to floating point number
|
||||
*
|
||||
* @param binaryPackedLatLon Binary packed lat OR lon
|
||||
* @return Floating point lat/lon
|
||||
*/
|
||||
public static double binaryPackedToLatLon(long binaryPackedLatLon) {
|
||||
return (double) binaryPackedLatLon * 180.0 / 2147483648.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert binary packed heading to floating point number
|
||||
*
|
||||
* @param binaryPackedHeading Binary packed heading
|
||||
* @return heading as a decimal
|
||||
*/
|
||||
public static double binaryPackedHeadingToDouble(long binaryPackedHeading) {
|
||||
return (double) binaryPackedHeading * 360.0 / 65536.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert binary packed wind angle to floating point number
|
||||
*
|
||||
* @param binaryPackedWindAngle Binary packed wind angle
|
||||
* @return wind angle as a decimal
|
||||
*/
|
||||
public static double binaryPackedWindAngleToDouble(long binaryPackedWindAngle) {
|
||||
return (double) binaryPackedWindAngle * 180.0 / 32768.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a latitude or longitude to a binary packed long
|
||||
*
|
||||
* @param latLon A floating point latitude/longitude
|
||||
* @return A binary packed lat/lon
|
||||
*/
|
||||
public static long latLonToBinaryPackedLong(double latLon) {
|
||||
return (long) ((536870912 * latLon) / 45);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a heading to a binary packed long
|
||||
*
|
||||
* @param heading A floating point heading
|
||||
* @return A binary packed heading
|
||||
*/
|
||||
public static long headingToBinaryPackedLong(double heading) {
|
||||
return (long) ((8192 * heading) / 45);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a wind angle to a binary packed long
|
||||
*
|
||||
* @param windAngle Floating point wind angle
|
||||
* @return A binary packed wind angle
|
||||
*/
|
||||
public static long windAngleToBinaryPackedLong(double windAngle) {
|
||||
return (long) ((8192 * windAngle) / 45);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_SIZE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* The current status of a boat
|
||||
*/
|
||||
public enum BoatStatus {
|
||||
UNDEFINED(0),
|
||||
PRESTART(1),
|
||||
RACING(2),
|
||||
FINISHED(3),
|
||||
DNS(4),
|
||||
DNF(5),
|
||||
DSQ(6),
|
||||
CS(7);
|
||||
|
||||
private long code;
|
||||
|
||||
BoatStatus(long code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public long getCode(){
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* The status of each boat, sent within a race status message
|
||||
*/
|
||||
public class BoatSubMessage{
|
||||
private final int MESSAGE_SIZE = 20;
|
||||
|
||||
private long sourceId;
|
||||
private BoatStatus boatStatus;
|
||||
private long legNumber;
|
||||
private long numberPenaltiesAwarded;
|
||||
private long numberPenaltiesServed;
|
||||
private long estimatedTimeAtNextMark;
|
||||
private long estimatedTimeAtFinish;
|
||||
private ByteBuffer buff = ByteBuffer.allocate(getSize());
|
||||
private int buffPos = 0;
|
||||
|
||||
/**
|
||||
* Boat Sub message from section 4.2 of the AC35 streaming data interface spec
|
||||
* @param sourceId The source ID of the boat
|
||||
* @param boatStatus The boats status
|
||||
* @param legNumber The leg the boat is on (0= prestart, 1=start to first mark etc)
|
||||
* @param numberPenaltiesAwarded The number of penalties awarded to the boat
|
||||
* @param numberPenaltiesServed The number of penalties served to the boat
|
||||
* @param estimatedTimeAtFinish The estimated time (UTC) the boat will finish the race
|
||||
* @param estimatedTimeAtNextMark The estimated time (UTC) the boat will arrive at the next mark
|
||||
*/
|
||||
public BoatSubMessage(long sourceId, BoatStatus boatStatus, long legNumber, long numberPenaltiesAwarded, long numberPenaltiesServed,
|
||||
long estimatedTimeAtFinish, long estimatedTimeAtNextMark){
|
||||
this.sourceId = sourceId;
|
||||
this.boatStatus = boatStatus;
|
||||
this.legNumber = legNumber;
|
||||
this.numberPenaltiesAwarded = numberPenaltiesAwarded;
|
||||
this.numberPenaltiesServed = numberPenaltiesServed;
|
||||
this.estimatedTimeAtFinish = estimatedTimeAtFinish;
|
||||
this.estimatedTimeAtNextMark = estimatedTimeAtNextMark;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The size of this message in bytes
|
||||
*/
|
||||
public int getSize(){
|
||||
return MESSAGE_SIZE;
|
||||
}
|
||||
|
||||
private void putInBuffer(byte[] bytes, long val){
|
||||
byte[] tmp = bytes.clone();
|
||||
Message.reverse(tmp);
|
||||
|
||||
buff.put(tmp);
|
||||
buffPos += tmp.length;
|
||||
buff.position(buffPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a ByteBuffer containing this boat status message
|
||||
*/
|
||||
public ByteBuffer getByteBuffer(){
|
||||
// Source ID, 4 bytes
|
||||
putInBuffer(Message.intToByteArray(sourceId, 4), 4);
|
||||
|
||||
// Boat Status, 1 byte
|
||||
putInBuffer(ByteBuffer.allocate(1).put((byte) (boatStatus.getCode() & 0xff)).array(), 1);
|
||||
|
||||
// Leg number, 1 byte
|
||||
putInBuffer(ByteBuffer.allocate(1).put((byte) (legNumber & 0xff)).array(), 1);
|
||||
|
||||
// Number of penalties awarded, 1 byte
|
||||
putInBuffer(ByteBuffer.allocate(1).put((byte) (numberPenaltiesAwarded & 0xff)).array(), 1);
|
||||
|
||||
// Number of penalties served, 1 byte
|
||||
putInBuffer(ByteBuffer.allocate(1).put((byte) (numberPenaltiesServed & 0xff)).array(), 1);
|
||||
|
||||
// Estimated time at next mark, 6 bytes
|
||||
putInBuffer(Message.intToByteArray((int) estimatedTimeAtNextMark, 6),6);
|
||||
|
||||
// Estimated time at finish, 6 bytes
|
||||
putInBuffer(Message.intToByteArray((int) estimatedTimeAtFinish, 6), 6);
|
||||
|
||||
return buff;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
|
||||
public class ChatterMessage extends Message {
|
||||
|
||||
private final long MESSAGE_VERSION_NUMBER = 1;
|
||||
private final int MESSAGE_SIZE = 3;
|
||||
private int message_type;
|
||||
private int message_size = 21;
|
||||
private String message;
|
||||
|
||||
public ChatterMessage(int message_type, int message_size, String message) {
|
||||
this.message_type = message_type;
|
||||
this.message_size = message_size;
|
||||
this.message = message;
|
||||
|
||||
setHeader(new Header(MessageType.CHATTER_TEXT, 1, (short) getSize()));
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
putByte((byte) MESSAGE_VERSION_NUMBER);
|
||||
putInt(message_type, 1);
|
||||
putInt(message_size, 1);
|
||||
putBytes(message.getBytes());
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_SIZE + message_size;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
public enum ClientType {
|
||||
SPECTATOR(0x00),
|
||||
PLAYER(0x01),
|
||||
CONTROL_TUTORIAL(0x02),
|
||||
GHOST_MODE(0x03);
|
||||
|
||||
private int type;
|
||||
|
||||
ClientType(int type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getCode(){
|
||||
return type;
|
||||
}
|
||||
|
||||
public static ClientType getClientType(int typeCode){
|
||||
switch (typeCode){
|
||||
case 0x00:
|
||||
return SPECTATOR;
|
||||
case 0x01:
|
||||
return PLAYER;
|
||||
case 0x02:
|
||||
return CONTROL_TUTORIAL;
|
||||
case 0x03:
|
||||
return GHOST_MODE;
|
||||
default:
|
||||
return PLAYER;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
// TODO: 14/08/17 ajm412: this may eventually need adjusting due to conforming to the agreed spec.
|
||||
public class CustomizeRequestMessage extends Message {
|
||||
|
||||
|
||||
private static int MESSAGE_LENGTH = 6;
|
||||
|
||||
//Message fields
|
||||
private CustomizeRequestType customizeType;
|
||||
private Integer payloadLength;
|
||||
|
||||
public CustomizeRequestMessage(CustomizeRequestType customizeType, double sourceID,
|
||||
byte[] payload) {
|
||||
payloadLength = payload.length;
|
||||
setHeader(new Header(MessageType.CUSTOMIZATION_REQUEST, 1, (short) getSize()));
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
|
||||
putInt((int) sourceID, 4);
|
||||
putInt((int) customizeType.getType(), 2);
|
||||
putBytes(payload);
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_LENGTH + payloadLength; // placeholder
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
// TODO: 14/08/17 ajm412: this may eventually need adjusting due to conforming to the agreed spec.
|
||||
public enum CustomizeRequestType {
|
||||
NAME(0x00),
|
||||
COLOR(0x01),
|
||||
SHAPE(0x02);
|
||||
|
||||
private int type;
|
||||
|
||||
CustomizeRequestType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
int getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public static CustomizeRequestType getRequestType(int typeCode) {
|
||||
switch (typeCode) {
|
||||
case 0x00:
|
||||
return NAME;
|
||||
case 0x01:
|
||||
return COLOR;
|
||||
case 0x02:
|
||||
return SHAPE;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* Created by ajm412 on 14/08/17.
|
||||
*/
|
||||
public class CustomizeResponseMessage extends Message {
|
||||
|
||||
private static int MESSAGE_LENGTH = 2;
|
||||
|
||||
public CustomizeResponseMessage(CustomizeResponseType responseType) {
|
||||
setHeader(new Header(MessageType.CUSTOMIZATION_RESPONSE, 1, (short) getSize()));
|
||||
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
putInt(responseType.getType(), 2);
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_LENGTH; // placeholder
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
// TODO: 14/08/17 ajm412: this may eventually need adjusting due to conforming to the agreed spec.
|
||||
public enum CustomizeResponseType {
|
||||
SUCCESS(0x00),
|
||||
FAILURE(0x01),
|
||||
FAILURE_MALFORMED_DATA(0x02),
|
||||
FAILURE_INCOMPATIBLE(0x03);
|
||||
|
||||
private int type;
|
||||
|
||||
CustomizeResponseType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
int getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public static CustomizeResponseType getResponseType(int typeCode) {
|
||||
switch (typeCode) {
|
||||
case 0x00:
|
||||
return SUCCESS;
|
||||
case 0x01:
|
||||
return FAILURE;
|
||||
case 0x02:
|
||||
return FAILURE_MALFORMED_DATA;
|
||||
case 0x03:
|
||||
return FAILURE_INCOMPATIBLE;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
public enum DeviceType {
|
||||
UNKNOWN(0),
|
||||
RACING_YACHT(1);
|
||||
|
||||
private long code;
|
||||
|
||||
DeviceType(long code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public long getCode(){
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class Header {
|
||||
// From API spec
|
||||
private final int syncByte1 = 0x47;
|
||||
private final int syncByte2 = 0x83;
|
||||
|
||||
private MessageType messageType;
|
||||
private int timeStamp;
|
||||
private int sourceId;
|
||||
private short messageLength;
|
||||
private static final int MESSAGE_LEN = 15;
|
||||
private ByteBuffer buff;
|
||||
private int buffPos;
|
||||
|
||||
/**
|
||||
* Message Header from section 3.2 of the AC35 Streaming
|
||||
* Data spec
|
||||
* @param messageType The type of the message following this header
|
||||
* @param sourceId The message source (as defined in the spec)
|
||||
* @param messageLength The length of the message following this header
|
||||
*/
|
||||
public Header(MessageType messageType, int sourceId, Short messageLength){
|
||||
this.messageType = messageType;
|
||||
this.sourceId = sourceId;
|
||||
this.messageLength = messageLength;
|
||||
timeStamp = (int) (System.currentTimeMillis() / 1000L);
|
||||
buff = ByteBuffer.allocate(MESSAGE_LEN);
|
||||
buffPos = 0;
|
||||
}
|
||||
|
||||
private void putInBuffer(byte[] bytes, long val){
|
||||
byte[] tmp = bytes.clone();
|
||||
Message.reverse(tmp);
|
||||
|
||||
buff.put(tmp);
|
||||
buffPos += tmp.length;
|
||||
buff.position(buffPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the buffer
|
||||
*/
|
||||
public void reset(){
|
||||
buffPos = 0;
|
||||
buff.clear();
|
||||
buff.position(buffPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a ByteBuffer containing the message header
|
||||
*/
|
||||
public ByteBuffer getByteBuffer(){
|
||||
reset();
|
||||
|
||||
putInBuffer(ByteBuffer.allocate(1).put((byte)syncByte1).array(), syncByte1);
|
||||
|
||||
putInBuffer(ByteBuffer.allocate(1).put((byte)syncByte2).array(), syncByte2);
|
||||
|
||||
putInBuffer(ByteBuffer.allocate(1).put((byte)messageType.getCode()).array(), messageType.getCode());
|
||||
|
||||
putInBuffer(Message.intToByteArray(timeStamp, 6), timeStamp);
|
||||
|
||||
putInBuffer(Message.intToByteArray(sourceId, 4), sourceId);
|
||||
|
||||
putInBuffer(Message.intToByteArray(messageLength, 2), messageLength);
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this message
|
||||
* @return the size of the message
|
||||
*/
|
||||
public static Integer getSize(){
|
||||
return MESSAGE_LEN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
public class Heartbeat extends Message {
|
||||
private final int MESSAGE_SIZE = 4;
|
||||
|
||||
/**
|
||||
* Heartbeat from the AC35 Streaming data spec
|
||||
* @param seqNo Increment every time a message is sent
|
||||
*/
|
||||
public Heartbeat(int seqNo){
|
||||
setHeader(new Header(MessageType.HEARTBEAT, 0x01, (short) getSize()));
|
||||
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
putUnsignedInt(seqNo, 4);
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_SIZE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* Types of marks boats can round
|
||||
*/
|
||||
public enum MarkType {
|
||||
UNKNOWN(0),
|
||||
ROUNDING_MARK(1),
|
||||
GATE(2);
|
||||
|
||||
private long code;
|
||||
|
||||
MarkType(long code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public long getCode(){
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
public abstract class Message {
|
||||
private final int CRC_SIZE = 4;
|
||||
private Header header;
|
||||
private ByteBuffer buffer;
|
||||
private int bufferPosition;
|
||||
private CRC32 crc;
|
||||
|
||||
/**
|
||||
* @param header Set the header for this message
|
||||
*/
|
||||
void setHeader(Header header){
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the header specified for this message
|
||||
*/
|
||||
Header getHeader(){
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the size of the message
|
||||
*/
|
||||
public abstract int getSize();
|
||||
|
||||
/**
|
||||
* Allocate byte buffer to correct size
|
||||
*/
|
||||
void allocateBuffer(){
|
||||
buffer = ByteBuffer.allocate(Header.getSize() + getSize() + CRC_SIZE);
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
bufferPosition = 0;
|
||||
buffer.position(bufferPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the set header to the byte buffer
|
||||
*/
|
||||
void writeHeaderToBuffer(){
|
||||
buffer.put(getHeader().getByteBuffer().array());
|
||||
bufferPosition += Header.getSize();
|
||||
buffer.position(bufferPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the buffer position by n bytes
|
||||
* @param size Number of bytes to move the buffer by
|
||||
*/
|
||||
private void moveBufferPositionBy(int size){
|
||||
bufferPosition += size;
|
||||
buffer.position(bufferPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an unsigned byte in the buffer
|
||||
*/
|
||||
void putUnsignedByte(byte b){
|
||||
buffer.put(ByteBuffer.allocate(1).put((byte) (b & 0xff)).array());
|
||||
moveBufferPositionBy(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an signed byte in the buffer
|
||||
*/
|
||||
void putByte(byte b){
|
||||
buffer.put(ByteBuffer.allocate(1).put(b).array());
|
||||
moveBufferPositionBy(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Place an unsigned integer of the specified length in the buffer
|
||||
* @param val The integer value to add (Note: This must be long due to java not supporting unsigned integers)
|
||||
* @param size The size of the int to be added to the buffer
|
||||
*/
|
||||
void putUnsignedInt(long val, int size){
|
||||
if (size <= 1){
|
||||
putUnsignedByte((byte) val);
|
||||
|
||||
}
|
||||
else if (size < 4){
|
||||
// Use short
|
||||
byte[] tmp = Message.intToByteArray(val, size); //ByteBuffer.allocate(size).putShort((short) (val & 0xffff)).array();
|
||||
reverse(tmp);
|
||||
buffer.put(tmp);
|
||||
moveBufferPositionBy(size);
|
||||
}
|
||||
else{
|
||||
// Use int
|
||||
byte[] tmp = Message.intToByteArray(val, size);
|
||||
reverse(tmp);
|
||||
moveBufferPositionBy(size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a signed int of a specified length in the buffer
|
||||
* @param val The integer value to add
|
||||
* @param size The size of the integer to be added to the buffer
|
||||
*/
|
||||
void putInt(long val, int size){
|
||||
if (size < 4){
|
||||
byte[] tmp = Message.intToByteArray(val, size);
|
||||
reverse(tmp);
|
||||
buffer.put(tmp);
|
||||
}
|
||||
else{
|
||||
byte[] tmp = Message.intToByteArray(val, size);
|
||||
reverse(tmp);
|
||||
buffer.put(tmp);
|
||||
}
|
||||
moveBufferPositionBy(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an array of bytes to the buffer
|
||||
* @param bytes to write
|
||||
*/
|
||||
void putBytes(byte[] bytes){
|
||||
buffer.put(bytes);
|
||||
moveBufferPositionBy(bytes.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a ByteBuffer of bytes to the buffer
|
||||
* @param bytes to write
|
||||
* @param size number of bytes
|
||||
*/
|
||||
void putBytes(ByteBuffer bytes, int size){
|
||||
buffer.put(bytes.array());
|
||||
moveBufferPositionBy(size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the CRC of the buffer and append it to the end of the buffer
|
||||
*/
|
||||
void writeCRC(){
|
||||
crc = new CRC32();
|
||||
|
||||
buffer.position(0);
|
||||
|
||||
byte[] data = Arrays.copyOfRange(buffer.array(), 0, buffer.array().length-CRC_SIZE);
|
||||
crc.update(data);
|
||||
buffer.position(bufferPosition);
|
||||
|
||||
putInt((int) crc.getValue(), CRC_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current buffer as a byte array
|
||||
*/
|
||||
public byte[] getBuffer(){
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the buffer to the beginning
|
||||
*/
|
||||
void rewind(){
|
||||
buffer.flip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an integer to an array of bytes
|
||||
* @param val The value to add
|
||||
* @param len The width of the integer in the buffer
|
||||
* @return A byte array to be sent
|
||||
*/
|
||||
public static byte[] intToByteArray(long val, int len){
|
||||
int index = 0;
|
||||
byte[] data = new byte[len];
|
||||
|
||||
for (int i = 0; i < len; i++){
|
||||
data[len - index - 1] = (byte) (val & 0xFF);
|
||||
val >>>= 8;
|
||||
index++;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* takes an array of up to 7 bytes in little endian format and
|
||||
* returns a positive long constructed from the input bytes
|
||||
*
|
||||
* @param bytes the bytes to be converted to long
|
||||
* @return a positive long if there is less than 8 bytes -1 otherwise
|
||||
*/
|
||||
public static long bytesToLong(byte[] bytes){
|
||||
long partialLong = 0;
|
||||
int index = 0;
|
||||
for (byte b: bytes){
|
||||
if (index > 6){
|
||||
return -1;
|
||||
}
|
||||
partialLong = partialLong | (b & 0xFFL) << (index * 8);
|
||||
index++;
|
||||
}
|
||||
return partialLong;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse an array of bytes
|
||||
* @param data The byte[] to reverse
|
||||
*/
|
||||
public static void reverse(byte[] data) {
|
||||
for (int left = 0, right = data.length - 1; left < right; left++, right--) {
|
||||
byte temp = (byte) (data[left] & 0xff);
|
||||
data[left] = (byte) (data[right] & 0xff);
|
||||
data[right] = (byte) (temp & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* Enum containing the types of messages
|
||||
* sent by the server
|
||||
*/
|
||||
public enum MessageType {
|
||||
HEARTBEAT(1),
|
||||
RACE_STATUS(12),
|
||||
DISPLAY_TEXT_MESSAGE(20),
|
||||
XML_MESSAGE(26),
|
||||
RACE_START_STATUS(27),
|
||||
YACHT_EVENT_CODE(29),
|
||||
YACHT_ACTION_CODE(31),
|
||||
CHATTER_TEXT(36),
|
||||
BOAT_LOCATION(37),
|
||||
MARK_ROUNDING(38),
|
||||
COURSE_WIND(44),
|
||||
AVERAGE_WIND(47),
|
||||
BOAT_ACTION(100),
|
||||
REGISTRATION_REQUEST(101),
|
||||
REGISTRATION_RESPONSE(102),
|
||||
CUSTOMIZATION_REQUEST(103),
|
||||
CUSTOMIZATION_RESPONSE(104);
|
||||
|
||||
|
||||
private int code;
|
||||
|
||||
MessageType(int code){
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message code (From the API Spec)
|
||||
* @return the message code
|
||||
*/
|
||||
int getCode(){
|
||||
return this.code;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* The types of race start status messages
|
||||
*/
|
||||
public enum RaceStartNotificationType {
|
||||
SET_RACE_START_TIME(1),
|
||||
RACE_POSTPONED(2),
|
||||
RACE_ABANDONED(3),
|
||||
RACE_TERMINATED(4);
|
||||
|
||||
private final long type;
|
||||
|
||||
RaceStartNotificationType(long type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
long getType(){
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
public class RaceStartStatusMessage extends Message {
|
||||
private final int MESSAGE_SIZE = 20;
|
||||
|
||||
private long version;
|
||||
private long timeStamp;
|
||||
private long ackNumber;
|
||||
private long raceStartTime;
|
||||
private long raceId;
|
||||
private RaceStartNotificationType notificationType;
|
||||
|
||||
/**
|
||||
* Message sent to clients with the expected start time of the race
|
||||
* @param ackNumber Sequence number of message.
|
||||
* @param raceStartTime Expected race start time
|
||||
* @param raceId Race ID#
|
||||
* @param notificationType Type of this notification
|
||||
*/
|
||||
public RaceStartStatusMessage(long ackNumber, long raceStartTime, long raceId, RaceStartNotificationType notificationType){
|
||||
this.version = 1;
|
||||
this.timeStamp = System.currentTimeMillis() / 1000L;
|
||||
this.ackNumber = ackNumber;
|
||||
this.raceStartTime = raceStartTime;
|
||||
this.notificationType = notificationType;
|
||||
this.raceId = raceId;
|
||||
|
||||
setHeader(new Header(MessageType.RACE_START_STATUS, 1, (short) getSize()));
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
putUnsignedByte((byte) version);
|
||||
putInt((int) timeStamp, 6);
|
||||
putInt((int) ackNumber, 2);
|
||||
putInt((int) raceStartTime, 6);
|
||||
putInt((int) raceId, 4);
|
||||
putUnsignedByte((byte) notificationType.getType());
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_SIZE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* The current status of the race
|
||||
*/
|
||||
public enum RaceStatus {
|
||||
NOTACTIVE(0),
|
||||
WARNING(1), // Between 3:00 and 1:00 before start
|
||||
PREPARATORY(2), // Less than 1:00 before start
|
||||
STARTED(3),
|
||||
ABANDONED(6),
|
||||
POSTPONED(7),
|
||||
TERMINATED(8),
|
||||
RACE_START_TIME_NOT_SET(9),
|
||||
PRESTART(10); // More than 3:00 before start
|
||||
|
||||
private int code;
|
||||
|
||||
RaceStatus(int code){
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode(){
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
public class RaceStatusMessage extends Message{
|
||||
private final MessageType MESSAGE_TYPE = MessageType.RACE_STATUS;
|
||||
private final int MESSAGE_VERSION = 2; //Always set to 1
|
||||
private final int MESSAGE_BASE_SIZE = 24;
|
||||
private final double windDirFactor = 0x4000 / 90;
|
||||
|
||||
|
||||
private long currentTime;
|
||||
private long raceId;
|
||||
private RaceStatus raceStatus;
|
||||
private long expectedStartTime;
|
||||
private double raceWindDirection;
|
||||
private long windSpeed;
|
||||
private long numBoatsInRace;
|
||||
private RaceType raceType;
|
||||
private List<BoatSubMessage> boats;
|
||||
private CRC32 crc;
|
||||
|
||||
/**
|
||||
* A message containing the current status of the race
|
||||
* @param raceId The ID of the current race
|
||||
* @param raceStatus The status of the race
|
||||
* @param expectedStartTime The expected start time
|
||||
* @param raceWindDirection The wind direction (north, east, south)
|
||||
* @param windSpeed The wind speed in mm/sec
|
||||
* @param numBoatsInRace The number of boats in the race
|
||||
* @param raceType The race type (Match/fleet)
|
||||
* @param sourceId The source of this message
|
||||
* @param boats A list of boat status sub messages
|
||||
*/
|
||||
public RaceStatusMessage(long raceId, RaceStatus raceStatus, long expectedStartTime, double raceWindDirection,
|
||||
long windSpeed, long numBoatsInRace, RaceType raceType, long sourceId, List<BoatSubMessage> boats){
|
||||
currentTime = System.currentTimeMillis();
|
||||
this.raceId = raceId;
|
||||
this.raceStatus = raceStatus;
|
||||
this.expectedStartTime = expectedStartTime;
|
||||
this.raceWindDirection = raceWindDirection * windDirFactor;
|
||||
this.windSpeed = windSpeed;
|
||||
this.numBoatsInRace = numBoatsInRace;
|
||||
this.raceType = raceType;
|
||||
this.boats = boats;
|
||||
crc = new CRC32();
|
||||
|
||||
setHeader(new Header(MESSAGE_TYPE, (int) sourceId, (short) getSize()));
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
putByte((byte) MESSAGE_VERSION);
|
||||
putInt(currentTime, 6);
|
||||
putInt((int) raceId, 4);
|
||||
putByte((byte) raceStatus.getCode());
|
||||
putInt(expectedStartTime, 6);
|
||||
putInt((int) this.raceWindDirection, 2);
|
||||
putInt((int) windSpeed, 2);
|
||||
putByte((byte) numBoatsInRace);
|
||||
putByte((byte) raceType.getCode());
|
||||
|
||||
for (BoatSubMessage boatSubMessage : boats){
|
||||
putBytes(boatSubMessage.getByteBuffer(), boatSubMessage.getSize());
|
||||
}
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the size of this message in bytes
|
||||
*/
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_BASE_SIZE + (20 * ((int) numBoatsInRace));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* Enum containing the types of races
|
||||
* sent by the server
|
||||
*/
|
||||
public enum RaceType {
|
||||
MATCH_RACE(1),
|
||||
FLEET_RACE(2);
|
||||
|
||||
private long code;
|
||||
|
||||
RaceType(long code){
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public long getCode(){
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
|
||||
public class RegistrationRequestMessage extends Message {
|
||||
private static int MESSAGE_LENGTH = 2;
|
||||
|
||||
public RegistrationRequestMessage(ClientType type){
|
||||
setHeader(new Header(MessageType.REGISTRATION_REQUEST, 1, (short) getSize()));
|
||||
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
putInt(type.getCode(), 2);
|
||||
|
||||
writeCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return MESSAGE_LENGTH;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
public class RegistrationResponseMessage extends Message{
|
||||
|
||||
public RegistrationResponseMessage(int clientSourceID, RegistrationResponseStatus status){
|
||||
setHeader(new Header(MessageType.REGISTRATION_RESPONSE, 1, (short) getSize()));
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
putInt(clientSourceID, 4);
|
||||
putInt(status.getCode(), 1);
|
||||
|
||||
writeCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
public enum RegistrationResponseStatus {
|
||||
SUCCESS_SPECTATING(0x00),
|
||||
SUCCESS_PLAYING(0x01),
|
||||
SUCCESS_TUTORIAL(0x02),
|
||||
SUCCESS_GHOSTING(0x03),
|
||||
|
||||
FAILURE_GENERAL(0x10),
|
||||
FAILURE_FULL(0x11);
|
||||
|
||||
private int code;
|
||||
|
||||
RegistrationResponseStatus(int code){
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message code (From the API Spec)
|
||||
* @return the message code
|
||||
*/
|
||||
int getCode(){
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static RegistrationResponseStatus getResponseStatus(int typeCode){
|
||||
switch (typeCode){
|
||||
case 0x00:
|
||||
return SUCCESS_SPECTATING;
|
||||
case 0x01:
|
||||
return SUCCESS_PLAYING;
|
||||
case 0x02:
|
||||
return SUCCESS_TUTORIAL;
|
||||
case 0x03:
|
||||
return SUCCESS_GHOSTING;
|
||||
case 0x10:
|
||||
return FAILURE_GENERAL;
|
||||
case 0x11:
|
||||
return FAILURE_FULL;
|
||||
default:
|
||||
return FAILURE_GENERAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* The status of a boat rounding a mark
|
||||
*/
|
||||
public enum RoundingBoatStatus {
|
||||
UNKNOWN(0),
|
||||
RACING(1),
|
||||
DSQ(2),
|
||||
WITHDRAWN(3);
|
||||
|
||||
private long code;
|
||||
|
||||
RoundingBoatStatus(long code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public long getCode(){
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* The side the boat rounded the mark
|
||||
*/
|
||||
public enum RoundingSide {
|
||||
UNKNOWN(0, "Unknown"),
|
||||
PORT(1, "Port"),
|
||||
STARBOARD(2, "Stbd"),
|
||||
SP(3, "SP"),
|
||||
PS(4, "PS");
|
||||
|
||||
|
||||
private long code;
|
||||
private String name;
|
||||
|
||||
RoundingSide(long code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getCode(){
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static RoundingSide getRoundingSide(String identifier) {
|
||||
RoundingSide roundingSide = UNKNOWN;
|
||||
switch (identifier) {
|
||||
case "Unknown":
|
||||
roundingSide = UNKNOWN;
|
||||
break;
|
||||
case "Port":
|
||||
roundingSide = PORT;
|
||||
break;
|
||||
case "Stbd":
|
||||
roundingSide = STARBOARD;
|
||||
break;
|
||||
case "SP":
|
||||
roundingSide = SP;
|
||||
break;
|
||||
case "PS":
|
||||
roundingSide = PS;
|
||||
break;
|
||||
}
|
||||
|
||||
return roundingSide;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
public class XMLMessage extends Message{
|
||||
private final MessageType MESSAGE_TYPE = MessageType.XML_MESSAGE;
|
||||
private final int MESSAGE_VERSION = 1; //Always set to 1
|
||||
private final int MESSAGE_SIZE = 14;
|
||||
|
||||
// Message fields
|
||||
private long timeStamp;
|
||||
private long ack = 0x00; //Unused
|
||||
private XMLMessageSubType xmlMessageSubType;
|
||||
private long length;
|
||||
private long sequence;
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* XML Message from the AC35 Streaming data spec
|
||||
* @param content The XML content
|
||||
* @param type The XML Message Sub Type
|
||||
* @param sequenceNum sequenceNum
|
||||
*/
|
||||
public XMLMessage(String content, XMLMessageSubType type, long sequenceNum){
|
||||
this.content = content;
|
||||
this.xmlMessageSubType = type;
|
||||
timeStamp = System.currentTimeMillis() / 1000L;
|
||||
ack = 0;
|
||||
length = this.content.length();
|
||||
sequence = sequenceNum;
|
||||
|
||||
setHeader(new Header(MESSAGE_TYPE, 0x01, (short) getSize()));
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
// Write message fields
|
||||
putUnsignedByte((byte) MESSAGE_VERSION);
|
||||
putInt((int) ack, 2);
|
||||
putInt((int) timeStamp, 6);
|
||||
putByte((byte)xmlMessageSubType.getType());
|
||||
putInt((int) sequence, 2);
|
||||
putInt((int) length, 2);
|
||||
putBytes(content.getBytes());
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The length of this message
|
||||
*/
|
||||
public int getSize(){
|
||||
return MESSAGE_SIZE + content.length();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* Enum containing the types of XML messages
|
||||
*/
|
||||
public enum XMLMessageSubType {
|
||||
REGATTA(5),
|
||||
RACE(6),
|
||||
BOAT(7);
|
||||
|
||||
private int type;
|
||||
|
||||
XMLMessageSubType(int type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getType(){
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package seng302.gameServer.messages;
|
||||
|
||||
/**
|
||||
* Created by zyt10 on 10/08/17.
|
||||
*/
|
||||
public class YachtEventCodeMessage extends Message {
|
||||
|
||||
private final MessageType MESSAGE_TYPE = MessageType.YACHT_EVENT_CODE;
|
||||
private final int MESSAGE_VERSION = 1; //Always set to 1
|
||||
private final int MESSAGE_SIZE = 22;
|
||||
|
||||
// Message fields
|
||||
private long timeStamp;
|
||||
private long ack = 0x00; //Unused
|
||||
private int raceId;
|
||||
private int destSourceId;
|
||||
private int incidentId;
|
||||
private int eventId;
|
||||
|
||||
|
||||
public YachtEventCodeMessage(Integer subjectId) {
|
||||
timeStamp = System.currentTimeMillis() / 1000L;
|
||||
ack = 0;
|
||||
raceId = 1;
|
||||
destSourceId = subjectId; // collision boat source id
|
||||
incidentId = 0;
|
||||
eventId = 33;
|
||||
|
||||
setHeader(new Header(MESSAGE_TYPE, 0x01, (short) getSize()));
|
||||
allocateBuffer();
|
||||
writeHeaderToBuffer();
|
||||
|
||||
// Write message fields
|
||||
putUnsignedByte((byte) MESSAGE_VERSION);
|
||||
putInt((int) timeStamp, 6);
|
||||
putInt((int) ack, 2);
|
||||
putInt((int) raceId, 4);
|
||||
putInt((int) destSourceId, 4);
|
||||
putInt((int) incidentId, 4);
|
||||
putInt((int) eventId, 1);
|
||||
|
||||
writeCRC();
|
||||
rewind();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The length of this message
|
||||
*/
|
||||
public int getSize() {
|
||||
return MESSAGE_SIZE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user