From 36d348dc1e554d706de439711f8a246a16e064b0 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Mon, 25 May 2026 16:31:29 +0200 Subject: [PATCH] Changed: Now Disconnection request can be sent , (TUI,RMI,TCP) --- .../polimi/ingsw/gc14/ClientLauncherTUI.java | 17 ++++++++++++++- .../gc14/Controller/ClientController.java | 5 +++++ .../it/polimi/ingsw/gc14/Network/IClient.java | 3 +++ .../gc14/Network/RMI/Client/RMIClient.java | 12 ++++++++++- .../gc14/Network/RMI/Common/IGameServer.java | 2 ++ .../gc14/Network/RMI/Server/RMIHeartbeat.java | 2 +- .../gc14/Network/RMI/Server/RMIServer.java | 4 ++++ .../gc14/Network/TCP/Client/TCPClient.java | 21 +++++++++++++++++-- .../Network/TCP/Server/ClientHandler.java | 5 ++--- .../Network/TCP/Server/HeartbeatHandler.java | 10 +++++++-- .../it/polimi/ingsw/gc14/View/TUI/TUI.java | 1 + 11 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java index 78296bd..c402c87 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java @@ -1,5 +1,6 @@ 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.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Client.RMIClient; import it.polimi.ingsw.gc14.Network.TCP.Client.TCPClient; @@ -38,6 +39,7 @@ public class ClientLauncherTUI { */ public void main() throws InterruptedException { view = new TUI(null); + admissibleChar.add("0"); admissibleChar.add("1"); admissibleChar.add("2"); admissibleChar.add("3"); @@ -137,7 +139,16 @@ public class ClientLauncherTUI { if(admissibleChar.contains(action)) { - if (!action.equals("6") && !action.equals("A") && !action.equals("B") && !action.equals("C")&&!action.equals("a") && !action.equals("b") && !action.equals("c")) { + if(action.equals("0")) + { + System.out.println("Are you sure? Y/N"); + String c= scanner.next(); + if(!c.equals("Y") && !c.equals("y")) + { + view.render(); + return; + } + }else if (!action.equals("6") && !action.equals("A") && !action.equals("B") && !action.equals("C")&&!action.equals("a") && !action.equals("b") && !action.equals("c")) { try { System.out.println("Insert the required position:"); pos = scanner.nextInt(); @@ -147,6 +158,10 @@ public class ClientLauncherTUI { } } switch (action) { + case "0" -> { + controller.disconnect(); + System.exit(0); + } case "1" -> controller.slotChoice(username, pos); case "2" -> controller.drawUpperTribeCard(username, pos); case "3" -> controller.drawUpperBuildingCard(username, pos); 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 13edbd4..e0af719 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java +++ b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java @@ -195,4 +195,9 @@ public class ClientController { client.totemChoice(playerUsername, String.valueOf(miniModel.availableTotems.get(pos))); } } + + public void disconnect() + { + client.notifyDisconnection(); + } } \ No newline at end of file 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 43704e2..2bf79b9 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java @@ -70,4 +70,7 @@ public interface IClient { * @param totem the name of the selected totem. */ void totemChoice(String playerUsername, String totem); + + //TODO + void notifyDisconnection(); } 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 44f425a..060da63 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 @@ -124,7 +124,7 @@ public class RMIClient implements IClient { if (!running) return; running = false; if (pingSender != null) pingSender.shutdownNow(); - controller.view.showError("Connessione al server persa"); + controller.view.showError("Connection with server closed"); } @@ -235,5 +235,15 @@ public class RMIClient implements IClient { } } + public void notifyDisconnection() { + pingSender.shutdownNow(); + try{ + stub.disconnectPlayer(username); + } + catch (RemoteException e){ + System.out.println("Error during remote disconnection"); + } + } + } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java index aef508d..629f7ea 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java @@ -93,4 +93,6 @@ public interface IGameServer extends Remote { * @throws RemoteException if an RMI communication error occurs. */ void ping(String username) throws RemoteException; + + void disconnectPlayer(String username) throws RemoteException; } \ No newline at end of file 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 4d29816..a1ca275 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 @@ -89,7 +89,7 @@ public class RMIHeartbeat { * the associated RMI callback is removed, and a disconnection event is * added to the action queue for server-side processing. */ - private void disconnect() { + public void disconnect() { if (!running) return; running = false; watchdog.shutdownNow(); 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 bca2e27..ee0d09c 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 @@ -332,6 +332,10 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { watchdogs.put(username, wd); wd.start(); } + public void disconnectPlayer(String username) { + RMIHeartbeat wd = watchdogs.get(username); + wd.disconnect(); + } 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 67ae202..279d9b7 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 @@ -107,8 +107,12 @@ public class TCPClient implements IClient { ScheduledExecutorService sender = Executors.newSingleThreadScheduledExecutor(); sender.scheduleAtFixedRate(() -> { try { - heartbeatOut.write(PING); - heartbeatOut.flush(); + synchronized (heartbeatOut) + { + heartbeatOut.write(PING); + heartbeatOut.flush(); + } + } catch (IOException e) { sender.shutdownNow(); disconnect(); @@ -263,4 +267,17 @@ public class TCPClient implements IClient { public void totemChoice(String playerUsername,String totems) { doEvent(new TotemChoice(playerUsername,totems)); } + + public void notifyDisconnection() + { + synchronized (heartbeatOut) + { + try { + heartbeatOut.write(-1); + } catch (IOException e) { + disconnect(); + } + } + disconnect(); + } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java index 8e36e01..bd8e2ae 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java @@ -94,10 +94,9 @@ public class ClientHandler implements Runnable { } } } catch (IOException e) { - clientHandlers.remove(this); - e.printStackTrace(); + System.err.println("Error in incoming connection/disconnection"); } catch (ClassNotFoundException e) { - throw new RuntimeException(e); + System.err.println("Class not found"); } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/HeartbeatHandler.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/HeartbeatHandler.java index fdf9f8e..6e477fe 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/HeartbeatHandler.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/HeartbeatHandler.java @@ -94,7 +94,13 @@ public class HeartbeatHandler implements Runnable { try { while (running) { int b = in.read(); // blocca finché non arriva un byte - if (b == -1) { disconnect(); break; } // stream chiusa + if (b == -1) { + synchronized (this) + { + out.write(-1); + } + disconnect(); break; + } // stream chiusa if (b == PING) { lastReceivedTime = System.currentTimeMillis(); out.write(PONG); @@ -127,7 +133,7 @@ public class HeartbeatHandler implements Runnable { *

The handler is stopped, the watchdog task is terminated, the main * {@link ClientHandler} is disconnected, and the heartbeat socket is closed. */ - private void disconnect() { + private synchronized void disconnect() { running = false; watchdog.shutdownNow(); mainHandler.disconnect(); // disconnette anche il socket principale 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 6b318fa..606f998 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 @@ -257,6 +257,7 @@ public class TUI implements IView { table.addRow(List.of("4-DrawLowerTribe(pos)", "")); table.addRow(List.of("5-DrawLowerBuilding(pos)", "")); table.addRow(List.of("6-SkipTurn", "")); + table.addRow(List.of("0-Disconnect", "")); return table.build(); }