From 8106adb0d0fd13162dfd8c10cc8b1073c111842a Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sun, 10 May 2026 20:09:19 +0200 Subject: [PATCH] Fix: Server Persistence --- .../gc14/Network/RMI/Server/RMIServer.java | 69 ++++++--- .../gc14/Network/TCP/Server/TCPServer.java | 138 +++++++++++------- .../it/polimi/ingsw/gc14/ServerLauncher.java | 14 +- 3 files changed, 143 insertions(+), 78 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java index e5cb7ba..675944d 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java @@ -42,6 +42,7 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { BlockingQueue actionQueue; private LimitedMap playerList; + private boolean serverCrashed; public RMIServer(GameController controller, int nPort, BlockingQueue actionQueue, @@ -71,28 +72,51 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { if (preferredInt < 2 || preferredInt > 5) return false; synchronized (controller) { - if (playerList.isEmpty()) { - model = new Game(preferredInt); - controller.setModel(model); - playerList.setLimit(preferredInt); + if(serverCrashed) + { + if(controller.getModel().getPlayers().stream().anyMatch(p -> p.getUserName().equals(username))&& !playerList.containsKey(username)) { + clients.put(username, callback); + playerList.put(username, true); + startWatchdog(username); + System.out.println("(After crash)Reconnected player: " + username); + return true; + } + if (playerList.containsKey(username) && !playerList.get(username)) { + playerList.put(username, true); + clients.put(username, callback); + System.out.println("Reconnected player: " + username); + startWatchdog(username); + callback.onGameInit(model); + System.out.println("Model sent: " + username); + actionQueue.add(new ReconnectPlayer(username)); + return true; + } } - if (controller.addPlayer(username)) { - clients.put(username, callback); - playerList.put(username, true); - startWatchdog(username); - System.out.println("Accepted player: " + username); - return true; - } - // Reconnection: player was offline - if (playerList.containsKey(username) && !playerList.get(username)) { - playerList.put(username, true); - clients.put(username, callback); - System.out.println("Reconnected player: " + username); - startWatchdog(username); - callback.onGameInit(model); - System.out.println("Model sent: " + username); - actionQueue.add(new ReconnectPlayer(username)); - return true; + else + { + if (playerList.isEmpty()) { + model = new Game(preferredInt); + controller.setModel(model); + playerList.setLimit(preferredInt); + } + if (controller.addPlayer(username)) { + clients.put(username, callback); + playerList.put(username, true); + startWatchdog(username); + System.out.println("Accepted player: " + username); + return true; + } + // Reconnection: player was offline + if (playerList.containsKey(username) && !playerList.get(username)) { + playerList.put(username, true); + clients.put(username, callback); + System.out.println("Reconnected player: " + username); + startWatchdog(username); + callback.onGameInit(model); + System.out.println("Model sent: " + username); + actionQueue.add(new ReconnectPlayer(username)); + return true; + } } return false; } @@ -263,7 +287,8 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { * Starts the RMI server. * @return true if the server starts successfully, false otherwise */ - public boolean start() { + public boolean start(boolean serverCrashed) { + this.serverCrashed = serverCrashed; try { System.setProperty("java.rmi.server.hostname", host); registry = LocateRegistry.createRegistry(nPort); diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java index bce4110..eaea963 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java @@ -35,6 +35,7 @@ public class TCPServer { LimitedMap playerList; List clientHandlers; + boolean serverCrashed; // Mappa temporanea: username → ClientHandler // Serve per associare il socket heartbeat al giusto ClientHandler private final Map pendingHeartbeat = new ConcurrentHashMap<>(); @@ -50,7 +51,8 @@ public class TCPServer { this.clientHandlers = new ArrayList<>(); } - public void start() { + public void start(boolean serverCrashed) { + this.serverCrashed = serverCrashed; try { socketTCP = new ServerSocket(port); heartbeatSocketTCP = new ServerSocket(heartbeatPort); @@ -90,64 +92,96 @@ public class TCPServer { } synchronized (controller) { - if (playerList.isEmpty()) { - if(controller.getModel() == null){ + + String username = eventAddPlayer.getUsername(); + if(serverCrashed){ + if(controller.getModel().getPlayers().stream().anyMatch(p -> p.getUserName().equals(username))&& !playerList.containsKey(username)){ + playerList.put(username, true); + System.out.println("(After crash)Reconnected player: " + username); + ClientHandler handler = new ClientHandler( + username, clientSocket, clientSend, clientReceive, + clientHandlers,playerList, actionQueue + ); + clientSocket.getOutputStream().write(1); + pendingHeartbeat.put(username, handler); + Thread thread = new Thread(handler); + thread.start(); + clientHandlers.add(handler); + connectedPlayers++; + } + else if(playerList.containsKey(username) && !playerList.get(username)){ + // riconnessione + playerList.put(username, true); + System.out.println("Reconnected player: " + username); + + ClientHandler handler = new ClientHandler( + username, clientSocket, clientSend, clientReceive, + clientHandlers, playerList, actionQueue + ); + clientSocket.getOutputStream().write(1); + pendingHeartbeat.put(username, handler); + handler.notifyModel(controller.getModel()); + Thread thread = new Thread(handler); + thread.start(); + clientHandlers.add(handler); + connectedPlayers++; + actionQueue.add(new ReconnectPlayer(username)); + } + else + { + clientSocket.getOutputStream().write(-1); + clientSocket.close(); + System.out.println("Player could not be added. Connection terminated."); + } + } + else + { + if (playerList.isEmpty()) { Game model = new Game(eventAddPlayer.getProposedNPlayer()); controller.setModel(model); playerList.setLimit(eventAddPlayer.getProposedNPlayer()); } - else - { - for(Player p:controller.getModel().getPlayers()) { - playerList.put(p.getUserName(),false); - } + if (controller.addPlayer(username)) { + // nuovo giocatore + playerList.put(username, true); + System.out.println("Accepted player: " + username); + ClientHandler handler = new ClientHandler( + username, clientSocket, clientSend, clientReceive, + clientHandlers,playerList, actionQueue + ); + clientSocket.getOutputStream().write(1); + pendingHeartbeat.put(username, handler); + Thread thread = new Thread(handler); + thread.start(); + clientHandlers.add(handler); + connectedPlayers++; + // metti in attesa del socket heartbeat + } + else if(playerList.containsKey(username) && !playerList.get(username)){ + // riconnessione + playerList.put(username, true); + System.out.println("Reconnected player: " + username); + + ClientHandler handler = new ClientHandler( + username, clientSocket, clientSend, clientReceive, + clientHandlers, playerList, actionQueue + ); + clientSocket.getOutputStream().write(1); + pendingHeartbeat.put(username, handler); + handler.notifyModel(controller.getModel()); + Thread thread = new Thread(handler); + thread.start(); + clientHandlers.add(handler); + connectedPlayers++; + actionQueue.add(new ReconnectPlayer(username)); + } + else{ + clientSocket.getOutputStream().write(-1); + clientSocket.close(); + System.out.println("Player could not be added. Connection terminated."); } } - - String username = eventAddPlayer.getUsername(); - - if (controller.addPlayer(username)) { - // nuovo giocatore - playerList.put(username, true); - System.out.println("Accepted player: " + username); - ClientHandler handler = new ClientHandler( - username, clientSocket, clientSend, clientReceive, - clientHandlers,playerList, actionQueue - ); - clientSocket.getOutputStream().write(1); - pendingHeartbeat.put(username, handler); - Thread thread = new Thread(handler); - thread.start(); - clientHandlers.add(handler); - connectedPlayers++; - // metti in attesa del socket heartbeat - - - } - else if(playerList.containsKey(username) && !playerList.get(username)){ - // riconnessione - playerList.put(username, true); - System.out.println("Reconnected player: " + username); - - ClientHandler handler = new ClientHandler( - username, clientSocket, clientSend, clientReceive, - clientHandlers, playerList, actionQueue - ); - clientSocket.getOutputStream().write(1); - pendingHeartbeat.put(username, handler); - handler.notifyModel(controller.getModel()); - Thread thread = new Thread(handler); - thread.start(); - clientHandlers.add(handler); - connectedPlayers++; - actionQueue.add(new ReconnectPlayer(username)); - } - else{ - clientSocket.getOutputStream().write(-1); - clientSocket.close(); - System.out.println("Player could not be added. Connection terminated."); - } } diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 2337f91..a08d7fb 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -4,6 +4,7 @@ package it.polimi.ingsw.gc14; import it.polimi.ingsw.gc14.Controller.GameController; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; +import it.polimi.ingsw.gc14.Model.Player; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvents.DisconnectedPlayer; import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer; @@ -126,7 +127,7 @@ public class ServerLauncher { BlockingQueue actionQueue = new LinkedBlockingQueue<>(); GameController gameController = new GameController(); String IP; - + boolean serverCrashed; try { IP=chooseNetworkInterface(new Scanner(System.in)); } catch (Exception e) { @@ -136,7 +137,12 @@ public class ServerLauncher { RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue, playerList,IP); TCPServer serverTCP = new TCPServer(gameController, 8080, 8081,actionQueue, playerList); ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP); - + if(gameController.getModel() != null){ + playerList.setLimit(gameController.getModel().getNPlayers()); + serverCrashed = true; + } else { + serverCrashed = false; + } playerList.setAction(()->{ new Thread(()->{ try { @@ -149,8 +155,8 @@ public class ServerLauncher { }).start(); }); - serverRMI.start(); - new Thread(()->{serverTCP.start();}).start(); + serverRMI.start(serverCrashed); + new Thread(()->{serverTCP.start(serverCrashed);}).start(); }