From 2fb43c385bd48676fecdcdceeee019ffb3dbc6e9 Mon Sep 17 00:00:00 2001 From: aleandro Date: Tue, 9 Jun 2026 19:23:58 +0200 Subject: [PATCH] Refactor of network stack --- .../polimi/ingsw/gc14/ClientLauncherTUI.java | 5 ++- .../ingsw/gc14/Controller/GameController.java | 24 ++++++----- .../polimi/ingsw/gc14/GameEventProcessor.java | 5 +-- .../java/it/polimi/ingsw/gc14/Model/Game.java | 10 ++--- .../ingsw/gc14/Network/NetworkConfig.java | 11 +++++ .../NetworkEvents/DisconnectedPlayer.java | 2 +- .../NetworkEvents/ReconnectPlayer.java | 2 +- .../gc14/Network/NetworkEvents/SkipTurn.java | 2 +- .../Network/NetworkEvents/TotemChoice.java | 2 +- .../gc14/Network/RMI/Client/RMIClient.java | 10 ++--- .../gc14/Network/RMI/Server/RMIHeartbeat.java | 7 ++-- .../gc14/Network/TCP/Client/TCPClient.java | 3 +- .../Network/TCP/Server/HeartbeatHandler.java | 13 +----- .../gc14/Network/TCP/Server/TCPServer.java | 6 +-- .../polimi/ingsw/gc14/ServerLauncherTest.java | 5 ++- .../gc14/View/GUI/LoginFXMLController.java | 5 ++- .../gc14/Controller/GameControllerTest.java | 32 +++++++------- .../it/polimi/ingsw/gc14/Model/GameTest.java | 42 +++++++++---------- 18 files changed, 94 insertions(+), 92 deletions(-) create mode 100644 src/main/java/it/polimi/ingsw/gc14/Network/NetworkConfig.java diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java index fb3a65f..0dff39c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java @@ -2,6 +2,7 @@ package it.polimi.ingsw.gc14; import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character; import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; +import it.polimi.ingsw.gc14.Network.NetworkConfig; import it.polimi.ingsw.gc14.Network.InterfaceResolver; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Client.RMIClient; @@ -78,7 +79,7 @@ public class ClientLauncherTUI { throw new RuntimeException(e); } System.setProperty("java.rmi.server.hostname", myIP); - RMIClient client = new RMIClient(controller, IP, 1099, myIP); + RMIClient client = new RMIClient(controller, IP, NetworkConfig.RMI_PORT, myIP); ErrorType serverResponse=client.connect(username, proposedNumPlayers); if (serverResponse==null) { System.out.println("Succesfully connected to RMI server\n\n"); @@ -94,7 +95,7 @@ public class ClientLauncherTUI { // TCP } else if (networkType == 1) { // Connect - TCPClient client = new TCPClient(controller, IP, 8080,8081); + TCPClient client = new TCPClient(controller, IP, NetworkConfig.TCP_PORT, NetworkConfig.HEARTBEAT_PORT); ErrorType serverResponse=client.connect(username, proposedNumPlayers); if (serverResponse==null) { System.out.println("Succesfully connected to TCP server\n\n"); diff --git a/src/main/java/it/polimi/ingsw/gc14/Controller/GameController.java b/src/main/java/it/polimi/ingsw/gc14/Controller/GameController.java index 4aab6df..7d76dc9 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Controller/GameController.java +++ b/src/main/java/it/polimi/ingsw/gc14/Controller/GameController.java @@ -40,12 +40,12 @@ public class GameController { * {@code false} if no player with the specified username exists * or if the operation fails. */ - public synchronized boolean DisconnectedPlayer(String username) + public synchronized boolean disconnectedPlayer(String username) { Player player= model.getPlayerByUsername(username); if(player==null) return false; - return model.DisconnectedPlayer(player); + return model.disconnectedPlayer(player); } /** @@ -56,12 +56,12 @@ public class GameController { * {@code false} if no player with the specified username exists * or if the operation fails. */ - public synchronized boolean ReconnectPlayer(String username) + public synchronized boolean reconnectPlayer(String username) { Player player= model.getPlayerByUsername(username); if(player==null) return false; - return model.ReconnectPlayer(player); + return model.reconnectPlayer(player); } /** @@ -165,11 +165,11 @@ public class GameController { * @return {@code true} if the skip action is valid and successfully performed, * {@code false} if the player does not exist or if the action is not valid. */ - public synchronized boolean SkipTurn(String playerUsername) { + public synchronized boolean skipTurn(String playerUsername) { Player player= model.getPlayerByUsername(playerUsername); if(player==null) return false; - return model.SkipTurn(model.getPlayerByUsername(playerUsername)); + return model.skipTurn(model.getPlayerByUsername(playerUsername)); } @@ -199,15 +199,17 @@ public class GameController { * {@code false} if no player with the specified username exists * or if the choice operation fails. */ - public synchronized boolean TotemChoice(String playerUsername,String totem) { + public synchronized boolean totemChoice(String playerUsername,String totem) { Player player= model.getPlayerByUsername(playerUsername); if(player==null) return false; - return model.TotemChoice(player, Totems.valueOf(totem)); + return model.totemChoice(player, Totems.valueOf(totem)); } - //TODO - public synchronized void EndGameForFeit(){ - model.EndGameForFeit(); + @Deprecated + public synchronized void EndGameForFeit() { endGameForFeit(); } + + public synchronized void endGameForFeit() { + model.endGameForFeit(); } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/GameEventProcessor.java b/src/main/java/it/polimi/ingsw/gc14/GameEventProcessor.java index e8dd9c9..d4436d7 100644 --- a/src/main/java/it/polimi/ingsw/gc14/GameEventProcessor.java +++ b/src/main/java/it/polimi/ingsw/gc14/GameEventProcessor.java @@ -280,12 +280,11 @@ public class GameEventProcessor { */ private void endGameForFeit(Game game) { synchronized (gameController) { - gameController.EndGameForFeit(); + gameController.endGameForFeit(); EndedGame forfeitEnd = new EndedGame( game.getSlotMap(), game.orderLogicCard, game.getCurrentState(), game.getPlayerStanding() ); - forfeitEnd.setDisconnected(buildDisconnectedList(game)); broadcaster.notifyAll(forfeitEnd); System.out.println("Timer expired: no player reconnected in 60 s."); removeOfflinePlayers(); @@ -319,14 +318,12 @@ public class GameEventProcessor { game.getUpperListTribeCards(), game.getLowerListTribeCards(), game.getUpperListBuilding(), game.getLowerListBuilding() ); - nextRound.setDisconnected(buildDisconnectedList(game)); broadcaster.notifyAll(nextRound); } else if (game.getCurrentState().getGameStage() == GameStages.ENDED) { EndedGame endedGame = new EndedGame( game.getSlotMap(), game.orderLogicCard, game.getCurrentState(), game.getPlayerStanding() ); - endedGame.setDisconnected(buildDisconnectedList(game)); broadcaster.notifyAll(endedGame); if (!saveManager.delete()) { System.out.println("\n!!! Couldn't delete save !!!\n"); diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java index 64352c0..fcba1d8 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -83,7 +83,7 @@ public class Game implements Serializable { * @param totem the selected totem. * @return {@code true} if the choice is applied successfully, {@code false} otherwise. */ - public synchronized boolean TotemChoice(Player player,Totems totem) { + public synchronized boolean totemChoice(Player player,Totems totem) { if(!currentState.getGameStage().equals(GameStages.TOTEM_CHOICE)) return false; if(!getCurrentState().getCurrentPlayer().equals(player)) @@ -135,7 +135,7 @@ public class Game implements Serializable { * @return {@code true} if the disconnection is handled successfully, * {@code false} if the player was already marked as disconnected. */ - public synchronized boolean DisconnectedPlayer(Player player) + public synchronized boolean disconnectedPlayer(Player player) { if(disconnetedPlayers.containsKey(player) && disconnetedPlayers.get(player)) { @@ -177,7 +177,7 @@ public class Game implements Serializable { * @return {@code true} if the reconnection is handled successfully, * {@code false} if the player was not previously marked as disconnected. */ - public synchronized boolean ReconnectPlayer(Player player) + public synchronized boolean reconnectPlayer(Player player) { if(!disconnetedPlayers.containsKey(player)) { @@ -516,7 +516,7 @@ public class Game implements Serializable { * @param player the player skipping the turn . * @return {@code true} if the skip succeeds, {@code false} otherwise. */ - public boolean SkipTurn(Player player) { + public boolean skipTurn(Player player) { if(currentState.getGameStage()!= GameStages.RES_ACTIONS && !currentState.getGameStage().equals(GameStages.OPT_CARD_E)) { return false; @@ -992,7 +992,7 @@ public class Game implements Serializable { * in the first position of the final ranking. The remaining players are * ordered by prestige value and, in case of a tie, by food value. */ - public synchronized void EndGameForFeit() { + public synchronized void endGameForFeit() { Player winner=playersList.stream().filter(x->!disconnetedPlayers.containsKey(x)||!disconnetedPlayers.get(x)).toList().get(0); currentState.GameStageUpdate(GameStages.ENDED); playerStanding=new ArrayList<>(playersList); diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkConfig.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkConfig.java new file mode 100644 index 0000000..dba18e9 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkConfig.java @@ -0,0 +1,11 @@ +package it.polimi.ingsw.gc14.Network; + +public final class NetworkConfig { + public static final int RMI_PORT = 1099; + public static final int TCP_PORT = 8080; + public static final int HEARTBEAT_PORT = 8081; + public static final long SILENCE_THRESHOLD_MS = 5_000; + public static final long KEEPALIVE_INTERVAL_MS = 3_000; + + private NetworkConfig() {} +} diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DisconnectedPlayer.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DisconnectedPlayer.java index c552b59..8afb21d 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DisconnectedPlayer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DisconnectedPlayer.java @@ -44,7 +44,7 @@ public class DisconnectedPlayer extends NetworkEvent implements Serializable{ */ @Override public boolean apply(GameController gameController){ - return gameController.DisconnectedPlayer(username); + return gameController.disconnectedPlayer(username); } //TODO diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/ReconnectPlayer.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/ReconnectPlayer.java index eca8bad..fedccfc 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/ReconnectPlayer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/ReconnectPlayer.java @@ -39,7 +39,7 @@ public class ReconnectPlayer extends NetworkEvent implements Serializable { */ @Override public boolean apply(GameController gameController) { - return gameController.ReconnectPlayer(username); + return gameController.reconnectPlayer(username); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/SkipTurn.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/SkipTurn.java index 71711b9..312c6ce 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/SkipTurn.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/SkipTurn.java @@ -28,7 +28,7 @@ public class SkipTurn extends NetworkEvent implements Serializable{ */ @Override public boolean apply(GameController gameController){ - return gameController.SkipTurn(username); + return gameController.skipTurn(username); } //TODO diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/TotemChoice.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/TotemChoice.java index 864eee9..bdbf962 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/TotemChoice.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/TotemChoice.java @@ -62,7 +62,7 @@ public class TotemChoice extends NetworkEvent implements Serializable { */ @Override public boolean apply(GameController gameController) { - return gameController.TotemChoice(username, totem); + return gameController.totemChoice(username, totem); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java index 08e7c1b..a1f9c9e 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java @@ -7,6 +7,7 @@ import java.util.concurrent.*; import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.ErrorType; import it.polimi.ingsw.gc14.Network.IClient; +import it.polimi.ingsw.gc14.Network.NetworkConfig; import it.polimi.ingsw.gc14.Network.NetworkEvents.*; import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer; @@ -15,9 +16,6 @@ import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer; */ public class RMIClient implements IClient { - private static final long PING_INTERVAL_S = 3; // mirrors TCPClient 3 s - private static final long PING_TIMEOUT_MS = 5_000; // mirrors SILENCE_THRESHOLD_MS - private final String host; private final int port; private IGameServer stub; @@ -27,7 +25,7 @@ public class RMIClient implements IClient { private volatile boolean running = false; - /** Scheduler that fires ping() every PING_INTERVAL_S seconds. */ + /** Scheduler that fires ping() every {@value NetworkConfig#KEEPALIVE_INTERVAL_MS} ms. */ private ScheduledExecutorService pingSender; /** @@ -107,7 +105,7 @@ public class RMIClient implements IClient { } }); try { - future.get(PING_TIMEOUT_MS, TimeUnit.MILLISECONDS); // mirrors setSoTimeout(5000) + future.get(NetworkConfig.SILENCE_THRESHOLD_MS, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { future.cancel(true); controller.view.showError(ErrorType.SERVER_CRASHED,ErrorType.SERVER_CRASHED.toString()); @@ -116,7 +114,7 @@ public class RMIClient implements IClient { disconnect(); controller.view.showError(ErrorType.SERVER_CRASHED,ErrorType.SERVER_CRASHED.toString()); } - }, 0, PING_INTERVAL_S, TimeUnit.SECONDS); + }, 0, NetworkConfig.KEEPALIVE_INTERVAL_MS, TimeUnit.MILLISECONDS); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIHeartbeat.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIHeartbeat.java index a1ca275..f2f0f52 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIHeartbeat.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIHeartbeat.java @@ -2,6 +2,7 @@ package it.polimi.ingsw.gc14.Network.RMI.Server; import it.polimi.ingsw.gc14.LimitedMap; import it.polimi.ingsw.gc14.Network.NetworkEvent; +import it.polimi.ingsw.gc14.Network.NetworkConfig; import it.polimi.ingsw.gc14.Network.NetworkEvents.DisconnectedPlayer; import java.util.Map; @@ -14,7 +15,7 @@ import java.util.concurrent.*; * instead of reading raw bytes from a dedicated socket, it relies on {@link #receivePing()} * being called by {@link RMIServer#ping(String)} every time the client sends a ping. * - *

If no ping is received within {@value SILENCE_THRESHOLD_MS} ms, the player is + *

If no ping is received within {@value NetworkConfig#SILENCE_THRESHOLD_MS} ms, the player is * considered disconnected and {@link #disconnect()} is invoked, which: *