diff --git a/src/main/java/seng302/controllers/LobbyController.java b/src/main/java/seng302/controllers/LobbyController.java index 0cc50be9..34b6b549 100644 --- a/src/main/java/seng302/controllers/LobbyController.java +++ b/src/main/java/seng302/controllers/LobbyController.java @@ -1,17 +1,13 @@ package seng302.controllers; import java.io.IOException; +import java.io.InputStream; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.Observable; -import java.util.Observer; -import java.util.ResourceBundle; +import java.util.*; + import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -24,6 +20,8 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; import javafx.scene.text.Text; import seng302.client.ClientState; import seng302.client.ClientStateQueryingRunnable; @@ -220,10 +218,29 @@ public class LobbyController implements Initializable, Observer{ @FXML public void readyButtonPressed() { + playTheme(); setContentPane("/views/RaceView.fxml"); GameState.setCurrentStage(GameStages.RACING); } + + private static MediaPlayer mediaPlayer; + + private void playTheme() { + Random random = new Random(System.currentTimeMillis()); + if(random.nextInt(11) == 10) { + URL file = getClass().getResource("/music/Disturbed - down with the sickness.mp3"); + Media hit = new Media(file.toString()); + mediaPlayer = new MediaPlayer(hit); + mediaPlayer.play(); + } else if(random.nextInt(11) == 9) { + URL file = getClass().getResource("/music/Owl City - Fireflies.mp3"); + Media hit = new Media(file.toString()); + mediaPlayer = new MediaPlayer(hit); + mediaPlayer.play(); + } + } + private void switchToRaceView() { setContentPane("/views/RaceView.fxml"); } diff --git a/src/main/java/seng302/gameServer/GameServerThread.java b/src/main/java/seng302/gameServer/GameServerThread.java deleted file mode 100644 index 3a208f36..00000000 --- a/src/main/java/seng302/gameServer/GameServerThread.java +++ /dev/null @@ -1,372 +0,0 @@ -package seng302.gameServer; - -import seng302.models.Player; -import seng302.models.Yacht; -import seng302.server.messages.*; -import seng302.server.simulator.Boat; -import seng302.server.simulator.Simulator; - -import java.io.IOException; -import java.io.InputStream; -import java.net.InetSocketAddress; -import java.net.SocketOption; -import java.net.SocketOptions; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.*; - -public class GameServerThread implements Runnable, Observer, ClientConnectionDelegate{ - - private static final Integer MAX_NUM_PLAYERS = 10; - public static final int PORT_NUMBER = 4942; - - private Boolean hosting = true; - - private ServerSocketChannel server; - private long startTime; - private short seqNum; - - private final int RACE_STATUS_PERIOD = 1000/2; - private final int RACE_START_STATUS_PERIOD = 1000; - private final int BOAT_LOCATION_PERIOD = 1000/5; - private final int TIME_TILL_RACE_START = 20*1000; - private static final int LOG_LEVEL = 1; - - public GameServerThread(String threadName){ - Thread runner = new Thread(this, threadName); - runner.setDaemon(true); - seqNum = 0; - - runner.start(); - } - - public static void serverLog(String message, int logLevel){ - if(logLevel <= LOG_LEVEL){ - System.out.println("[SERVER] " + message); - } - } - - /** - * Creates and returns an XML Message from the file specified - * @param fileName The source XML file - * @param type The XML Message type - * @return The XML Message - */ - private Message getXmlMessage(String fileName, XMLMessageSubType type){ - String fileContents = null; - - try { - InputStream thisStream = this.getClass().getResourceAsStream(fileName); - fileContents = new String(org.apache.commons.io.IOUtils.toByteArray(thisStream)); - } catch (IOException e) { - e.printStackTrace(); - } catch (NullPointerException e){ - return null; - } - - if (fileContents != null){ - return new XMLMessage(fileContents, type, seqNum); - } - - return null; - } - - /** - * @return Get a race status message for the current race - */ - private Message getRaceStatusMessage(){ - - List boatSubMessages = new ArrayList<>(); - BoatStatus boatStatus; - RaceStatus raceStatus; - boolean thereAreBoatsNotFinished = false; - - for (Player player : GameState.getPlayers()){ - Yacht y = player.getYacht(); - - if (GameState.getCurrentStage() == GameStages.PRE_RACE){ - boatStatus = BoatStatus.PRESTART; - thereAreBoatsNotFinished = true; - } - else if(false){ //@TODO if boat has finished - boatStatus = BoatStatus.FINISHED; - } - else{ - boatStatus = BoatStatus.PRESTART; - thereAreBoatsNotFinished = true; - } - - BoatSubMessage m = new BoatSubMessage(y.getSourceId(), boatStatus, y.getLastMarkRounded().getId(), 0, 0, 1234l, 1234l); - boatSubMessages.add(m); - } - - if (thereAreBoatsNotFinished){ - if (GameState.getCurrentStage() == GameStages.RACING){ - raceStatus = RaceStatus.STARTED; - } - else{ - long currentTime = System.currentTimeMillis(); - long timeDifference = startTime - currentTime; - - if (timeDifference > 60*3){ - raceStatus = RaceStatus.PRESTART; - } - else if (timeDifference > 60){ - raceStatus = RaceStatus.WARNING; - } - else{ - raceStatus = RaceStatus.PREPARATORY; - } - } - } - else{ - raceStatus = RaceStatus.TERMINATED; - } - - return new RaceStatusMessage(1, raceStatus, startTime, WindDirection.SOUTH, - 100, GameState.getPlayers().size(), RaceType.MATCH_RACE, 1, boatSubMessages); - } - - /** - * Start sending race start status messages until race starts - */ - private void startSendingRaceStartStatusMessages(){ - Timer t = new Timer(); - t.schedule(new TimerTask() { - @Override - public void run() { - Message raceStartStatusMessage = new RaceStartStatusMessage(seqNum, startTime , 1, - RaceStartNotificationType.SET_RACE_START_TIME); - try { - if (startTime < System.currentTimeMillis() && GameState.getCurrentStage() != GameStages.RACING){ - } - else{ - broadcast(raceStartStatusMessage); - } - - } catch (IOException e) { - e.printStackTrace(); - } - } - }, 0, RACE_START_STATUS_PERIOD); - } - - /** - * Start sending race start status messages until race starts - */ - private void startSendingRaceStatusMessages(){ - - Timer t = new Timer(); - t.schedule(new TimerTask() { - @Override - public void run() { - Message raceStatusMessage = getRaceStatusMessage(); - try { - broadcast(raceStatusMessage); - } catch (IOException e) { - e.printStackTrace(); - } - } - }, 0, RACE_STATUS_PERIOD); - } - - /** - * Sends the race, boat, and regatta XML files to the client - */ - private void sendXml(){ - try{ - Message raceData = getXmlMessage("/server_config/race.xml", XMLMessageSubType.RACE); - Message boatData = getXmlMessage("/server_config/boats.xml", XMLMessageSubType.BOAT); - Message regatta = getXmlMessage("/server_config/regatta.xml", XMLMessageSubType.REGATTA); - - if (raceData != null){ - broadcast(raceData); - } - if (boatData != null){ - broadcast(boatData); - } - if (regatta != null){ - broadcast(regatta); - } - } catch (IOException e) { - serverLog("Couldn't send an XML Message: " + e.getMessage(), 0); - } - } - - /** - * Send the post-start race course information - */ - private void sendPostStartCourseXml(){ - Timer t = new Timer(); - t.schedule(new TimerTask() { - @Override - public void run() { - try { - Message raceData = getXmlMessage("/server_config/courseLimits.xml", XMLMessageSubType.RACE); - if (raceData != null) { - broadcast(raceData); - } - }catch (IOException e) { - serverLog("Couldn't send an XML Message: " + e.getMessage(), 0); - } - } - },1000); - //Delays the new course xml data for 25 seconds so the boats are able to pass the starting line - } - - public void run() { - ServerListenThread serverListenThread; - HeartbeatThread heartbeatThread; - Boolean serverIsSendingMessages = false; - - try{ - server = ServerSocketChannel.open(); - server.socket().bind(new InetSocketAddress("localhost", PORT_NUMBER)); - -// serverListenThread = new ServerListenThread(server, this); - heartbeatThread = new HeartbeatThread(this); - - heartbeatThread.start(); -// serverListenThread.start(); - } - catch (IOException e){ - serverLog("Failed to bind socket: " + e.getMessage(), 0); - } - - while (hosting) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - if (GameState.getCurrentStage() == GameStages.RACING && !serverIsSendingMessages) { - serverLog("Race Started", 0); - - sendXml(); - startSendingRaceStartStatusMessages(); - //startSendingRaceStatusMessages(); - sendPostStartCourseXml(); - serverIsSendingMessages = true; - } - - else if (GameState.getCurrentStage() == GameStages.FINISHED) { - serverLog("Race Finished", 0); - } - - startTime = System.currentTimeMillis() + TIME_TILL_RACE_START; - } - } - -// /** -// * Start sending static boat position updates when race has finished -// */ -// private void startSendingRaceFinishedBoatPositions(){ -// Timer t = new Timer(); -// t.schedule(new TimerTask() { -// @Override -// public void run() { -// try { -// for (Boat b : raceSimulator.getBoats()){ -// Message m = new BoatLocationMessage(b.getSourceID(), seqNum, b.getLat(), -// b.getLng(), b.getLastPassedCorner().getBearingToNextCorner(), -// ((long) 0)); -// -// server.send(m); -// } -// -// } catch (IOException e) { -// e.printStackTrace(); -// } -// } -// }, 0, BOAT_LOCATION_PERIOD); -// } - - /** - * A client has tried to connect to the server - * @param player The player that connected - */ - public void clientConnected(Player player) { - if (GameState.getPlayers().size() < MAX_NUM_PLAYERS && GameState.getCurrentStage() == GameStages.LOBBYING) { - serverLog("Player Connected", 0); - GameState.addPlayer(player); - sendXml(); - } - } - - @Override - public void clientConnected(ServerToClientThread serverToClientThread) { - - } - - /** - * A player has left the game, remove the player from the GameState - * @param player The player that left - */ - @Override - public void clientDisconnected(Player player) { - serverLog("Player disconnected", 0); - GameState.removePlayer(player); - sendXml(); - } - - - void broadcast(Message message) throws IOException{ - for(Player player : GameState.getPlayers()) { - //heh - player.getSocket().getOutputStream().write(message.getBuffer()); - } - seqNum++; - } - - /** - * Send a boat location message when they are updated by the simulator - * @param o . - * @param arg . - */ - @Override - @SuppressWarnings("unchecked") - public void update(Observable o, Object arg) { - /* Only send if server started - // TODO: I don't understand why i need to check server is null or not ... confused - haoming 2/5/17 - if(server == null || !server.isStarted()){ - return; - } - - int numOfBoatsFinished = 0; - for (Boat boat : (List) arg){ - try { - if (boat.isFinished()) { - numOfBoatsFinished ++; - if (!boatsFinished.get(boat.getSourceID())) { - boatsFinished.put(boat.getSourceID(), true); - } - } - Message m = new BoatLocationMessage(boat.getSourceID(), 1, boat.getLat(), - boat.getLng(), boat.getLastPassedCorner().getBearingToNextCorner(), - ((long) boat.getSpeed())); - broadcast(m); - } catch (IOException e) { - serverLog("Couldn't send a boat status message", 3); - return; - } - catch (NullPointerException e){ - e.printStackTrace(); - }*/ - } - -// if (numOfBoatsFinished == ((List) arg).size()) { -// startSendingRaceFinishedBoatPositions(); -// } - - //} - - public void terminateGame() { - try { - //TODO: for now, I just close the socket, but i think we should terminate the whole thread instead. -hyi25 13 July - server.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/seng302/gameServer/GameState.java b/src/main/java/seng302/gameServer/GameState.java index 70c5653c..7c1a9be1 100644 --- a/src/main/java/seng302/gameServer/GameState.java +++ b/src/main/java/seng302/gameServer/GameState.java @@ -25,7 +25,7 @@ public class GameState { public GameState(String hostIpAddress) { windDirection = 170d; - windSpeed = 0d; + windSpeed = 1300d; yachts = new HashMap<>(); players = new ArrayList<>(); @@ -117,6 +117,8 @@ public class GameState { System.out.println("-----------------------"); System.out.println("Heading: " + playerYacht.getHeading()); System.out.println("Sails are in: " + playerYacht.getSailIn()); + System.out.println("Lat: " + playerYacht.getLocation().getLat()); + System.out.println("Lng: " + playerYacht.getLocation().getLng()); System.out.println("-----------------------\n"); } diff --git a/src/main/java/seng302/gameServer/HeartbeatThread.java b/src/main/java/seng302/gameServer/HeartbeatThread.java index 837677bd..80c5bb24 100644 --- a/src/main/java/seng302/gameServer/HeartbeatThread.java +++ b/src/main/java/seng302/gameServer/HeartbeatThread.java @@ -43,7 +43,7 @@ public class HeartbeatThread extends Thread{ Message heartbeat = new Heartbeat(seqNum); for (Player player : GameState.getPlayers()){ - if (!player.getSocket().isConnected()){ + if (!player.getSocket().isConnected()) { playerLostConnection(player); } diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 6a74970b..f61c18ea 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -60,7 +60,7 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff //You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app. while (!thread.isInterrupted()) { try { - Thread.sleep(1000 / UPDATES_PER_SECOND); //60 times per second we should calculate the game state + Thread.sleep(1000 / UPDATES_PER_SECOND); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/src/main/java/seng302/gameServer/ServerToClientThread.java b/src/main/java/seng302/gameServer/ServerToClientThread.java index 9418e6d9..cdeaf374 100644 --- a/src/main/java/seng302/gameServer/ServerToClientThread.java +++ b/src/main/java/seng302/gameServer/ServerToClientThread.java @@ -1,7 +1,6 @@ package seng302.gameServer; -import com.sun.xml.internal.bind.v2.TODO; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -75,7 +74,7 @@ public class ServerToClientThread implements Runnable, Observer { sourceId = GameState.getUniquePlayerID(); if (threeWayHandshake(sourceId)) { serverLog("Successful handshake. Client allocated id: " + sourceId, 1); - Yacht yacht = new Yacht("Yacht", sourceId, sourceId.toString(), "Kap", "Kappa", "NZ"); + Yacht yacht = new Yacht("Yacht", sourceId, sourceId.toString(), "Kapa", "Kappa", "NZ"); // Yacht yacht = new Yacht("Kappa", "Kap", new GeoPoint(57.6708220, 11.8321340), 90.0); GameState.addYacht(sourceId, yacht); GameState.addPlayer(new Player(socket, yacht)); @@ -185,7 +184,14 @@ public class ServerToClientThread implements Runnable, Observer { //Perform a write if it is time to as delegated by the MainServerThread if (updateClient) { // TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream - sendBoatLocationPackets(); +// ChatterMessage chatterMessage = new ChatterMessage(4, 14, "Hello, it's me"); +// sendMessage(chatterMessage); +// try { +// GameState.outputState(os); +// } catch (IOException e) { +// System.out.println("IO error in server thread upon writing to output stream"); +// } +// sendBoatLocationPackets(); updateClient = false; } @@ -219,8 +225,9 @@ public class ServerToClientThread implements Runnable, Observer { } } } catch (Exception e) { - // TODO: 24/07/17 zyt10 - fix a logic here when a client disconnected + // TODO: 24/07/17 zyt10 - fix a logic here when a client disconnected serverLog("ERROR OCCURRED, CLOSING SERVER CONNECTION: " + socket.getRemoteSocketAddress().toString(), 1); +// e.printStackTrace(); closeSocket(); return; } @@ -232,8 +239,8 @@ public class ServerToClientThread implements Runnable, Observer { xml = new XMLGenerator(); Race race = new Race(); - for (Player player : GameState.getPlayers()){ - race.addBoat(player.getYacht()); + for (Yacht yacht : GameState.getYachts().values()){ + race.addBoat(yacht); } //@TODO calculate lat/lng values @@ -248,7 +255,7 @@ public class ServerToClientThread implements Runnable, Observer { xmlMessage = new XMLMessage(xml.getRaceAsXml(), XMLMessageSubType.RACE, xml.getRaceAsXml().length()); sendMessage(xmlMessage); - System.out.println("Sent xml messages for " + thread.getName()); +// System.out.println("Sent xml messages for " + thread.getName()); } diff --git a/src/main/resources/music/Disturbed - down with the sickness.mp3 b/src/main/resources/music/Disturbed - down with the sickness.mp3 new file mode 100644 index 00000000..375b140b Binary files /dev/null and b/src/main/resources/music/Disturbed - down with the sickness.mp3 differ diff --git a/src/main/resources/music/Owl City - Fireflies.mp3 b/src/main/resources/music/Owl City - Fireflies.mp3 new file mode 100644 index 00000000..fce20269 Binary files /dev/null and b/src/main/resources/music/Owl City - Fireflies.mp3 differ