diff --git a/src/main/java/seng302/gameServer/GameState.java b/src/main/java/seng302/gameServer/GameState.java index e710d81b..7eadd509 100644 --- a/src/main/java/seng302/gameServer/GameState.java +++ b/src/main/java/seng302/gameServer/GameState.java @@ -59,6 +59,7 @@ public class GameState implements Runnable { private static Long previousUpdateTime; public static Double windDirection; private static Double windSpeed; + private static Double speedMultiplier = 1d; private static Boolean customizationFlag; // dirty flag to tell if a player has customized their boat. @@ -356,7 +357,7 @@ public class GameState implements Runnable { Double velocity = yacht.getCurrentVelocity(); Double trueWindAngle = Math.abs(windDirection - yacht.getHeading()); Double boatSpeedInKnots = PolarTable.getBoatSpeed(getWindSpeedKnots(), trueWindAngle); - Double maxBoatSpeed = GeoUtility.knotsToMMS(boatSpeedInKnots); + Double maxBoatSpeed = GeoUtility.knotsToMMS(boatSpeedInKnots) * speedMultiplier; // TODO: 15/08/17 remove magic numbers from these equations. if (yacht.getSailIn()) { if (velocity < maxBoatSpeed - 500) { @@ -693,4 +694,13 @@ public class GameState implements Runnable { public static void broadcastChatter(ChatterMessage chatterMessage) { notifyMessageListeners(chatterMessage); } + + public static void endRace () { + yachts.forEach((id, yacht) -> yacht.setBoatStatus(BoatStatus.FINISHED)); +// currentStage = GameStages.FINISHED; + } + + public static void setSpeedMultiplier (double multiplier) { + speedMultiplier = multiplier; + } } diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 83fb304c..5446d0de 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -86,7 +86,13 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { //FINISHED else if (GameState.getCurrentStage() == GameStages.FINISHED) { - terminate(); + broadcastMessage(makeRaceStatusMessage()); + try { + Thread.sleep(1000); //Hackish fix to make sure all threads have broadcasted + terminate(); + } catch (InterruptedException ie) { + serverLog("Thread interrupted while waiting to terminate clients", 1); + } } } @@ -169,6 +175,9 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { @Override public void clientConnected(ServerToClientThread serverToClientThread) { serverLog("Player Connected From " + serverToClientThread.getThread().getName(), 0); + if (serverToClientThreads.size() == 0) { //Sets first client as host. + serverToClientThread.setAsHost(); + } serverToClientThreads.add(serverToClientThread); serverToClientThread.addConnectionListener(() -> { for (ServerToClientThread thread : serverToClientThreads) { @@ -257,6 +266,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate { if (timeTillStart > PREPATORY_TIME) { raceStatus = RaceStatus.PREPARATORY; } + } else if (GameState.getCurrentStage() == GameStages.FINISHED) { + raceStatus = RaceStatus.TERMINATED; } else { raceStatus = RaceStatus.STARTED; } diff --git a/src/main/java/seng302/gameServer/ServerToClientThread.java b/src/main/java/seng302/gameServer/ServerToClientThread.java index 1cbba682..69cec93c 100644 --- a/src/main/java/seng302/gameServer/ServerToClientThread.java +++ b/src/main/java/seng302/gameServer/ServerToClientThread.java @@ -31,23 +31,6 @@ 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; -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.ClientType; -import seng302.gameServer.messages.Message; -import seng302.gameServer.messages.RegistrationResponseMessage; -import seng302.gameServer.messages.RegistrationResponseStatus; -import seng302.gameServer.messages.XMLMessage; -import seng302.gameServer.messages.XMLMessageSubType; -import seng302.gameServer.messages.YachtEventCodeMessage; import seng302.model.Player; import seng302.model.ServerYacht; import seng302.model.stream.packets.PacketType; @@ -92,6 +75,7 @@ public class ServerToClientThread implements Runnable, Observer { private ClientType clientType; private Boolean isRegistered = false; + private Boolean isHost = false; private XMLGenerator xml; @@ -227,9 +211,10 @@ public class ServerToClientThread implements Runnable, Observer { completeRegistration(requestedType); break; case CHATTER_TEXT: - GameState.broadcastChatter( - ServerPacketParser.extractChatterText(payload) - ); +// GameState.broadcastChatter( +// ServerPacketParser.extractChatterText(payload) +// ); + parseChatter(payload); break; case RACE_CUSTOMIZATION_REQUEST: Long sourceID = Message @@ -391,4 +376,42 @@ public class ServerToClientThread implements Runnable, Observer { public void addDisconnectListener(DisconnectListener disconnectListener) { this.disconnectListener = disconnectListener; } + + public void setAsHost() { + isHost = true; + } + + private void parseChatter(byte[] chatterPayload) { + String chatterText = new String( + Arrays.copyOfRange(chatterPayload, 3, 3 + chatterPayload.length) + ); + String[] words = chatterText.split("\\s+"); + if (words.length < 3) { + return; + } + switch (words[2].trim()) { + case ">speed": + try { + GameState.setSpeedMultiplier(Double.valueOf(words[3])); + GameState.broadcastChatter(new ChatterMessage( + Byte.toUnsignedInt(chatterPayload[1]), + words[0] + "Host has set speed modifier to x" + words[3] + )); + } catch (Exception e) { + logger.error("cannot parse >speed value"); + } + break; + case ">finish": + GameState.endRace(); + GameState.broadcastChatter(new ChatterMessage( + chatterPayload[1], + words[0] + "Host has ended the game" + )); + break; + default: + GameState.broadcastChatter( + ServerPacketParser.extractChatterText(chatterPayload) + ); + } + } }