From 815b40a8e7bde830ca423111857a338910b23bd3 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Thu, 14 May 2026 13:48:12 +0200 Subject: [PATCH 1/6] Fixed: disconnection during lobby creation --- .../java/it/polimi/ingsw/gc14/Model/Game.java | 25 ++-- .../gc14/Controller/ClientControllerTest.java | 141 ------------------ 2 files changed, 15 insertions(+), 151 deletions(-) delete mode 100644 src/test/java/it/polimi/ingsw/gc14/Controller/ClientControllerTest.java 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 1b59d3d..65c8cf1 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -96,20 +96,25 @@ public class Game implements Serializable { return false; } disconnetedPlayers.put(player,true); - if(currentState.getCurrentPlayer().equals(player)) - if(!currentState.getGameStage().equals(GameStages.TOTEM_CHOICE)) + if (currentState.equals(GameStages.WAITING)) { + playersList.remove(player); + return true; + } + if(currentState.getCurrentPlayer().equals(player)) { + if (!currentState.getGameStage().equals(GameStages.TOTEM_CHOICE)) { nextPlayerSetup(); - else - { - if(totemChoiceQueue.isEmpty()) - { - player.totem=getAvailableTotems().get(new Random().nextInt(getAvailableTotems().size()-1)); - } - else { + return true; + } + else { + if (totemChoiceQueue.isEmpty()) { + player.totem = getAvailableTotems().get(new Random().nextInt(getAvailableTotems().size() - 1)); + } else { totemChoiceQueue.add(player); } - currentState.PlayerUpdate(totemChoiceQueue.poll(),null); + currentState.PlayerUpdate(totemChoiceQueue.poll(), null); + return true; } + } return true; } diff --git a/src/test/java/it/polimi/ingsw/gc14/Controller/ClientControllerTest.java b/src/test/java/it/polimi/ingsw/gc14/Controller/ClientControllerTest.java deleted file mode 100644 index 3f071fd..0000000 --- a/src/test/java/it/polimi/ingsw/gc14/Controller/ClientControllerTest.java +++ /dev/null @@ -1,141 +0,0 @@ -package it.polimi.ingsw.gc14.Controller; - -import it.polimi.ingsw.gc14.Model.Game; -import it.polimi.ingsw.gc14.Model.Player; -import it.polimi.ingsw.gc14.Network.IClient; -import it.polimi.ingsw.gc14.View.IView; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.rmi.RemoteException; - -import static org.junit.jupiter.api.Assertions.*; - -class ClientControllerTest { - - private FakeView view; - private FakeClient client; - private ClientController controller; - - @BeforeEach - void setUp() { - view = new FakeView(); - client = new FakeClient(); - controller = new ClientController(view); - controller.setClient(client); - } - - @Test - void testConstructorInitialization() { - assertSame(view, controller.view); - assertNotNull(controller.localController); - } - - @Test - void testSetModelUpdatesLocalControllerAndView() { - Game game = createGame(); - controller.setModel(game); - - assertSame(game, controller.localController.getModel()); - assertSame(game, view.model); - } - - @Test - void testOnError() { - controller.onError("Errore di test"); - assertEquals("Errore di test", view.lastError); - } - - @Test - void testSetClientDelegatesAction() { - FakeClient newClient = new FakeClient(); - controller.setClient(newClient); - - Game game = createGame(); - controller.setModel(game); - - String current = game.getCurrentState().getCurrentPlayer().getUserName(); - controller.drawUpperTribeCard(current, 0); - - assertEquals("drawUpperTribeCard", newClient.lastMethodCalled); - assertEquals(current, newClient.lastUsername); - assertEquals(0, newClient.lastPos); - } - - @Test - void testDrawUpperTribeCardDelegatesCorrectly() { - Game game = createGame(); - controller.setModel(game); - - String current = game.getCurrentState().getCurrentPlayer().getUserName(); - controller.drawUpperTribeCard(current, 0); - - assertEquals("drawUpperTribeCard", client.lastMethodCalled); - assertEquals(current, client.lastUsername); - assertEquals(0, client.lastPos); - assertNull(view.lastError); - } - - @Test - void testDrawUpperTribeCardWrongPlayerShowsError() { - Game game = createGame(); - controller.setModel(game); - - String current = game.getCurrentState().getCurrentPlayer().getUserName(); - String wrong = current.equals("p1") ? "p2" : "p1"; - controller.drawUpperTribeCard(wrong, 0); - - assertEquals("It's not your turn!", view.lastError); - assertNull(client.lastMethodCalled); - } - - @Test - void testSlotChoiceDelegatesCorrectly() { - Game game = createGame(); - controller.setModel(game); - - String current = game.getCurrentState().getCurrentPlayer().getUserName(); - controller.slotChoice(current, 1); - - assertEquals("slotChoice", client.lastMethodCalled); - assertEquals(current, client.lastUsername); - assertEquals(1, client.lastPos); - assertNull(view.lastError); - } - - - private Game createGame() { - Game game = new Game(2); - game.addPlayer(new Player("p1")); - game.addPlayer(new Player("p2")); - return game; - } - - - private static class FakeView implements IView { - Game model; - String lastError; - - @Override public void setModel(Game game) { this.model = game; } - @Override public void render() {} - @Override public void showMessage(String message) {} - @Override public void showError(String message) { this.lastError = message; } - } - - private static class FakeClient implements IClient { - String lastMethodCalled; - String lastUsername; - int lastPos; - - @Override public boolean connect(String username, int preferredInt) { return true; } - @Override public void drawUpperTribeCard(String u, int pos) throws RemoteException { lastMethodCalled = "drawUpperTribeCard"; lastUsername = u; lastPos = pos; } - @Override public void drawLowerTribeCard(String u, int pos) throws RemoteException { lastMethodCalled = "drawLowerTribeCard"; lastUsername = u; lastPos = pos; } - @Override public void drawUpperBuildingCard(String u, int pos) throws RemoteException { lastMethodCalled = "drawUpperBuildingCard"; lastUsername = u; lastPos = pos; } - @Override public void drawLowerBuildingCard(String u, int pos) throws RemoteException { lastMethodCalled = "drawLowerBuildingCard"; lastUsername = u; lastPos = pos; } - @Override public void skipTurn(String u) throws RemoteException { lastMethodCalled = "skipTurn"; lastUsername = u; } - @Override public void pickOptionalTribeCard(String u, int pos) throws RemoteException { lastMethodCalled = "pickOptionalTribeCard"; lastUsername = u; lastPos = pos; } - @Override public void pickOptionalBuildingCard(String u, int pos) throws RemoteException { lastMethodCalled = "pickOptionalBuildingCard"; lastUsername = u; lastPos = pos; } - @Override public void noOptionalCard(String u) throws RemoteException { lastMethodCalled = "noOptionalCard"; lastUsername = u; } - @Override public void slotChoice(String u, int pos) throws RemoteException { lastMethodCalled = "slotChoice"; lastUsername = u; lastPos = pos; } - } -} \ No newline at end of file From eb4eae4605cb68a9ca20eacfaf8eba8db23db79b Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Thu, 14 May 2026 13:55:27 +0200 Subject: [PATCH 2/6] Fixed: disconnection during lobby creation(NetworkSide) --- .../java/it/polimi/ingsw/gc14/ServerLauncher.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 1fe83c8..e2bf223 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -120,9 +120,17 @@ public class ServerLauncher { Game game=gameController.getModel(); if(!event.getIsError()) { - event.setData(game.getSlotMap(),game.orderLogicCard,game.getCurrentState(),game.getPlayerByUsername(event.getUsername())); - if(event.getEventType().equals(EventType.TOTEM_CHOICE)) - ((TotemChoice)event).setAvailableTotems(gameController.getModel().getAvailableTotems()); + if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER)&& game.getCurrentState().equals(GameStages.WAITING)) + { + playerList.remove(event.getUsername()); + }else { + event.setData(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(), game.getPlayerByUsername(event.getUsername())); + if (event.getEventType().equals(EventType.TOTEM_CHOICE)) { + ((TotemChoice) event).setAvailableTotems(gameController.getModel().getAvailableTotems()); + } else if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && game.getCurrentState().equals(GameStages.WAITING)) { + playerList.remove(event.getUsername()); + } + } } serverRMI.notifyAll(event); serverTCP.notifyAll(event); From 6ff79f2e1d703afc4c57971cc0bb7ae3bcfb86cd Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Thu, 14 May 2026 14:04:22 +0200 Subject: [PATCH 3/6] Fixed: disconnection during lobby creation--> currentStateProblem --- src/main/java/it/polimi/ingsw/gc14/Model/Game.java | 3 ++- src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java | 10 +++++++--- .../ingsw/gc14/View/GUI/TotemFXMLController.java | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) 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 65c8cf1..02a31ec 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -96,8 +96,9 @@ public class Game implements Serializable { return false; } disconnetedPlayers.put(player,true); - if (currentState.equals(GameStages.WAITING)) { + if (currentState.getGameStage().equals(GameStages.WAITING)) { playersList.remove(player); + totemChoiceQueue.remove(player); return true; } if(currentState.getCurrentPlayer().equals(player)) { diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index e2bf223..ada11eb 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -120,7 +120,7 @@ public class ServerLauncher { Game game=gameController.getModel(); if(!event.getIsError()) { - if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER)&& game.getCurrentState().equals(GameStages.WAITING)) + if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER)&& game.getCurrentState().getGameStage().equals(GameStages.WAITING)) { playerList.remove(event.getUsername()); }else { @@ -155,7 +155,6 @@ public class ServerLauncher { else if(!this.gameSave() ){ System.out.println("\n!!! Save failed !!!\n"); } - } if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && playerList.values().stream().filter(x -> x).count() == 1) { if (disconnectionTimer != null && !disconnectionTimer.isDone()) { @@ -266,7 +265,12 @@ public class ServerLauncher { while (true) { try{ this.doFirstEvent(); - this.view.fullRender(); + try{ + this.view.fullRender(); + } + catch (NullPointerException e){ + + } } catch(InterruptedException e){ Thread.currentThread().interrupt(); diff --git a/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java b/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java index c794026..1b2f6f8 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java @@ -29,7 +29,7 @@ public class TotemFXMLController { ImageView img = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_"+ String.valueOf(totem).toLowerCase(Locale.ROOT) +".png"))); img.setFitHeight(240); img.setPreserveRatio(true); - img.setOnMouseClicked(e -> controller.totemChoice(controller.myUsername)); + //img.setOnMouseClicked(e -> controller.totemChoice(controller.myUsername)); mainHBox.getChildren().add(img); } } From f3aaab516fa52ee4ea221d5d4912738c2286c0d8 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Fri, 15 May 2026 13:36:26 +0200 Subject: [PATCH 4/6] Fixed: DisconnectedPlayer and ReconnectPlayer apply with minimodel not initialized, disconnection countdown when the game is ended. Fixed: the player is now removed from order if it was added before. --- src/main/java/it/polimi/ingsw/gc14/LimitedMap.java | 3 ++- .../it/polimi/ingsw/gc14/Model/OrderLogicCard.java | 2 ++ .../Network/NetworkEvents/DisconnectedPlayer.java | 11 +++++++---- .../gc14/Network/NetworkEvents/ReconnectPlayer.java | 10 ++++++---- .../java/it/polimi/ingsw/gc14/ServerLauncher.java | 4 ++-- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/LimitedMap.java b/src/main/java/it/polimi/ingsw/gc14/LimitedMap.java index d4833ae..c9e7c5f 100644 --- a/src/main/java/it/polimi/ingsw/gc14/LimitedMap.java +++ b/src/main/java/it/polimi/ingsw/gc14/LimitedMap.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * A {@link LinkedHashMap} with a configurable size limit and an associated action. @@ -15,7 +16,7 @@ import java.util.Set; */ public class LimitedMap implements Map { - private final LinkedHashMap map = new LinkedHashMap<>(); + private final ConcurrentHashMap map = new ConcurrentHashMap<>(); /** * The maximum number of elements allowed in the map before the action is triggered. diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java index dd6863c..1fac78a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java @@ -70,7 +70,9 @@ public abstract class OrderLogicCard implements Serializable { playerList=new ArrayList<>(); } + playerList.removeIf(x->player.getUserName().equals(x.player.getUserName())); playerList.add(new OrderPlayer(player,false)); + players.removeIf(x->player.getUserName().equals(x.getUserName())); players.add(player); } 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 06234c7..a7db467 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 @@ -35,10 +35,13 @@ public class DisconnectedPlayer extends NetworkEvent implements Serializable{ public boolean apply(MiniModel miniModel){ if(isError) return false; - miniModel.setPlayer(player); - miniModel.setOrderLogicCard(orderLogicCard); - miniModel.setCurrentState(currentState); - miniModel.setSlotPlayerMap(slotPlayerMap); + if(miniModel!=null) + { + miniModel.setPlayer(player); + miniModel.setOrderLogicCard(orderLogicCard); + miniModel.setCurrentState(currentState); + miniModel.setSlotPlayerMap(slotPlayerMap); + } return true; } 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 2289a58..ffcca72 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 @@ -33,10 +33,12 @@ public class ReconnectPlayer extends NetworkEvent implements Serializable{ public boolean apply(MiniModel miniModel){ if(isError) return false; - miniModel.setPlayer(player); - miniModel.setOrderLogicCard(orderLogicCard); - miniModel.setCurrentState(currentState); - miniModel.setSlotPlayerMap(slotPlayerMap); + if(miniModel!=null) { + miniModel.setPlayer(player); + miniModel.setOrderLogicCard(orderLogicCard); + miniModel.setCurrentState(currentState); + miniModel.setSlotPlayerMap(slotPlayerMap); + } return true; } diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index ada11eb..5f38dbf 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -156,7 +156,7 @@ public class ServerLauncher { System.out.println("\n!!! Save failed !!!\n"); } } - if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && playerList.values().stream().filter(x -> x).count() == 1) { + if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && playerList.values().stream().filter(x -> x).count() == 1&& game.getCurrentState().getGameStage() != GameStages.ENDED) { if (disconnectionTimer != null && !disconnectionTimer.isDone()) { disconnectionTimer.cancel(false); } @@ -277,7 +277,7 @@ public class ServerLauncher { break; } catch(RemoteException e){ - throw new RuntimeException(e); + //throw new RuntimeException(e); } } } From df1b41b6661213e0f6656db434b1494ddfaf1543 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Fri, 15 May 2026 16:01:09 +0200 Subject: [PATCH 5/6] Fixed: Some exception not managed fixed --- .../it/polimi/ingsw/gc14/Network/IClient.java | 18 ++-- .../gc14/Network/RMI/Client/RMIClient.java | 90 ++++++++++++++----- .../gc14/Network/RMI/Server/RMIServer.java | 20 ++++- .../gc14/Network/TCP/Client/TCPClient.java | 11 +-- .../it/polimi/ingsw/gc14/ServerLauncher.java | 55 ++++-------- .../it/polimi/ingsw/gc14/View/TUI/TUI.java | 27 +++--- 6 files changed, 131 insertions(+), 90 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java index 6392d5b..23a8f3b 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java @@ -8,26 +8,26 @@ import java.util.Objects; public interface IClient { public boolean connect(String username,int preferredInt); - public void drawUpperTribeCard(String playerUsername, int pos) throws RemoteException; + public void drawUpperTribeCard(String playerUsername, int pos) ; - public void drawLowerTribeCard(String playerUsername,int pos) throws RemoteException; + public void drawLowerTribeCard(String playerUsername,int pos) ; - public void drawUpperBuildingCard(String playerUsername,int pos) throws RemoteException; + public void drawUpperBuildingCard(String playerUsername,int pos) ; - public void drawLowerBuildingCard(String playerUsername,int pos) throws RemoteException; + public void drawLowerBuildingCard(String playerUsername,int pos) ; public void skipTurn(String playerUsername) throws RemoteException; - public void pickOptionalTribeCard(String playerUsername,int pos) throws RemoteException; + public void pickOptionalTribeCard(String playerUsername,int pos) ; - public void pickOptionalBuildingCard(String playerUsername,int pos) throws RemoteException; + public void pickOptionalBuildingCard(String playerUsername,int pos) ; - public void noOptionalCard(String playerUsername) throws RemoteException; + public void noOptionalCard(String playerUsername) ; - public void slotChoice(String playerUsername,int pos) throws RemoteException; - public void totemChoice(String playerUsername,String totem) throws RemoteException; + public void slotChoice(String playerUsername,int pos) ; + public void totemChoice(String playerUsername,String 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 f9d683a..73fd073 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 @@ -134,8 +134,13 @@ public class RMIClient implements IClient { * @param playerUsername the name of the player performing the action * @param pos the index of the card to draw */ - public void drawUpperTribeCard(String playerUsername, int pos) throws RemoteException { - stub.drawUpperTribeCard(playerUsername,pos); + public void drawUpperTribeCard(String playerUsername, int pos) { + try{ + stub.drawUpperTribeCard(playerUsername,pos); + } + catch (RemoteException e){ + System.out.println("Error during remote draw upper tribe card"); + } } @@ -145,8 +150,13 @@ public class RMIClient implements IClient { * @param playerUsername the name of the player performing the action * @param pos the index of the card to draw */ - public void drawLowerTribeCard(String playerUsername,int pos) throws RemoteException { - stub.drawLowerTribeCard(playerUsername,pos); + public void drawLowerTribeCard(String playerUsername,int pos) { + try{ + stub.drawLowerTribeCard(playerUsername,pos); + } + catch (RemoteException e){ + System.out.println("Error during remote draw lower tribe card"); + } } @@ -156,8 +166,13 @@ public class RMIClient implements IClient { * @param playerUsername the name of the player performing the action * @param pos the index of the card to draw */ - public void drawUpperBuildingCard(String playerUsername,int pos) throws RemoteException { - stub.drawUpperBuildingCard(playerUsername,pos); + public void drawUpperBuildingCard(String playerUsername,int pos) { + try{ + stub.drawUpperBuildingCard(playerUsername,pos); + } + catch (RemoteException e){ + System.out.println("Error during remote draw upper building card"); + } } @@ -167,8 +182,13 @@ public class RMIClient implements IClient { * @param playerUsername the name of the player performing the action * @param pos the index of the card to draw */ - public void drawLowerBuildingCard(String playerUsername,int pos) throws RemoteException { - stub.drawLowerBuildingCard(playerUsername,pos); + public void drawLowerBuildingCard(String playerUsername,int pos) { + try{ + stub.drawLowerBuildingCard(playerUsername,pos); + } + catch (RemoteException e){ + System.out.println("Error during remote draw lower building card"); + } } @@ -177,8 +197,13 @@ public class RMIClient implements IClient { * This action is available only when the player cannot draw any tribe card, but still can buy some buildings. * @param playerUsername the name of the player performing the action */ - public void skipTurn(String playerUsername) throws RemoteException { - stub.skipTurn(playerUsername); + public void skipTurn(String playerUsername) { + try{ + stub.skipTurn(playerUsername); + } + catch (RemoteException e){ + System.out.println("Error during remote skip turn"); + } } @@ -190,8 +215,13 @@ public class RMIClient implements IClient { * @param playerUsername the name of the player performing the action * @param pos the index of the card to draw */ - public void pickOptionalTribeCard(String playerUsername,int pos) throws RemoteException { - stub.pickOptionalTribeCard(playerUsername,pos); + public void pickOptionalTribeCard(String playerUsername,int pos) { + try{ + stub.pickOptionalTribeCard(playerUsername,pos); + } + catch (RemoteException e){ + System.out.println("Error during remote pick optional tribe card"); + } } @@ -201,8 +231,13 @@ public class RMIClient implements IClient { * @param playerUsername the name of the player performing the action * @param pos the index of the card to draw */ - public void pickOptionalBuildingCard(String playerUsername,int pos) throws RemoteException { - stub.pickOptionalBuildingCard(playerUsername,pos); + public void pickOptionalBuildingCard(String playerUsername,int pos) { + try{ + stub.pickOptionalBuildingCard(playerUsername,pos); + } + catch (RemoteException e){ + System.out.println("Error during remote pick optional building card"); + } } @@ -211,8 +246,13 @@ public class RMIClient implements IClient { * Available only if the player owns the building 12. * @param playerUsername the name of the player performing the action */ - public void noOptionalCard(String playerUsername) throws RemoteException { - stub.noOptionalCard(playerUsername); + public void noOptionalCard(String playerUsername) { + try{ + stub.noOptionalCard(playerUsername); + } + catch (RemoteException e){ + System.out.println("Error during remote no pick optional card"); + } } @@ -221,12 +261,22 @@ public class RMIClient implements IClient { * @param playerUsername the name of the player performing the action * @param pos the index of the selected slot */ - public void slotChoice(String playerUsername,int pos) throws RemoteException { - stub.slotChoice(playerUsername,pos); + public void slotChoice(String playerUsername,int pos) { + try{ + stub.slotChoice(playerUsername,pos); + } + catch (RemoteException e){ + System.out.println("Error during remote slot choice"); + } } //TODO - public void totemChoice(String playerUsername,String totem) throws RemoteException { - stub.totemChoice(playerUsername,totem); + public void totemChoice(String playerUsername,String totem) { + try{ + stub.totemChoice(playerUsername,totem); + } + catch (RemoteException e){ + System.out.println("Error during remote totem choice"); + } } 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 e74f777..0e7c2cf 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 @@ -153,11 +153,17 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { * Also updates every watchdog with the latest model so disconnect logic * knows whose turn it is. */ - public void notifyAll(NetworkEvent action) throws RemoteException { + public void notifyAll(NetworkEvent action){ for (Map.Entry entry : clients.entrySet()) { if (!action.getIsError() || (action.getIsError() && action.getUsername().equals(entry.getKey()))) { - entry.getValue().onAction(action); + try{ + entry.getValue().onAction(action); + } + catch (RemoteException e) + { + System.out.println("Remote exception: Exception during action sending attempt " + e.getMessage()); + } } } } @@ -167,13 +173,19 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { * Mirrors {@code TCPServer.notifyAll(Game)} + the {@code ClientHandler.notifyModel} * call that stores the model for disconnect-turn checking. */ - public void notifyAll(MiniModel model) throws RemoteException { + public void notifyAll(MiniModel model) { // Keep every watchdog's game reference up to date synchronized (controller){ watchdogs.values().forEach(wd -> wd.setGame(controller.getModel())); } for (IClientCallback cb : clients.values()) { - cb.onGameInit(model); + try{ + cb.onGameInit(model); + } + catch (RemoteException e) + { + System.out.println("Remote exception: Exception during model sending attempt " + e.getMessage()); + } } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java index ffd5d99..affbeb6 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java @@ -69,12 +69,10 @@ public class TCPClient implements IClient { */ public boolean connect(String user, int proposedNPlayers) { try { - // Socket principale communicationSocket = new Socket(hostname, mainPort); socketSend = new ObjectOutputStream(communicationSocket.getOutputStream()); socketReceive = new ObjectInputStream(communicationSocket.getInputStream()); NetworkEvent event= new AddPlayer(user, proposedNPlayers); - System.out.println("Sending event: " + event); socketSend.writeObject(event); int read= communicationSocket.getInputStream().read(); if ( read== -1) { @@ -94,8 +92,6 @@ public class TCPClient implements IClient { new Thread(this::heartbeatLoop, "heartbeat").start(); running = true; - - return true; } catch (IOException e) { @@ -105,7 +101,6 @@ public class TCPClient implements IClient { } private void heartbeatLoop() { - // thread che manda ping ogni 3s ScheduledExecutorService sender = Executors.newSingleThreadScheduledExecutor(); sender.scheduleAtFixedRate(() -> { try { @@ -117,7 +112,6 @@ public class TCPClient implements IClient { } }, 0, 3, TimeUnit.SECONDS); - // thread corrente: aspetta pong con timeout try { heartbeatSocket.setSoTimeout(5_000); while (running) { @@ -142,7 +136,7 @@ public class TCPClient implements IClient { running = false; try { communicationSocket.close(); } catch (IOException ignored) {} try { heartbeatSocket.close(); } catch (IOException ignored) {} - controller.view.showError("Connessione al server persa"); + controller.view.showError("Connection with server lost"); } @@ -162,7 +156,7 @@ public class TCPClient implements IClient { e.printStackTrace(); break; } - if (read instanceof NetworkEvent event) { //TODO: avoid instanceof + if (read instanceof NetworkEvent event) { if (event.getIsError()) { controller.view.showError(event.toString()); } else { @@ -285,7 +279,6 @@ public class TCPClient implements IClient { private void doEvent(NetworkEvent event) { try { synchronized (socketSend) { - System.out.println("Sending event: " + event); socketSend.writeObject(event); } } catch (IOException e) { diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 5f38dbf..60a848e 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -97,9 +97,8 @@ public class ServerLauncher { * All clients (both TCP and RMI) are notified of the event * @return the outcome of applying the event to the controller * @throws InterruptedException if an error occurs while accessing the actionQueue - * @throws RemoteException if an RMI error occurs */ - public boolean doFirstEvent() throws InterruptedException, RemoteException { + public boolean doFirstEvent() throws InterruptedException { NetworkEvent event = actionQueue.take(); if(gameController.getModel()!=null && !gameController.getModel().getCurrentState().equals(GameStages.ENDED)) { @@ -114,7 +113,7 @@ public class ServerLauncher { disconnectionTimer.cancel(false); disconnectionTimer = null; } - int roundPrec=gameController.getModel().getCurrentState().getRound(); + int roundPrev=gameController.getModel().getCurrentState().getRound(); synchronized(gameController){ event.setIsError(!event.apply(gameController)); Game game=gameController.getModel(); @@ -134,7 +133,7 @@ public class ServerLauncher { } serverRMI.notifyAll(event); serverTCP.notifyAll(event); - if(game.getCurrentState().getRound()!=roundPrec) + if(game.getCurrentState().getRound()!=roundPrev) { ApplyNextRound nextRound=new ApplyNextRound(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayers()); serverRMI.notifyAll(nextRound); @@ -161,8 +160,8 @@ public class ServerLauncher { disconnectionTimer.cancel(false); } disconnectionTimer = timerExecutor.schedule(() -> { - System.out.println("Timer scaduto: nessun giocatore riconnesso in 30s."); - }, 30, TimeUnit.SECONDS); + System.out.println("Timer expired: no player reconnected in 60s."); + }, 1, TimeUnit.MINUTES); } return !event.getIsError(); } @@ -221,29 +220,24 @@ public class ServerLauncher { } playerList.setAction(()->{ new Thread(()->{ - try { - System.out.println("\n\nNotifying model"); - MiniModel miniModel; - synchronized (gameController) { - Game game = gameController.getModel(); - miniModel= new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers(), new ArrayList<>(List.of(Totems.values()))); - } - serverRMI.notifyAll(miniModel); - serverTCP.notifyAll(miniModel); - view = new TUI(miniModel); - view.fullRender(); - } catch (RemoteException e) { - throw new RuntimeException(e); + System.out.println("\n\nNotifying model"); + MiniModel miniModel; + synchronized (gameController) { + Game game = gameController.getModel(); + miniModel= new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers(), new ArrayList<>(List.of(Totems.values()))); } + serverRMI.notifyAll(miniModel); + serverTCP.notifyAll(miniModel); + view = new TUI(miniModel); + view.fullRender(); }).start(); }); new Thread(()-> { try { launcher.run(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (RemoteException e) { - throw new RuntimeException(e); + } catch (Exception e) + { + System.out.println("Generic exception occurred"+e.getMessage()); } }).start(); @@ -257,28 +251,17 @@ public class ServerLauncher { * Game creation: TCP/RMI servers send the game model to all players. * Game execution: repeatedly calls doFirstEvent() to process the events in the actionQueue. * @throws InterruptedException if the TCP server thread is interrupted - * @throws RemoteException if an RMI error occurs */ - public void run() throws InterruptedException, RemoteException { - - // Game execution + public void run() { while (true) { try{ this.doFirstEvent(); - try{ - this.view.fullRender(); - } - catch (NullPointerException e){ - - } + this.view.fullRender(); } catch(InterruptedException e){ Thread.currentThread().interrupt(); break; } - catch(RemoteException e){ - //throw new RuntimeException(e); - } } } diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java index 4a93894..a023341 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java @@ -90,20 +90,23 @@ public class TUI implements IView { */ @Override public void render() { - if(model.currentState.getGameStage().equals(GameStages.TOTEM_CHOICE)) + if(model != null) { - renderTotems(); + if(model.currentState.getGameStage().equals(GameStages.TOTEM_CHOICE)) + { + renderTotems(); + } + else if(model.currentState.getGameStage().equals(GameStages.ENDED)) + { + //renderStanding + renderBoard(); + } + else + { + renderBoard(); + } + System.out.println("\nYOUR ACTION:"); } - else if(model.currentState.getGameStage().equals(GameStages.ENDED)) - { - //renderStanding - renderBoard(); - } - else - { - renderBoard(); - } - System.out.println("\nYOUR ACTION:"); } /** From 374247f98485113d72120948d3262395c4658673 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Fri, 15 May 2026 16:27:23 +0200 Subject: [PATCH 6/6] Fixed: various --- .../gc14/Controller/ClientController.java | 60 ++++--------------- .../ingsw/gc14/Model/OrderLogicCard.java | 5 +- .../it/polimi/ingsw/gc14/Network/IClient.java | 2 +- .../it/polimi/ingsw/gc14/View/TUI/TUI.java | 10 ++-- 4 files changed, 19 insertions(+), 58 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java index 0322b97..6121fcd 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java +++ b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java @@ -86,11 +86,7 @@ public class ClientController { } else { - try { - client.drawUpperTribeCard(playerUsername, pos); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.drawUpperTribeCard(playerUsername, pos); } } @@ -105,11 +101,7 @@ public class ClientController { if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else - try { - client.drawLowerTribeCard(playerUsername, pos); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.drawLowerTribeCard(playerUsername, pos); } @@ -123,11 +115,7 @@ public class ClientController { if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { - try { - client.drawUpperBuildingCard(playerUsername,pos); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.drawUpperBuildingCard(playerUsername,pos); } } @@ -143,11 +131,7 @@ public class ClientController { if(!Objects.equals(playerUsername,miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { - try { - client.drawLowerBuildingCard(playerUsername,pos); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.drawLowerBuildingCard(playerUsername,pos); } } @@ -161,11 +145,7 @@ public class ClientController { if(!Objects.equals(playerUsername,miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { - try { - client.skipTurn(playerUsername); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.skipTurn(playerUsername); } } @@ -182,11 +162,7 @@ public class ClientController { if(!Objects.equals(playerUsername,miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { - try { - client.pickOptionalTribeCard(playerUsername,pos); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.pickOptionalTribeCard(playerUsername,pos); } } @@ -201,11 +177,7 @@ public class ClientController { if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { - try { - client.pickOptionalBuildingCard(playerUsername,pos); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.pickOptionalBuildingCard(playerUsername,pos); } } @@ -219,11 +191,7 @@ public class ClientController { if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { - try { - client.noOptionalCard(playerUsername); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.noOptionalCard(playerUsername); } } @@ -237,11 +205,7 @@ public class ClientController { if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { - try { - client.slotChoice(playerUsername,pos); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.slotChoice(playerUsername,pos); } } @@ -250,11 +214,7 @@ public class ClientController { if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { - try { - client.totemChoice(playerUsername, String.valueOf(miniModel.availableTotems.get(pos))); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + client.totemChoice(playerUsername, String.valueOf(miniModel.availableTotems.get(pos))); } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java index 1fac78a..d49b955 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java @@ -70,9 +70,12 @@ public abstract class OrderLogicCard implements Serializable { playerList=new ArrayList<>(); } + if(players.stream().anyMatch(x->x.getUserName().equals(player.getUserName()))) + { + return; + } playerList.removeIf(x->player.getUserName().equals(x.player.getUserName())); playerList.add(new OrderPlayer(player,false)); - players.removeIf(x->player.getUserName().equals(x.getUserName())); players.add(player); } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java index 23a8f3b..6534082 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java @@ -17,7 +17,7 @@ public interface IClient { public void drawLowerBuildingCard(String playerUsername,int pos) ; - public void skipTurn(String playerUsername) throws RemoteException; + public void skipTurn(String playerUsername); diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java index a023341..2ccaf7e 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java @@ -158,14 +158,13 @@ public class TUI implements IView { public void renderTotems() { clearTerminal(); var table = new AsciiTable(BorderStyle.ROUNDED, model.availableTotems.size()); - List lines = model.availableTotems.stream().map(Totems::toString).toList(); - int i=0; - for(String line : lines) + List lines =new ArrayList<>(); + for(int i=0;i