diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 1539730e..8c563258 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -44,6 +44,7 @@ public class MainServerThread extends Observable implements Runnable, ClientConn HeartbeatThread heartbeatThread; serverListenThread = new ServerListenThread(serverSocket, this); + heartbeatThread = new HeartbeatThread(this); heartbeatThread.start(); @@ -102,9 +103,11 @@ public class MainServerThread extends Observable implements Runnable, ClientConn public void clientConnected(ServerToClientThread serverToClientThread) { serverLog("Player Connected From " + serverToClientThread.getThread().getName(), 0); serverToClientThreads.add(serverToClientThread); - this.addObserver(serverToClientThread); - setChanged(); - notifyObservers(); + serverToClientThread.addConnectionListener(() -> { + for (ServerToClientThread thread : serverToClientThreads) { + thread.sendSetupMessages(); + } + }); } /** @@ -121,11 +124,15 @@ public class MainServerThread extends Observable implements Runnable, ClientConn serverLog("Player " + player.getYacht().getSourceId() + "'s socket disconnected", 0); GameState.removeYacht(player.getYacht().getSourceId()); GameState.removePlayer(player); + ServerToClientThread closedConnection = null; for (ServerToClientThread serverToClientThread : serverToClientThreads) { if (serverToClientThread.getSocket() == player.getSocket()) { - this.deleteObserver(serverToClientThread); + closedConnection = serverToClientThread; + } else { + serverToClientThread.sendSetupMessages(); } } + serverToClientThreads.remove(closedConnection); setChanged(); notifyObservers(); } diff --git a/src/main/java/seng302/gameServer/ServerToClientThread.java b/src/main/java/seng302/gameServer/ServerToClientThread.java index 2a35e430..fde78482 100644 --- a/src/main/java/seng302/gameServer/ServerToClientThread.java +++ b/src/main/java/seng302/gameServer/ServerToClientThread.java @@ -12,8 +12,6 @@ import java.net.SocketException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import java.util.Observable; -import java.util.Observer; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; import java.util.zip.CRC32; @@ -44,7 +42,15 @@ import seng302.utilities.XMLGenerator; * its own thread. All server threads created and owned by the server thread handler which can * trigger client updates on its threads Created by wmu16 on 13/07/17. */ -public class ServerToClientThread implements Runnable, Observer { +public class ServerToClientThread implements Runnable { + + /** + * Called to notify listeners when this thread receives a connection correctly. + */ + @FunctionalInterface + interface ConnectionListener { + void notifyConnection (); + } private static final Integer LOG_LEVEL = 1; private static final Integer MAX_ID_ATTEMPTS = 10; @@ -57,8 +63,6 @@ public class ServerToClientThread implements Runnable, Observer { private ByteArrayOutputStream crcBuffer; - private Boolean userIdentified = false; - private Boolean connected = true; private Boolean updateClient = true; // private Boolean initialisedRace = true; @@ -70,6 +74,8 @@ public class ServerToClientThread implements Runnable, Observer { private XMLGenerator xml; + private List connectionListeners = new ArrayList<>(); + public ServerToClientThread(Socket socket) { this.socket = socket; seqNo = 0; @@ -85,7 +91,7 @@ public class ServerToClientThread implements Runnable, Observer { thread.start(); } - private void setUpYacht(){ + private void setUpPlayer(){ BufferedReader fn; String fName = ""; BufferedReader ln; @@ -114,7 +120,6 @@ public class ServerToClientThread implements Runnable, Observer { Yacht yacht = new Yacht( "Yacht", sourceId, sourceId.toString(), fName, fName + " " + lName, "NZ" ); - GameState.addYacht(sourceId, yacht); GameState.addPlayer(new Player(socket, yacht)); } @@ -126,11 +131,6 @@ public class ServerToClientThread implements Runnable, Observer { } } - @Override - public void update(Observable o, Object arg) { - sendSetupMessages(); - } - private void completeRegistration(ClientType clientType) throws IOException { // Fail if not a player if (!clientType.equals(ClientType.PLAYER)){ @@ -150,12 +150,14 @@ public class ServerToClientThread implements Runnable, Observer { this.clientType = clientType; this.sourceId = sourceId; - setUpYacht(); - isRegistered = true; os.write(responseMessage.getBuffer()); - sendSetupMessages(); + setUpPlayer(); + + for (ConnectionListener listener : connectionListeners) { + listener.notifyConnection(); + } } public void run() { @@ -226,7 +228,7 @@ public class ServerToClientThread implements Runnable, Observer { } } - private void sendSetupMessages() { + public void sendSetupMessages() { xml = new XMLGenerator(); Race race = new Race(); @@ -257,22 +259,6 @@ public class ServerToClientThread implements Runnable, Observer { updateClient = true; } - - /** - * Tries to confirm the connection just accepted. - * Sends ID, expects that ID echoed for confirmation, - * if so, sends a confirmation packet back to that connection - * Creates a player instance with that ID and this thread and adds it to the GameState - * If not, close the socket and end the threads execution - * - * @param id the id to try and assign to the connection - * @return A boolean indicating if it was a successful handshake - */ - private Boolean threeWayHandshake(Integer id) { - - return true; - } - private void closeSocket() { try { socket.close(); @@ -281,7 +267,6 @@ public class ServerToClientThread implements Runnable, Observer { } } - private int readByte() throws Exception { int currentByte = -1; try { @@ -353,7 +338,6 @@ public class ServerToClientThread implements Runnable, Observer { public void sendRaceStatusMessage() { // variables taken from GameServerThread - List boatSubMessages = new ArrayList<>(); BoatStatus boatStatus; RaceStatus raceStatus; @@ -388,4 +372,12 @@ public class ServerToClientThread implements Runnable, Observer { public Socket getSocket() { return socket; } + + public void addConnectionListener(ConnectionListener listener) { + connectionListeners.add(listener); + } + + public void removeConnectionListener(ConnectionListener listener) { + connectionListeners.remove(listener); + } } diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index 0bb046e8..f71e49da 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -450,9 +450,9 @@ public class Yacht { private void turnTowardsHeading(Double newHeading) { Double newVal = heading - newHeading; if (Math.floorMod(newVal.longValue(), 360L) > 180) { - adjustHeading(TURN_STEP); + adjustHeading(TURN_STEP / 5); } else { - adjustHeading(-TURN_STEP); + adjustHeading(-TURN_STEP / 5); } } diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index ef22a45b..e65cfbd9 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -49,7 +49,7 @@ public class GameClient { private ObservableList clientLobbyList = FXCollections.observableArrayList(); /** - * Create an instance of the game client. Does not do anything untill run with runAsClient() + * Create an instance of the game client. Does not do anything until run with runAsClient() * runAsHost(). * @param holder The JavaFX Pane that the visual elements for the race will be inserted into. */ @@ -106,10 +106,8 @@ public class GameClient { private void loadStartScreen() { socketThread.setSocketToClose(); - socketThread = null; if (server != null) { - // TODO: 26/07/17 cir27 - handle disconnecting -// server.shutDown(); + server.terminate(); server = null; } FXMLLoader fxmlLoader = new FXMLLoader( @@ -191,9 +189,9 @@ public class GameClient { StreamParser.extractXmlMessage(packet) ); clientLobbyList.clear(); - allBoatsMap.forEach((id, boat) -> { - clientLobbyList.add(id + " " + boat.getBoatName()); - }); + allBoatsMap.forEach((id, boat) -> + clientLobbyList.add(id + " " + boat.getBoatName()) + ); break; case RACE_START_STATUS: