Minor structural changes. GameState now has a thread which updates itself so its update

rate can be independent of sending packets to the client in the MainServerThread

#story[986] #pair[wmu16, ptg19]
This commit is contained in:
William Muir
2017-07-26 14:48:32 +12:00
parent 2bfa6cb038
commit 5e6b402bf5
4 changed files with 47 additions and 51 deletions
@@ -101,7 +101,8 @@ public class ClientToServerThread implements Runnable {
} }
} catch (Exception e) { } catch (Exception e) {
closeSocket(); closeSocket();
e.printStackTrace(); System.err.println("SERVER DISCONNECTED");
// e.printStackTrace();
return; return;
} }
} }
@@ -12,7 +12,9 @@ import seng302.server.messages.BoatActionType;
* A Static class to hold information about the current state of the game (model) * A Static class to hold information about the current state of the game (model)
* Created by wmu16 on 10/07/17. * Created by wmu16 on 10/07/17.
*/ */
public class GameState { public class GameState implements Runnable {
private static Integer STATE_UPDATES_PER_SECOND = 60;
private static Long previousUpdateTime; private static Long previousUpdateTime;
public static Double windDirection; public static Double windDirection;
@@ -31,7 +33,7 @@ public class GameState {
players = new ArrayList<>(); players = new ArrayList<>();
GameState.hostIpAddress = hostIpAddress; this.hostIpAddress = hostIpAddress;
players = new ArrayList<>(); players = new ArrayList<>();
currentStage = GameStages.LOBBYING; currentStage = GameStages.LOBBYING;
isRaceStarted = false; isRaceStarted = false;
@@ -39,6 +41,9 @@ public class GameState {
//set this when game stage changes to prerace //set this when game stage changes to prerace
previousUpdateTime = System.currentTimeMillis(); previousUpdateTime = System.currentTimeMillis();
yachts = new HashMap<>(); yachts = new HashMap<>();
new Thread(this).start();
} }
public static String getHostIpAddress() { public static String getHostIpAddress() {
@@ -134,7 +139,6 @@ public class GameState {
} }
public static void update() { public static void update() {
Long timeInterval = System.currentTimeMillis() - previousUpdateTime; Long timeInterval = System.currentTimeMillis() - previousUpdateTime;
previousUpdateTime = System.currentTimeMillis(); previousUpdateTime = System.currentTimeMillis();
for (Yacht yacht : yachts.values()) { for (Yacht yacht : yachts.values()) {
@@ -151,4 +155,28 @@ public class GameState {
// TODO: 22/07/17 wmu16 - This may not be robust enough and may have to be improved on. // TODO: 22/07/17 wmu16 - This may not be robust enough and may have to be improved on.
return yachts.size() + 1; return yachts.size() + 1;
} }
/**
* A thread to have the game state update itself at certain intervals
*/
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000 / STATE_UPDATES_PER_SECOND);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (currentStage == GameStages.PRE_RACE) {
update();
}
//RACING
if (currentStage == GameStages.RACING) {
update();
}
}
}
} }
@@ -17,22 +17,17 @@ import java.util.concurrent.PriorityBlockingQueue;
* A class describing the overall server, which creates and collects server threads for each client * A class describing the overall server, which creates and collects server threads for each client
* Created by wmu16 on 13/07/17. * Created by wmu16 on 13/07/17.
*/ */
public class MainServerThread extends Observable implements Runnable, PacketBufferDelegate, ClientConnectionDelegate{ public class MainServerThread extends Observable implements Runnable, ClientConnectionDelegate{
private static final int PORT = 4942; private static final int PORT = 4942;
private static final Integer MAX_NUM_PLAYERS = 3; private static final Integer CLIENT_UPDATES_PER_SECOND = 5;
private static final Integer UPDATES_PER_SECOND = 2;
private static final int LOG_LEVEL = 1; private static final int LOG_LEVEL = 1;
private Thread thread; private Thread thread;
private ServerSocket serverSocket = null; private ServerSocket serverSocket = null;
private Socket socket;
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>(); private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
private PriorityBlockingQueue<StreamPacket> packetBuffer;
public MainServerThread() { public MainServerThread() {
try { try {
serverSocket = new ServerSocket(PORT); serverSocket = new ServerSocket(PORT);
@@ -40,8 +35,6 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
serverLog("IO error in server thread handler upon trying to make new server socket", 0); serverLog("IO error in server thread handler upon trying to make new server socket", 0);
} }
packetBuffer = new PriorityBlockingQueue<>();
thread = new Thread(this); thread = new Thread(this);
thread.start(); thread.start();
} }
@@ -57,22 +50,20 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
heartbeatThread.start(); heartbeatThread.start();
serverListenThread.start(); serverListenThread.start();
//You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app. //You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
while (!thread.isInterrupted()) { while (!thread.isInterrupted()) {
try { try {
Thread.sleep(1000 / UPDATES_PER_SECOND); Thread.sleep(1000 / CLIENT_UPDATES_PER_SECOND);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
if (GameState.getCurrentStage() == GameStages.PRE_RACE) { if (GameState.getCurrentStage() == GameStages.PRE_RACE) {
GameState.update(); updateClients();
} }
//RACING //RACING
if (GameState.getCurrentStage() == GameStages.RACING) { if (GameState.getCurrentStage() == GameStages.RACING) {
GameState.update();
updateClients(); updateClients();
} }
@@ -81,14 +72,6 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
} }
while (!packetBuffer.isEmpty()){
try {
StreamPacket packet = packetBuffer.take();
ClientPacketParser.parsePacket(packet);
} catch (InterruptedException e) {
continue;
}
}
} }
// TODO: 14/07/17 wmu16 - Send out disconnect packet to clients // TODO: 14/07/17 wmu16 - Send out disconnect packet to clients
@@ -113,11 +96,6 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
} }
} }
@Override
public boolean addToBuffer(StreamPacket streamPacket) {
return packetBuffer.add(streamPacket);
}
/** /**
* A client has tried to connect to the server * A client has tried to connect to the server
* @param serverToClientThread The player that connected * @param serverToClientThread The player that connected
+10 -21
View File
@@ -117,28 +117,17 @@ public class Yacht {
* @param timeInterval since last update in milliseconds * @param timeInterval since last update in milliseconds
*/ */
public void update(Long timeInterval) { public void update(Long timeInterval) {
Double secondsElapsed = timeInterval / 1000000.0; if (sailIn) {
Double windSpeedKnots = GameState.getWindSpeedKnots(); Double secondsElapsed = timeInterval / 1000000.0;
Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading); Double windSpeedKnots = GameState.getWindSpeedKnots();
Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle); Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading);
Double maxBoatSpeed = boatSpeedInKnots / ClientPacketParser.MS_TO_KNOTS * 1000; Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle);
if (sailIn && velocity <= maxBoatSpeed) { // Acceleration velocity = boatSpeedInKnots / ClientPacketParser.MS_TO_KNOTS * 1000;
if (velocity < maxBoatSpeed) { Double metersCovered = velocity * secondsElapsed;
velocity += maxBoatSpeed / 25; location = getGeoCoordinate(location, heading, metersCovered);
if (velocity > maxBoatSpeed) { } else {
velocity = maxBoatSpeed; velocity = 0d;
}
}
} else { // Deceleration
if (velocity > 0) {
velocity = velocity -= maxBoatSpeed / 25;
if (velocity < 0) {
velocity = 0d;
}
}
} }
Double metersCovered = velocity * secondsElapsed;
location = getGeoCoordinate(location, heading, metersCovered);
} }