Fixed: new game after server crash

This commit is contained in:
rubenpirreram
2026-05-26 17:49:47 +02:00
parent b900deadd8
commit bbeec46ca2
3 changed files with 76 additions and 131 deletions
@@ -47,16 +47,6 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
BlockingQueue<NetworkEvent> actionQueue;
private LimitedMap<String, Boolean> playerList;
private boolean serverCrashed;
/**
* Sets whether the server is recovering from a previous crash.
*
* @param serverCrashed {@code true} if the server is in crash-recovery mode,
*/
public void setServerCrashed(boolean serverCrashed) {
this.serverCrashed = serverCrashed;
}
/**
* Constructs an RMI server with the required game and network components.
@@ -96,19 +86,8 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
if (preferredInt < 2 || preferredInt > 5) return false;
synchronized (controller) {
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;
}
}
else
{
if (playerList.isEmpty()) {
if (playerList.isEmpty() && controller.getModel()==null) {
controller.setModel(new Game(preferredInt));
playerList.setLimit(preferredInt);
System.out.println("Game Created With :"+preferredInt+" Players");
@@ -120,6 +99,12 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
System.out.println("Accepted player: " + username);
return true;
}
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);
@@ -279,13 +264,10 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
* on the specified port, and registers this server instance under the
* {@code RMIGameServer} name.
*
* @param serverCrashed {@code true} if the server is being restarted after a crash,
* {@code false} otherwise.
* @return {@code true} if the server starts successfully,
* {@code false} otherwise.
*/
public boolean start(boolean serverCrashed) {
this.serverCrashed = serverCrashed;
public boolean start() {
try {
System.setProperty("java.rmi.server.hostname", host);
registry = LocateRegistry.createRegistry(nPort);
@@ -73,20 +73,6 @@ public class TCPServer {
*/
List<ClientHandler> clientHandlers;
/**
* Flag indicating whether the server is recovering from a previous crash.
*/
boolean serverCrashed;
/**
* Sets whether the server is recovering from a previous crash.
*
* @param serverCrashed {@code true} if the server is in crash-recovery mode,
* {@code false} otherwise.
*/
public void setServerCrashed(boolean serverCrashed) {
this.serverCrashed = serverCrashed;
}
/**
* Temporary map associating each username with the corresponding
@@ -129,12 +115,8 @@ public class TCPServer {
* the connection is handled either as a new player joining the game
* or as a reconnection attempt.
*
* @param serverCrashed {@code true} if the server is being restarted after a crash,
* {@code false} otherwise.
*/
public void start(boolean serverCrashed) {
this.serverCrashed = serverCrashed;
public void start() {
try {
socketTCP = new ServerSocket(port);
heartbeatSocketTCP = new ServerSocket(heartbeatPort);
@@ -180,39 +162,7 @@ public class TCPServer {
synchronized (controller) {
String username = eventAddPlayer.getUsername();
//reconnect players after a server crash
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++;
continue;
}
}
//manages a new player adding
else {
if (playerList.isEmpty()) {
if (playerList.isEmpty()&& controller.getModel()==null) {
Game model = new Game(eventAddPlayer.getProposedNPlayer());
controller.setModel(model);
playerList.setLimit(eventAddPlayer.getProposedNPlayer());
@@ -244,6 +194,32 @@ public class TCPServer {
continue;
}
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++;
continue;
}
//reconnect a previously disconnected player
if (playerList.containsKey(username)
@@ -288,8 +264,6 @@ public class TCPServer {
System.out.println("Player could not be added. Connection terminated.");
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
@@ -186,8 +186,6 @@ public class ServerLauncher {
if(!entry.getValue())
playerList.remove(entry.getKey());
}
serverRMI.setServerCrashed(false);
serverTCP.setServerCrashed(false);
}
//notify the event
else {
@@ -206,14 +204,16 @@ public class ServerLauncher {
// removes disconneted players when the game is ended
if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER))
{
synchronized (gameController) {
playerList.remove(event.getUsername());
if(playerList.isEmpty())
{
if (playerList.isEmpty()) {
gameController.setModel(null);
System.out.println("\n!!! Player list is now empty, ready for a new game init !!!\n");
}
return true;
}
}
return false;
}
@@ -245,7 +245,6 @@ public class ServerLauncher {
BlockingQueue<NetworkEvent> actionQueue = new LinkedBlockingQueue<>();
GameController gameController = new GameController();
String IP;
boolean serverCrashed;
try {
IP=chooseNetworkInterface(new Scanner(System.in));
System.out.println(IP);
@@ -266,10 +265,6 @@ public class ServerLauncher {
playerList.put(entry.getKey().getUserName(),false);
}
}
serverCrashed = true;
} else {
serverCrashed = false;
}
playerList.setAction(()->{
new Thread(()->{
@@ -281,8 +276,6 @@ public class ServerLauncher {
}
serverRMI.notifyAll(miniModel);
serverTCP.notifyAll(miniModel);
view = new TUI(miniModel);
view.render();
}).start();
});
new Thread(()-> {
@@ -295,8 +288,8 @@ public class ServerLauncher {
}
}).start();
serverRMI.start(serverCrashed);
new Thread(()->{serverTCP.start(serverCrashed);}).start();
serverRMI.start();
new Thread(()->{serverTCP.start();}).start();
System.out.println("Server RMI: "+System.getProperty("java.rmi.server.hostname"));
}
@@ -314,10 +307,6 @@ public class ServerLauncher {
while (true) {
try{
this.doFirstEvent();
// if(view!=null)
// {
// view.fullRender();
// }
}
catch(InterruptedException e){
Thread.currentThread().interrupt();