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

# Conflicts:
#	src/main/java/seng302/gameServer/GameState.java
#	src/main/java/seng302/gameServer/ServerPacketParser.java
#	src/main/java/seng302/gameServer/ServerToClientThread.java
#	src/main/java/seng302/gameServer/messages/ChatterMessage.java
#	src/main/java/seng302/gameServer/messages/MarkRoundingMessage.java
#	src/main/java/seng302/model/ServerYacht.java
#	src/main/java/seng302/visualiser/ClientToServerThread.java
#	src/main/java/seng302/visualiser/GameClient.java
#	src/main/java/seng302/visualiser/GameView.java
This commit is contained in:
Alistair McIntyre
2017-08-17 13:31:27 +12:00
26 changed files with 1020 additions and 376 deletions
+27 -15
View File
@@ -104,7 +104,6 @@ public class GameState implements Runnable {
resetStartTime();
new Thread(this).start(); //Run the auto updates on the game state
new Thread(this, "GameState").start(); //Run the auto updates on the game state
marks = new MarkOrder().getAllMarks();
@@ -186,6 +185,14 @@ public class GameState implements Runnable {
return windDirection;
}
public static void setWindDirection(Double newWindDirection) {
windDirection = newWindDirection;
}
public static void setWindSpeed(Double newWindSpeed) {
windSpeed = newWindSpeed;
}
public static Double getWindSpeedMMS() {
return windSpeed;
}
@@ -256,7 +263,6 @@ public class GameState implements Runnable {
}
}
/**
* Called periodically in this GameState thread to update the GameState values
*/
@@ -277,6 +283,8 @@ public class GameState implements Runnable {
checkForLegProgression(yacht);
raceFinished = false;
}
}
if (raceFinished) {
@@ -335,17 +343,20 @@ public class GameState implements Runnable {
notifyMessageListeners(
new YachtEventCodeMessage(serverYacht.getSourceId())
);
} else if (checkBoundaryCollision(serverYacht)) {
serverYacht.setLocation(
calculateBounceBack(serverYacht, serverYacht.getLocation(),
BOUNCE_DISTANCE_YACHT)
);
serverYacht.setCurrentVelocity(
serverYacht.getCurrentVelocity() * COLLISION_VELOCITY_PENALTY
);
notifyMessageListeners(
new YachtEventCodeMessage(serverYacht.getSourceId())
);
}
else{
if (checkBoundaryCollision(serverYacht)) {
serverYacht.setLocation(
calculateBounceBack(serverYacht, serverYacht.getLocation(),
BOUNCE_DISTANCE_YACHT)
);
serverYacht.setCurrentVelocity(
serverYacht.getCurrentVelocity() * COLLISION_VELOCITY_PENALTY
);
notifyMessageListeners(
new YachtEventCodeMessage(serverYacht.getSourceId())
);
}
}
}
}
@@ -409,7 +420,7 @@ public class GameState implements Runnable {
}
/**
/** lobbyController.setPlayerListSource(clientLobbyList);
* 4 Different cases of progression in the race 1 - Passing the start line 2 - Passing any
* in-race Gate 3 - Passing any in-race Mark 4 - Passing the finish line
*
@@ -432,6 +443,7 @@ public class GameState implements Runnable {
}
if (hasProgressed) {
yacht.incrementLegNumber();
sendMarkRoundingMessage(yacht);
logMarkRounding(yacht);
yacht.setHasPassedLine(false);
@@ -654,7 +666,7 @@ public class GameState implements Runnable {
// TODO: 13/8/17 figure out the rounding side, rounded mark source ID and boat status.
Message markRoundingMessage = new MarkRoundingMessage(0, 0,
sourceID, RoundingBoatStatus.RACING, roundingMark.getRoundingSide(), markType,
roundingMark.getSourceID());
currentMarkSeqID + 1);
notifyMessageListeners(markRoundingMessage);
}
@@ -13,7 +13,7 @@ import seng302.gameServer.messages.Message;
* Will call .clientDisconnected on the delegate when a heartbeat message
* cannot be sent to a player
*/
public class HeartbeatThread extends Thread{
public class HeartbeatThread implements Runnable {
private final int HEARTBEAT_PERIOD = 200;
private ClientConnectionDelegate delegate;
private Integer seqNum;
@@ -23,6 +23,9 @@ public class HeartbeatThread extends Thread{
this.delegate = delegate;
seqNum = 0;
disconnectedPlayers = new Stack<>();
Thread thread = new Thread(this, "HeartBeat");
thread.start();
}
/**
@@ -5,6 +5,7 @@ import java.net.ServerSocket;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import seng302.gameServer.messages.BoatSubMessage;
@@ -20,7 +21,6 @@ import seng302.model.PolarTable;
import seng302.model.ServerYacht;
import seng302.model.mark.CompoundMark;
import seng302.utilities.GeoUtility;
import seng302.visualiser.GameClient;
/**
* A class describing the overall server, which creates and collects server threads for each client
@@ -29,12 +29,17 @@ import seng302.visualiser.GameClient;
public class MainServerThread implements Runnable, ClientConnectionDelegate {
private static final int PORT = 4942;
private static final Integer CLIENT_UPDATES_PER_SECOND = 10;
private static final Integer CLIENT_UPDATES_PER_SECOND = 60;
private static final int LOG_LEVEL = 1;
private static final int WARNING_TIME = 10 * -1000;
private static final int PREPATORY_TIME = 5 * -1000;
public static final int TIME_TILL_START = 10 * 1000;
private static final int MAX_WIND_SPEED = 12000;
private static final int MIN_WIND_SPEED = 8000;
public static int windSpeed = 1000;
private boolean terminated;
private Thread thread;
@@ -42,8 +47,6 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
private ServerSocket serverSocket = null;
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
private GameClient gameClient;
public MainServerThread() {
new GameState("localhost");
try {
@@ -55,19 +58,15 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
GameState.addMarkPassListener(this::broadcastMessage);
terminated = false;
thread = new Thread(this, "MainServer");
startUpdatingWind();
thread.start();
}
public void run() {
ServerListenThread serverListenThread;
HeartbeatThread heartbeatThread;
serverListenThread = new ServerListenThread(serverSocket, this);
heartbeatThread = new HeartbeatThread(this);
heartbeatThread.start();
serverListenThread.start();
new HeartbeatThread(this);
new ServerListenThread(serverSocket, this);
//You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
while (!terminated) {
@@ -121,6 +120,45 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
}
}
private static void updateWind(){
Integer direction = GameState.getWindDirection().intValue();
Integer windSpeed = GameState.getWindSpeedMMS().intValue();
Random random = new Random();
if (Math.floorMod(random.nextInt(), 2) == 0){
direction += random.nextInt(4);
windSpeed += random.nextInt(100) + 500;
}
else{
direction -= random.nextInt(4);
windSpeed -= random.nextInt(100) + 500;
}
direction = Math.floorMod(direction, 360);
if (windSpeed > MAX_WIND_SPEED){
windSpeed -= random.nextInt(1000);
}
if (windSpeed <= MIN_WIND_SPEED){
windSpeed += random.nextInt(1000);
}
GameState.setWindSpeed(Double.valueOf(windSpeed));
GameState.setWindDirection(direction.doubleValue());
}
private static void startUpdatingWind(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
updateWind();
}
}, 0, 500);
}
static void serverLog(String message, int logLevel) {
if (logLevel <= LOG_LEVEL) {
@@ -202,7 +240,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
for (Player player : GameState.getPlayers()) {
ServerYacht y = player.getYacht();
BoatSubMessage m = new BoatSubMessage(y.getSourceId(), y.getBoatStatus(), 0,
BoatSubMessage m = new BoatSubMessage(y.getSourceId(), y.getBoatStatus(),
y.getLegNumber(),
0, 0, 1234L,
1234L);
boatSubMessages.add(m);
@@ -236,25 +275,17 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
terminated = true;
}
/**
* Pass GameClient to main server thread so it can access the properties inside.
*
* @param gameClient gameClient
*/
public void setGameClient(GameClient gameClient) {
this.gameClient = gameClient;
}
/**
* Initialise boats to specific spaced out geopoints behind starting line.
*/
private void initialiseBoatPositions() {
// Getting the start line compound marks
CompoundMark cm = gameClient.getCourseData().getCompoundMarks().get(1);
GeoPoint startMark1 = new GeoPoint(cm.getMarks().get(0).getLat(),
cm.getMarks().get(0).getLng());
GeoPoint startMark2 = new GeoPoint(cm.getMarks().get(1).getLat(),
cm.getMarks().get(1).getLng());
// if (gameClient== null) {
// return;
// }
CompoundMark cm = GameState.getMarkOrder().getMarkOrder().get(0);
GeoPoint startMark1 = cm.getSubMark(1);
GeoPoint startMark2 = cm.getSubMark(2);
// Calculating midpoint
Double perpendicularAngle = GeoUtility.getBearing(startMark1, startMark2);
@@ -8,13 +8,16 @@ import java.net.Socket;
* A class for a thread to listen to connections
* Created by wmu16 on 11/07/17.
*/
public class ServerListenThread extends Thread{
public class ServerListenThread implements Runnable {
private ServerSocket serverSocket;
private ClientConnectionDelegate delegate;
public ServerListenThread(ServerSocket serverSocket, ClientConnectionDelegate delegate){
this.serverSocket = serverSocket;
this.delegate = delegate;
Thread thread = new Thread(this, "ServerListen");
thread.start();
}
/**
@@ -30,6 +30,7 @@ import seng302.gameServer.messages.RegistrationResponseStatus;
import seng302.gameServer.messages.XMLMessage;
import seng302.gameServer.messages.XMLMessageSubType;
import seng302.gameServer.messages.YachtEventCodeMessage;
import seng302.gameServer.messages.YachtEventCodeMessage;
import seng302.model.Player;
import seng302.model.ServerYacht;
import seng302.model.stream.packets.PacketType;
@@ -37,6 +38,19 @@ import seng302.model.stream.packets.StreamPacket;
import seng302.model.stream.xml.generator.Race;
import seng302.model.stream.xml.generator.Regatta;
import seng302.utilities.XMLGenerator;
import seng302.gameServer.messages.BoatAction;
import seng302.gameServer.messages.BoatLocationMessage;
import seng302.gameServer.messages.BoatSubMessage;
import seng302.gameServer.messages.ClientType;
import seng302.gameServer.messages.Message;
import seng302.gameServer.messages.RaceStatus;
import seng302.gameServer.messages.RaceStatusMessage;
import seng302.gameServer.messages.RaceType;
import seng302.gameServer.messages.RegistrationResponseMessage;
import seng302.gameServer.messages.RegistrationResponseStatus;
import seng302.gameServer.messages.XMLMessage;
import seng302.gameServer.messages.XMLMessageSubType;
import seng302.model.ServerYacht;
/**
* A class describing a single connection to a Client for the purposes of sending and receiving on
@@ -186,6 +200,7 @@ public class ServerToClientThread implements Runnable, Observer {
long computedCrc = checksum.getValue();
long packetCrc = Message.bytesToLong(getBytes(4));
if (computedCrc == packetCrc) {
//System.out.println("RECEIVED A PACKET");
switch (PacketType.assignPacketType(type, payload)) {
case BOAT_ACTION:
BoatAction actionType = ServerPacketParser
@@ -1,6 +1,8 @@
package seng302.gameServer.messages;
/**
* Created by kre39 on 20/07/17.
*/
public class ChatterMessage extends Message {
private final long MESSAGE_VERSION_NUMBER = 1;
@@ -0,0 +1,58 @@
package seng302.gameServer.messages;
public class MarkRoundingMessage extends Message{
private final long MESSAGE_VERSION_NUMBER = 1;
private final int MESSAGE_SIZE = 21;
private long time;
private long ackNumber;
private long raceId;
private long sourceId;
private RoundingBoatStatus boatStatus;
private RoundingSide roundingSide;
private long markId;
/**
* This message is sent when a boat passes a mark, start line, or finish line
* The purpose of this is to record the time when yachts cross marks
* @param ackNumber ackNumber
* @param raceId raceId
* @param sourceId boatSourceId
* @param roundingBoatStatus roundingBoatStatus
* @param roundingSide roundingSide
* @param markId markId
*/
public MarkRoundingMessage(int ackNumber, int raceId, int sourceId, RoundingBoatStatus roundingBoatStatus,
RoundingSide roundingSide, MarkType markType, int markId) {
this.time = System.currentTimeMillis();
this.ackNumber = ackNumber;
this.raceId = raceId;
this.sourceId = sourceId;
this.boatStatus = roundingBoatStatus;
this.roundingSide = roundingSide;
this.markId = markId;
setHeader(new Header(MessageType.MARK_ROUNDING, 1, (short) getSize()));
allocateBuffer();
writeHeaderToBuffer();
putByte((byte) MESSAGE_VERSION_NUMBER);
putInt((int) time, 6);
putInt((int) ackNumber, 2);
putInt((int) raceId, 4);
putInt((int) sourceId, 4);
putByte((byte) boatStatus.getCode());
putByte((byte) roundingSide.getCode());
putByte((byte) markType.getCode());
putByte((byte) markId);
writeCRC();
rewind();
}
@Override
public int getSize() {
return MESSAGE_SIZE;
}
}
@@ -39,7 +39,7 @@ public class RaceStatusMessage extends Message{
this.raceId = raceId;
this.raceStatus = raceStatus;
this.expectedStartTime = expectedStartTime;
this.raceWindDirection = raceWindDirection * windDirFactor;
this.raceWindDirection = raceWindDirection * windDirFactor+100.0;
this.windSpeed = windSpeed;
this.numBoatsInRace = numBoatsInRace;
this.raceType = raceType;