From f065ad109f59e463e02ce5ca458e7ac45199c5c8 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Fri, 24 Apr 2026 16:29:58 +0200 Subject: [PATCH 01/41] Fix: AddPlayerEvent --- .../polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java index 602a231..d8ab797 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java @@ -8,8 +8,13 @@ import it.polimi.ingsw.gc14.View.IView; import java.io.Serializable; public class AddPlayer extends NetworkEvent implements Serializable { - public AddPlayer(String username) { + private int proposedNPlayer; + public int getProposedNPlayer() { + return proposedNPlayer; + } + public AddPlayer(String username, int proposedNPlayer) { super(username, EventType.ADD_PLAYER); + this.proposedNPlayer = proposedNPlayer; } @Override public boolean apply(GameController gameController) From 2fe430900d49abb73c9f47601d56f513d1aeef21 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Fri, 24 Apr 2026 16:56:53 +0200 Subject: [PATCH 02/41] Add: ClientLauncher Fix: changed management of addPlayer in ServerLauncher --- .../it/polimi/ingsw/gc14/ClientLauncher.java | 28 +++++++++++++ .../it/polimi/ingsw/gc14/ServerLauncher.java | 40 ++++++++++++++----- 2 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java new file mode 100644 index 0000000..fd8a3f8 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java @@ -0,0 +1,28 @@ +package it.polimi.ingsw.gc14; +import java.util.Scanner; + +public class ClientLauncher { + public void main() { + Scanner scanner = new Scanner(System.in); + + System.out.println("Selezionare nome utente: "); + String username = scanner.next(); + System.out.println(username); + + System.out.println("Selezionare numero di giocatori desiderato: "); + int proposedNumPlayers = scanner.nextInt(); + System.out.println(proposedNumPlayers); + + System.out.println("Selezionare RMI[0] o TCP[1]: "); + int networkType = scanner.nextInt(); + System.out.println(networkType); + + scanner.close(); // chiudi solo alla fine + + if (networkType == 0) { + return; + } else if (networkType == 1) { + return; + } + } +} \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index b3c14d7..36b57bc 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.Network.NetworkEvent; +import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer; import it.polimi.ingsw.gc14.Network.TCP.Server.TCPServer; @@ -26,7 +27,7 @@ public class ServerLauncher { this.serverTCP = serverTCP; } - public boolean doFirstEvent() throws InterruptedException, RemoteException { + public boolean doFirstEven() throws InterruptedException, RemoteException { NetworkEvent event = actionQueue.take(); if(event.apply(gameController)) { serverRMI.notifyAll(event); @@ -40,24 +41,45 @@ public class ServerLauncher { } - public static void main() throws RemoteException { + public static void main() throws RemoteException, InterruptedException { + // TODO + // Deve avere una coda con gli eventi. + // Il server RMI e il server TCP quando ricevono un doEvent devono aggiungere l'evento alla coda condivisa + // Questa classe esegue gli eventi nella coda e chiama il notify all e notify error sia RMI che TCP + BlockingQueue actionQueue = new LinkedBlockingQueue<>(); - Game model = new Game(); - GameController gameController = new GameController(model); + GameController gameController = new GameController(); RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue); TCPServer serverTCP = new TCPServer(gameController, 8080, actionQueue); - serverRMI.start(); - new Thread (()->{serverTCP.start();}).start(); - ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP); launcher.run(); } - public void run() { + public void run() throws InterruptedException, RemoteException { + + // Aggiunge il primo player e imposta il numero di giocatori voluti + AddPlayer player1 = (AddPlayer) actionQueue.take(); + Game model = new Game(player1.getProposedNPlayer()); + gameController.setModel(model); + player1.apply(gameController); + + for(int i=1; i Date: Fri, 24 Apr 2026 18:19:15 +0200 Subject: [PATCH 03/41] Add: LimitedList --- .../it/polimi/ingsw/gc14/LimitedList.java | 26 +++++++++++++++++++ .../it/polimi/ingsw/gc14/ServerLauncher.java | 26 ++++++++----------- 2 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 src/main/java/it/polimi/ingsw/gc14/LimitedList.java diff --git a/src/main/java/it/polimi/ingsw/gc14/LimitedList.java b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java new file mode 100644 index 0000000..fb582c3 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java @@ -0,0 +1,26 @@ +package it.polimi.ingsw.gc14; + +import java.util.ArrayList; + +public class LimitedList extends ArrayList { + private int limit; + private final Runnable action; + + public LimitedList(int limit, Runnable action) { + this.limit = limit; + this.action = action; + } + + @Override + public boolean add(Player element) { + boolean result = super.add(element); + if (size() >= limit) { + action.run(); + } + return result; + } + + public void setElement(int num) { + this.limit=num; + } +} \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 36b57bc..2761ab8 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -17,6 +17,7 @@ public class ServerLauncher { GameController gameController; RMIServer serverRMI; TCPServer serverTCP; + LimitedList players; @@ -25,6 +26,16 @@ public class ServerLauncher { this.serverRMI = serverRMI; this.gameController = gameController; this.serverTCP = serverTCP; + this.players = new LimitedList<>(5, ()->{ + synchronized (gameController) { + try { + serverRMI.notifyAll(gameController.getModel()); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + }); } public boolean doFirstEven() throws InterruptedException, RemoteException { @@ -59,21 +70,6 @@ public class ServerLauncher { public void run() throws InterruptedException, RemoteException { // Aggiunge il primo player e imposta il numero di giocatori voluti - AddPlayer player1 = (AddPlayer) actionQueue.take(); - Game model = new Game(player1.getProposedNPlayer()); - gameController.setModel(model); - player1.apply(gameController); - - for(int i=1; i Date: Fri, 24 Apr 2026 18:24:11 +0200 Subject: [PATCH 04/41] Fix: Fixed Initial Socket Connection Logic. Add: "broadcastModel" Method In TCPServer.java, "notifyModel" Method In ClientHandler.java. --- .../gc14/Network/TCP/Client/TCPClient.java | 4 +-- .../Network/TCP/Server/ClientHandler.java | 25 +++++++++++++++---- .../gc14/Network/TCP/Server/TCPServer.java | 21 +++++++++++++--- 3 files changed, 40 insertions(+), 10 deletions(-) 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 113cd2e..d29de4b 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 @@ -22,13 +22,13 @@ public class TCPClient implements Serializable{ this.port = port; } - public boolean start(String user){ + public boolean start(String user, int players){ try{ communicationSocket = new Socket(hostname, port); socketSend = new ObjectOutputStream(communicationSocket.getOutputStream()); socketReceive = new ObjectInputStream(communicationSocket.getInputStream()); - socketSend.writeObject(new AddPlayer(user)); + socketSend.writeObject(new AddPlayer(user, players)); if(communicationSocket.getInputStream().read() == -1){ return false; } 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 97ea3c1..d471ab0 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 @@ -1,12 +1,14 @@ package it.polimi.ingsw.gc14.Network.TCP.Server; import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.EventType; import java.io.*; import java.net.*; import java.util.List; +import java.util.concurrent.BlockingQueue; public class ClientHandler implements Runnable { private Socket clientSocket; @@ -14,17 +16,17 @@ public class ClientHandler implements Runnable { public ObjectInputStream in = null; public ObjectOutputStream out = null; List clientHandlers; - GameController gameController; + BlockingQueue actionQueue; private EventType eventType; public Socket getClientSocket() { return clientSocket; } - public ClientHandler(Socket clientSocket, List clientHandlers, GameController gameController) { + public ClientHandler(Socket clientSocket, List clientHandlers, BlockingQueue actionQueue) { this.clientSocket = clientSocket; this.clientHandlers = clientHandlers; - this.gameController = gameController; + this.actionQueue = actionQueue; } @Override @@ -41,7 +43,7 @@ public class ClientHandler implements Runnable { while(true){ try{ input = (NetworkEvent) (in.readObject()); - if(input.apply(gameController)){ + if(actionQueue.add(input)){ server.broadcastUpdate(input); } } @@ -64,13 +66,26 @@ public class ClientHandler implements Runnable { synchronized(out){ try{ out = new ObjectOutputStream(clientSocket.getOutputStream()); - out.writeObject(gameController.getModel()); + out.writeObject(event); } catch(IOException e){ e.printStackTrace(); } } } + + public void notifyModel(Game game){ + synchronized(out){ + try{ + out = new ObjectOutputStream(clientSocket.getOutputStream()); + out.writeObject(game); + } + catch(IOException e){ + e.printStackTrace(); + } + } + } + } 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 f7910a3..b1ab13d 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 @@ -1,7 +1,9 @@ package it.polimi.ingsw.gc14.Network.TCP.Server; import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; +import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; import java.io.*; import java.net.*; @@ -9,6 +11,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; + public class TCPServer { int port = -1; int ConnectedPlayers = 0; @@ -42,24 +45,32 @@ public class TCPServer { try{ clientSocket = serverTCP.accept(); - if(!gameController.addPlayer(clientSocket.getInputStream().toString()) || ConnectedPlayers > gameController.getModel().getNPlayers()){ + ObjectInputStream clientSocketObj = new ObjectInputStream(clientSocket.getInputStream()); + NetworkEvent event = (NetworkEvent) clientSocketObj.readObject(); + + //sincronizzazione su gameController + if(!(event instanceof AddPlayer) || (ConnectedPlayers >= gameController.getModel().getCurrentPlayerNumber() && gameController.getModel() != null)){ clientSocket.getOutputStream().write((int)(-1)); clientSocket.close(); System.out.println("Invalid parameters. Connection terminated.\n"); } else{ + actionQueue.add(event); clientSocket.getOutputStream().write((int)(1)); } // gestione di ADD_PLAYER } - catch (IOException e){ + catch(IOException e){ e.printStackTrace(); } + catch(ClassNotFoundException e){ + throw new RuntimeException(e); + } System.out.println("Accepted player: " + gameController.getModel().getPlayerByUsername(clientSocket.getInetAddress().toString())); ConnectedPlayers++; - ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, gameController); + ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, actionQueue); clientHandlers.add(clientHandler); //Sending model to clients @@ -91,4 +102,8 @@ public class TCPServer { public void broadcastUpdate(NetworkEvent event){ clientHandlers.forEach((x) -> x.notifyEvent(event)); } + + public void broadcastModel(){ + clientHandlers.forEach((x) -> x.notifyModel(gameController.getModel())); + } } From b413ff3bcff5b85fea8cf7b609b91748e875b565 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Fri, 24 Apr 2026 18:28:52 +0200 Subject: [PATCH 05/41] Add: LimitedList --- .../java/it/polimi/ingsw/gc14/LimitedList.java | 6 ++++-- .../it/polimi/ingsw/gc14/ServerLauncher.java | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/LimitedList.java b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java index fb582c3..0bb1d66 100644 --- a/src/main/java/it/polimi/ingsw/gc14/LimitedList.java +++ b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java @@ -2,7 +2,7 @@ package it.polimi.ingsw.gc14; import java.util.ArrayList; -public class LimitedList extends ArrayList { +public class LimitedList extends ArrayList { private int limit; private final Runnable action; @@ -12,7 +12,7 @@ public class LimitedList extends ArrayList { } @Override - public boolean add(Player element) { + public boolean add(String element) { boolean result = super.add(element); if (size() >= limit) { action.run(); @@ -23,4 +23,6 @@ public class LimitedList extends ArrayList { public void setElement(int num) { this.limit=num; } + + public int getLimit(){return limit;} } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 2761ab8..6db75a5 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -27,14 +27,13 @@ public class ServerLauncher { this.gameController = gameController; this.serverTCP = serverTCP; this.players = new LimitedList<>(5, ()->{ - synchronized (gameController) { - try { - serverRMI.notifyAll(gameController.getModel()); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + try { + run(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (RemoteException e) { + throw new RuntimeException(e); } - }); } @@ -70,7 +69,10 @@ public class ServerLauncher { public void run() throws InterruptedException, RemoteException { // Aggiunge il primo player e imposta il numero di giocatori voluti - + Game model = new Game(players.getLimit()); + gameController.setModel(model); + serverRMI.notifyAll(model); + //serverTCP.broadcastUpdate(model); while (true) { From 783380218776c8dfea09a369b8887ea1a18e9d67 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Fri, 24 Apr 2026 18:31:04 +0200 Subject: [PATCH 06/41] Fixed: RMIServer and RMIClient --- .../gc14/Network/RMI/Client/RMIClient.java | 4 +-- .../gc14/Network/RMI/Common/IGameServer.java | 2 +- .../gc14/Network/RMI/Server/RMIServer.java | 29 ++++++++++++++----- 3 files changed, 24 insertions(+), 11 deletions(-) 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 ac0e14b..8d0721c 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 @@ -18,7 +18,7 @@ public class RMIClient { } - public boolean connect(String username,ClientController clientController) { + public boolean connect(String username,int preferredInt,ClientController clientController) { // 1. Connettiti al registry try { Registry registry = LocateRegistry.getRegistry(host, port); @@ -29,7 +29,7 @@ public class RMIClient { // 3. Crea il callback e registralo ClientCallbackImpl callback = new ClientCallbackImpl(clientController); - if (!stub.joinGame(username, callback)) + if (!stub.joinGame(username,preferredInt, callback)) { stub = null; return false; 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 8bcaff6..7a1ef25 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 @@ -6,7 +6,7 @@ import java.rmi.*; public interface IGameServer extends Remote { - boolean joinGame(String username, IClientCallback callback) throws RemoteException; + boolean joinGame(String username,int preferredInt, IClientCallback callback) throws RemoteException; boolean doEvent(NetworkEvent event) throws RemoteException; } 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 d81eb96..9e3d0e8 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 @@ -1,6 +1,7 @@ package it.polimi.ingsw.gc14.Network.RMI.Server; import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.LimitedList; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; @@ -24,31 +25,43 @@ public class RMIServer implements IGameServer { private int nPort; private final Map clients = new ConcurrentHashMap<>(); BlockingQueue actionQueue; - + private LimitedList playerList; // Costruttore - public RMIServer(GameController controller, int nPort, BlockingQueue actionQueue) throws RemoteException { + public RMIServer(GameController controller, int nPort, BlockingQueue actionQueue,LimitedList playerList) throws RemoteException { this.controller = controller; this.nPort = nPort; this.actionQueue = actionQueue; + this.playerList = playerList; } + // Metodi esposti RMI public void setController (GameController controller) { this.controller = controller; } @Override - public boolean joinGame(String username, IClientCallback callback) { - if(controller.addPlayer(username)) - { - clients.put(username, callback); - return true; + public boolean joinGame(String username, int preferredInt,IClientCallback callback) { + synchronized (controller) { + if(playerList.size()==0 && (preferredInt<2||preferredInt>5)) + return false; + if (controller.addPlayer(username)) { + if(playerList.size()==0) + { + Game game= new Game(preferredInt); + controller.setModel(game); + playerList.setElement(preferredInt); + } + playerList.add(username); + clients.put(username, callback); + return true; + } + return false; } - return false; } @Override public boolean doEvent(NetworkEvent event) throws RemoteException { From b88b57e9d9bc068c98390878d8af3f0e0d3be810 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Fri, 24 Apr 2026 18:36:50 +0200 Subject: [PATCH 07/41] Fix: boh --- src/main/java/it/polimi/ingsw/gc14/LimitedList.java | 6 +++--- .../ingsw/gc14/Network/RMI/Server/RMIServer.java | 2 +- .../java/it/polimi/ingsw/gc14/ServerLauncher.java | 11 ++++------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/LimitedList.java b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java index 0bb1d66..7ef8a47 100644 --- a/src/main/java/it/polimi/ingsw/gc14/LimitedList.java +++ b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java @@ -2,7 +2,7 @@ package it.polimi.ingsw.gc14; import java.util.ArrayList; -public class LimitedList extends ArrayList { +public class LimitedList extends ArrayList { private int limit; private final Runnable action; @@ -12,7 +12,7 @@ public class LimitedList extends ArrayList { } @Override - public boolean add(String element) { + public boolean add(T element) { boolean result = super.add(element); if (size() >= limit) { action.run(); @@ -20,7 +20,7 @@ public class LimitedList extends ArrayList { return result; } - public void setElement(int num) { + public void setLimit(int num) { this.limit=num; } 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 9e3d0e8..fc74f3c 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 @@ -54,7 +54,7 @@ public class RMIServer implements IGameServer { { Game game= new Game(preferredInt); controller.setModel(game); - playerList.setElement(preferredInt); + playerList.setLimit(preferredInt); } playerList.add(username); clients.put(username, callback); diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 6db75a5..5197c13 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -17,7 +17,7 @@ public class ServerLauncher { GameController gameController; RMIServer serverRMI; TCPServer serverTCP; - LimitedList players; + static LimitedList players; @@ -59,8 +59,8 @@ public class ServerLauncher { BlockingQueue actionQueue = new LinkedBlockingQueue<>(); GameController gameController = new GameController(); - RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue); - TCPServer serverTCP = new TCPServer(gameController, 8080, actionQueue); + RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue, players); + TCPServer serverTCP = new TCPServer(gameController, 8080, actionQueue, players); ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP); launcher.run(); @@ -68,10 +68,7 @@ public class ServerLauncher { public void run() throws InterruptedException, RemoteException { - // Aggiunge il primo player e imposta il numero di giocatori voluti - Game model = new Game(players.getLimit()); - gameController.setModel(model); - serverRMI.notifyAll(model); + serverRMI.notifyAll(gameController.getModel()); //serverTCP.broadcastUpdate(model); From ce75e470c2becf3476540d08041c677de22ce105 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Fri, 24 Apr 2026 18:50:21 +0200 Subject: [PATCH 08/41] Fix: Fixed Player Adding Logic In TCPServer.java. --- .../gc14/Network/TCP/Server/TCPServer.java | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) 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 b1ab13d..96ac01a 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 @@ -1,6 +1,7 @@ package it.polimi.ingsw.gc14.Network.TCP.Server; import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.LimitedList; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; @@ -18,7 +19,7 @@ public class TCPServer { ServerSocket serverTCP = null; GameController gameController; BlockingQueue actionQueue; - + private LimitedList playerList; private List clientHandlers; @@ -48,15 +49,32 @@ public class TCPServer { ObjectInputStream clientSocketObj = new ObjectInputStream(clientSocket.getInputStream()); NetworkEvent event = (NetworkEvent) clientSocketObj.readObject(); - //sincronizzazione su gameController - if(!(event instanceof AddPlayer) || (ConnectedPlayers >= gameController.getModel().getCurrentPlayerNumber() && gameController.getModel() != null)){ - clientSocket.getOutputStream().write((int)(-1)); - clientSocket.close(); - System.out.println("Invalid parameters. Connection terminated.\n"); - } - else{ - actionQueue.add(event); - clientSocket.getOutputStream().write((int)(1)); + synchronized (gameController){ + if(!(event instanceof AddPlayer) || (gameController.getModel() != null && gameController.getModel().getCurrentPlayerNumber() >= gameController.getModel().getNPlayers())){ + clientSocket.getOutputStream().write((int)(-1)); + clientSocket.close(); + System.out.println("Invalid parameters. Connection terminated.\n"); + } + else{ + synchronized (gameController) { + AddPlayer addPlayer = (AddPlayer) event; + if(playerList.isEmpty() && (addPlayer.getProposedNPlayer() < 2 || addPlayer.getProposedNPlayer() > 5)){ + clientSocket.getOutputStream().write((int)(-1)); + clientSocket.close(); + System.out.println("Invalid parameters. Connection terminated.\n"); + } + else if(gameController.addPlayer(addPlayer.getUsername())){ + if(playerList.isEmpty()){ + Game game = new Game(addPlayer.getProposedNPlayer()); + gameController.setModel(game); + playerList.setLimit(addPlayer.getProposedNPlayer()); + } + playerList.add(addPlayer.getUsername()); + clientSocket.getOutputStream().write((int)(1)); + } + } + + } } // gestione di ADD_PLAYER } @@ -93,10 +111,11 @@ public class TCPServer { } } - public TCPServer(GameController gameController, int port, BlockingQueue actionQueue){ + public TCPServer(GameController gameController, int port, BlockingQueue actionQueue, LimitedList players){ this.port = port; this.gameController = gameController; this.actionQueue = actionQueue; + this.playerList = players; } public void broadcastUpdate(NetworkEvent event){ From 152a744a8bbc771df5340fe19d493eb58f70147c Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Fri, 24 Apr 2026 18:53:19 +0200 Subject: [PATCH 09/41] Fix: Fixed "broadcastModel" Method In TCPServer.java. --- .../it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 96ac01a..7c928c3 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 @@ -122,7 +122,7 @@ public class TCPServer { clientHandlers.forEach((x) -> x.notifyEvent(event)); } - public void broadcastModel(){ - clientHandlers.forEach((x) -> x.notifyModel(gameController.getModel())); + public void broadcastModel(Game model){ + clientHandlers.forEach((x) -> x.notifyModel(model)); } } From e184158ae4a1861522b864cd183cd19c435dbd1e Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Fri, 24 Apr 2026 19:02:04 +0200 Subject: [PATCH 10/41] Fix: ServerLauncher --- .../it/polimi/ingsw/gc14/LimitedList.java | 6 +++- .../it/polimi/ingsw/gc14/ServerLauncher.java | 28 +++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/LimitedList.java b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java index 7ef8a47..6aa8cf9 100644 --- a/src/main/java/it/polimi/ingsw/gc14/LimitedList.java +++ b/src/main/java/it/polimi/ingsw/gc14/LimitedList.java @@ -4,7 +4,7 @@ import java.util.ArrayList; public class LimitedList extends ArrayList { private int limit; - private final Runnable action; + private Runnable action; public LimitedList(int limit, Runnable action) { this.limit = limit; @@ -25,4 +25,8 @@ public class LimitedList extends ArrayList { } public int getLimit(){return limit;} + + public void setAction(Runnable action) { + this.action=action; + } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 5197c13..67d4dfd 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -13,6 +13,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class ServerLauncher { + BlockingQueue actionQueue; GameController gameController; RMIServer serverRMI; @@ -26,15 +27,6 @@ public class ServerLauncher { this.serverRMI = serverRMI; this.gameController = gameController; this.serverTCP = serverTCP; - this.players = new LimitedList<>(5, ()->{ - try { - run(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - }); } public boolean doFirstEven() throws InterruptedException, RemoteException { @@ -57,19 +49,31 @@ public class ServerLauncher { // Il server RMI e il server TCP quando ricevono un doEvent devono aggiungere l'evento alla coda condivisa // Questa classe esegue gli eventi nella coda e chiama il notify all e notify error sia RMI che TCP + players = new LimitedList<>(5, ()->{}); BlockingQueue actionQueue = new LinkedBlockingQueue<>(); GameController gameController = new GameController(); RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue, players); TCPServer serverTCP = new TCPServer(gameController, 8080, actionQueue, players); - ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP); - launcher.run(); + + players.setAction(()->{ + try { + launcher.run(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + }); + + serverRMI.start(); + new Thread(()->{serverTCP.start();}).start(); } public void run() throws InterruptedException, RemoteException { serverRMI.notifyAll(gameController.getModel()); - //serverTCP.broadcastUpdate(model); + serverTCP.broadcastModel(gameController.getModel()); while (true) { From d69a806b3d3b5cd5ef6b597c54bbc48ce08caf8b Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sat, 25 Apr 2026 16:24:03 +0200 Subject: [PATCH 11/41] Add: ASCII Builder --- .../ingsw/gc14/View/TUI/AsciiTable.java | 48 ++++++++++ .../ingsw/gc14/View/TUI/BorderStyle.java | 39 ++++++++ .../it/polimi/ingsw/gc14/View/TUI/TUI.java | 93 +++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java create mode 100644 src/main/java/it/polimi/ingsw/gc14/View/TUI/BorderStyle.java create mode 100644 src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java new file mode 100644 index 0000000..7f6b1fc --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -0,0 +1,48 @@ +package it.polimi.ingsw.gc14.View.TUI; +import java.util.*; + +// Helper generale per costruire tabelle ASCII +public class AsciiTable { + private final BorderStyle s; + private final int cols, colWidth; + private final List> rows = new ArrayList<>(); + private final List separators = new ArrayList<>(); + + public AsciiTable(BorderStyle s, int cols, int colWidth) { + this.s = s; this.cols = cols; this.colWidth = colWidth; + } + + public void addRow(String... cells) { rows.add(Arrays.asList(cells)); } + public void addRow(List cells) { rows.add(cells); } + public void addHeader(String... cells) { rows.add(0, Arrays.asList(cells)); separators.add(0); } + public void addSeparator() { separators.add(rows.size()); } + + public String build() { + var sb = new StringBuilder(); + sb.append(hline(s.tl(), s.mt(), s.tr())).append('\n'); + for (int i = 0; i < rows.size(); i++) { + sb.append(s.v()); + for (String cell : rows.get(i)) + sb.append(rpad(" " + cell, colWidth)).append(s.v()); + sb.append('\n'); + if (separators.contains(i) && i < rows.size() - 1) + sb.append(hline(s.sl(), s.sx(), s.sr())).append('\n'); + } + sb.append(hline(s.bl(), s.mb(), s.br())); + return sb.toString(); + } + + private String hline(String l, String m, String r) { + var sb = new StringBuilder(l); + for (int i = 0; i < cols; i++) { + sb.append(s.h().repeat(colWidth)); + if (i < cols - 1) sb.append(m); + } + return sb.append(r).toString(); + } + + private String rpad(String s, int w) { + if (s.length() >= w) return s.substring(0, w); + return s + " ".repeat(w - s.length()); + } +} \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/BorderStyle.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/BorderStyle.java new file mode 100644 index 0000000..13b365d --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/BorderStyle.java @@ -0,0 +1,39 @@ +package it.polimi.ingsw.gc14.View.TUI; + +public enum BorderStyle { + UNICODE("╔","╗","╚","╝","═","║","╠","╣","╦","╩","╬","├","┤","─","┼"), + ASCII ("+","+","+","+","-","|","+","+","+","+","+","+","+","-","+"), + ROUNDED("╭","╮","╰","╯","─","│","├","┤","┬","┴","┼","├","┤","─","┼"); + + private final String tl,tr,bl,br,h,v,ml,mr,mt,mb,x,sl,sr,sh,sx; + + BorderStyle(String tl,String tr,String bl,String br, + String h, String v, String ml,String mr, + String mt,String mb,String x, + String sl,String sr,String sh,String sx) { + this.tl = tl; this.tr = tr; + this.bl = bl; this.br = br; + this.h = h; this.v = v; + this.ml = ml; this.mr = mr; + this.mt = mt; this.mb = mb; + this.x = x; + this.sl = sl; this.sr = sr; + this.sh = sh; this.sx = sx; + } + + public String tl() { return tl; } + public String tr() { return tr; } + public String bl() { return bl; } + public String br() { return br; } + public String h() { return h; } + public String v() { return v; } + public String ml() { return ml; } + public String mr() { return mr; } + public String mt() { return mt; } + public String mb() { return mb; } + public String x() { return x; } + public String sl() { return sl; } + public String sr() { return sr; } + public String sh() { return sh; } + public String sx() { return sx; } +} 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 new file mode 100644 index 0000000..1880c51 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java @@ -0,0 +1,93 @@ +package it.polimi.ingsw.gc14.View.TUI; +import it.polimi.ingsw.gc14.Model.Game; + +public class TUI { + + // ── dati di stato ─────────────────────────────────────────── + private BorderStyle style = BorderStyle.UNICODE; + private Game model; + // ── punto di ingresso ─────────────────────────────────────── + public String render() { + var sb = new StringBuilder(); + sb.append(renderHeader()); + sb.append(renderTurnOrder()); + sb.append(renderOfferTrack()); + sb.append(renderCardRows()); + sb.append(renderTableaux()); + sb.append(renderFooter()); + return sb.toString(); + } + + // ── sezioni ───────────────────────────────────────────────── + private String renderTurnOrder() { + var table = new AsciiTable(style, 4, 10); // 4 colonne, largh 10 + table.addRow(model.getPlayers().stream() + .map(p -> + ". " + p.getUserName()) + .toList()); + table.addRow(state.getPlayers().stream() + .map(p -> p.getTotemPosition() != null + ? "totem: " + p.getTotemPosition() + : "(da piaz)") + .toList()); + return " TURN ORDER\n" + table.build() + "\n"; + } + + private String renderOfferTrack() { + var table = new AsciiTable(style, 5, 14); + table.addRow(state.getOfferTiles().stream() + .map(t -> t.getId() + ": " + t.getLabel()).toList()); + table.addRow(state.getOfferTiles().stream() + .map(OfferTile::getRowsLabel).toList()); + table.addRow(state.getOfferTiles().stream() + .map(t -> state.getTotemOnTile(t.getId())).toList()); + return " OFFER TRACK\n" + table.build() + "\n"; + } + + private String renderCardRows() { + int cols = state.getTopRow().size(); + var table = new AsciiTable(style, cols, 13); + table.addRow(state.getTopRow().stream() + .map(c -> "[" + c.getTypeLabel() + "]").toList()); + table.addRow(state.getTopRow().stream() + .map(Card::getName).toList()); + table.addSeparator(); + table.addRow(state.getBotRow().stream() + .map(c -> "[" + c.getTypeLabel() + "]").toList()); + table.addRow(state.getBotRow().stream() + .map(Card::getName).toList()); + return " CARTE IN GIOCO\n" + prefix("TOP ", "BOT ", table.build()) + "\n"; + } + + private String renderTableaux() { + var sb = new StringBuilder(" TABLEAU GIOCATORI\n\n"); + for (Player p : state.getPlayers()) { + String marker = p.isActive() ? ">>>" : " "; + sb.append(String.format(" %s %s%s Food:%d PP:%d%n", + marker, p.getName(), + p.isActive() ? " [TUO TURNO]" : "", + p.getFood(), p.getPP())); + sb.append(renderPlayerTableau(p)); + sb.append("\n"); + } + return sb.toString(); + } + + private String renderPlayerTableau(Player p) { + var table = new AsciiTable(style, 3, 14); + table.addHeader("PERSONAGGI", "EDIFICI", "RISORSE"); + int rows = Math.max(p.getChars().size(), + Math.max(p.getBuildings().size(), 3)); + for (int i = 0; i < rows; i++) { + String ch = i < p.getChars().size() ? p.getChars().get(i) : ""; + String bd = i < p.getBuildings().size() ? p.getBuildings().get(i) : ""; + String rs = switch (i) { + case 0 -> "Food: " + "O".repeat(p.getFood()); + case 1 -> "PP: " + p.getPP(); + case 2 -> "Chars:" + p.getChars().size() + " Edif:" + p.getBuildings().size(); + default -> ""; + }; + table.addRow(ch, bd, rs); + } + return " " + table.build().replace("\n", "\n "); + } +} From 59dd27f1233cfd9bc342f2b9c502036e5677f7cc Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sat, 25 Apr 2026 16:27:42 +0200 Subject: [PATCH 12/41] Add: JavaDOC explaining the network stack workflow --- .../it/polimi/ingsw/gc14/ServerLauncher.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 67d4dfd..04de37c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -13,12 +13,30 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class ServerLauncher { + /** + * Main server launcher that handles both TCP and RMI connections. + * The workflow is divided into two parts: game creation and game execution. + * + * The process flow for game creation is as follows: + * - The first client (TCP/RMI) requests to join the game by providing a username and the desired number of players + * - The TCP/RMI server checks {@link #playerList} and, if it is empty, sets the number of players according to the first user's request using {@link LimitedList#setLimit(int)} + * - The TCP/RMI server creates the {@link Game} with the requested number of players and adds the player to {@link #playerList} + * - Other players request to join the game (their requested number of players is ignored) + * - When the number of players in {@link #playerList} reaches the {@link LimitedList}'s limit, the list calls {@link #run()} + * - All players are notified with the {@link Game} + * + * The process flow for game execution is as follows: + * - The TCP/RMI server receives a {@link NetworkEvent} from a client and adds it to the {@link #actionQueue} + * - The {@link #run()} method repeatedly calls {@link #doFirstEvent()}, which takes the first event in the {@link #actionQueue} and tries to apply it + * - If the event is successfully applied to the model, all players receive the event + * - Otherwise, the player who sent the action receives an error notification + */ BlockingQueue actionQueue; GameController gameController; RMIServer serverRMI; TCPServer serverTCP; - static LimitedList players; + static LimitedList playerList; @@ -29,7 +47,7 @@ public class ServerLauncher { this.serverTCP = serverTCP; } - public boolean doFirstEven() throws InterruptedException, RemoteException { + public boolean doFirstEvent() throws InterruptedException, RemoteException { NetworkEvent event = actionQueue.take(); if(event.apply(gameController)) { serverRMI.notifyAll(event); @@ -49,14 +67,14 @@ public class ServerLauncher { // Il server RMI e il server TCP quando ricevono un doEvent devono aggiungere l'evento alla coda condivisa // Questa classe esegue gli eventi nella coda e chiama il notify all e notify error sia RMI che TCP - players = new LimitedList<>(5, ()->{}); + playerList = new LimitedList<>(5, ()->{}); BlockingQueue actionQueue = new LinkedBlockingQueue<>(); GameController gameController = new GameController(); - RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue, players); - TCPServer serverTCP = new TCPServer(gameController, 8080, actionQueue, players); + RMIServer serverRMI = new RMIServer(gameController, 1099, actionQueue, playerList); + TCPServer serverTCP = new TCPServer(gameController, 8080, actionQueue, playerList); ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP); - players.setAction(()->{ + playerList.setAction(()->{ try { launcher.run(); } catch (InterruptedException e) { @@ -76,9 +94,10 @@ public class ServerLauncher { serverTCP.broadcastModel(gameController.getModel()); + // Game execution while (true) { try { - this.doFirstEven(); + this.doFirstEvent(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; From 1a69fade7c3c21bba9bf68994196f6fc046e9886 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Sat, 25 Apr 2026 16:38:13 +0200 Subject: [PATCH 13/41] Fix: Test Commit. --- .../gc14/Model/Cards/Building/Effects/Building0Test.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building0Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building0Test.java index 5420c00..effb1df 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building0Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building0Test.java @@ -143,8 +143,4 @@ class Building0Test { b0.buy(p1); assertFalse(b0.buy(p2)); } - - - - } \ No newline at end of file From 7f5899432634e7bcc3672caa592a8924663b2251 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Sat, 25 Apr 2026 17:07:34 +0200 Subject: [PATCH 14/41] Add: Added "toString" Method And Relevant Test In Building1.java And Building1Test.java. --- .../Cards/Building/Effects/Building1.java | 7 +++--- .../Cards/Building/Effects/Building1Test.java | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1.java index cdf7261..6bb3579 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1.java @@ -2,11 +2,8 @@ package it.polimi.ingsw.gc14.Model.Cards.Building.Effects; import it.polimi.ingsw.gc14.Model.Cards.Building.EffectType; import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; -import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; -import it.polimi.ingsw.gc14.Model.Player; -import java.util.HashMap; /** * During the Sustenance Event, you have a discount of 1 food token on the total you @@ -47,4 +44,8 @@ public class Building1 extends BuildingCard { return new Building1(getEra(),getPrice(),getPrestigeValue(),getIcon()); } + @Override + public String toString() { + return super.toString() + " Icon: " + this.icon.toString(); + } } diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1Test.java index eb76d5c..cfd9ef4 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1Test.java @@ -66,4 +66,26 @@ class Building1Test { assertEquals(Prestige, bClone.getPrestigeValue()); assertEquals(ct, b0.getIcon()); } + + @Test + @DisplayName("toString") + void testToString(){ + Building1 b1 = new Building1(1,2,3, CharacterType.INVENTOR); + assertEquals("Era:1 Price:2 Prestige:3 Icon: INVENTOR", b1.toString()); + + b1 = new Building1(1,2,3, CharacterType.BUILDER); + assertEquals("Era:1 Price:2 Prestige:3 Icon: BUILDER", b1.toString()); + + b1 = new Building1(1,2,3, CharacterType.GATHERER); + assertEquals("Era:1 Price:2 Prestige:3 Icon: GATHERER", b1.toString()); + + b1 = new Building1(1,2,3, CharacterType.ARTIST); + assertEquals("Era:1 Price:2 Prestige:3 Icon: ARTIST", b1.toString()); + + b1 = new Building1(1,2,3, CharacterType.SHAMAN); + assertEquals("Era:1 Price:2 Prestige:3 Icon: SHAMAN", b1.toString()); + + b1 = new Building1(1,2,3, CharacterType.HUNTER); + assertEquals("Era:1 Price:2 Prestige:3 Icon: HUNTER", b1.toString()); + } } \ No newline at end of file From 65bb479b9e1b75fcf75bb490a2524fe608729827 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Sat, 25 Apr 2026 17:34:01 +0200 Subject: [PATCH 15/41] Add: Added "toString" Method And Relevant Test In Building11.java And Building11Test.java. --- .../Cards/Building/Effects/Building11.java | 7 ++++++ .../Building/Effects/Building11Test.java | 23 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11.java index 5b47de1..59f86c0 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11.java @@ -6,6 +6,7 @@ import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.Player; public class Building11 extends BuildingCard { + private CharacterType icon ; /** @@ -14,6 +15,7 @@ public class Building11 extends BuildingCard { * @return the CharacterType associated with this building card effect. */ public CharacterType getIcon() {return icon;} + private int PrestigeMul; /** @@ -65,4 +67,9 @@ public class Building11 extends BuildingCard { throw new IllegalArgumentException(); player.addPrestige(player.getNType(getIcon()) * this.getPrestigeMul()); } + + @Override + public String toString() { + return super.toString() + " Icon: " + this.icon.toString(); + } } \ No newline at end of file diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11Test.java index 296b0da..620233a 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11Test.java @@ -3,7 +3,6 @@ package it.polimi.ingsw.gc14.Model.Cards.Building.Effects; import it.polimi.ingsw.gc14.Model.Cards.Building.EffectType; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Artist; -import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Hunter; import it.polimi.ingsw.gc14.Model.Player; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -109,4 +108,26 @@ class Building11Test { b4.applyEffect(p5); }); } + + @Test + @DisplayName("toString") + void testToString(){ + Building11 b11 = new Building11(1,2,3, CharacterType.INVENTOR, 1); + assertEquals("Era:1 Price:2 Prestige:3 Icon: INVENTOR", b11.toString()); + + b11 = new Building11(1,2,3, CharacterType.BUILDER, 1); + assertEquals("Era:1 Price:2 Prestige:3 Icon: BUILDER", b11.toString()); + + b11 = new Building11(1,2,3, CharacterType.GATHERER, 1); + assertEquals("Era:1 Price:2 Prestige:3 Icon: GATHERER", b11.toString()); + + b11 = new Building11(1,2,3, CharacterType.ARTIST, 1); + assertEquals("Era:1 Price:2 Prestige:3 Icon: ARTIST", b11.toString()); + + b11 = new Building11(1,2,3, CharacterType.SHAMAN, 1); + assertEquals("Era:1 Price:2 Prestige:3 Icon: SHAMAN", b11.toString()); + + b11 = new Building11(1,2,3, CharacterType.HUNTER, 1); + assertEquals("Era:1 Price:2 Prestige:3 Icon: HUNTER", b11.toString()); + } } \ No newline at end of file From 3a8706603c6d2cf592ada1c1a39c2eb4664db520 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sat, 25 Apr 2026 17:34:28 +0200 Subject: [PATCH 16/41] Add: JavaDOC in ServerLauncher Fix: Action error handling in the entire network stack Modified: TCP's broadcast methods name --- .../ingsw/gc14/Network/NetworkEvent.java | 17 +++- .../RMI/Client/ClientCallbackImpl.java | 14 ++- .../Network/RMI/Common/IClientCallback.java | 1 - .../gc14/Network/RMI/Server/RMIServer.java | 4 - .../gc14/Network/TCP/Client/TCPClient.java | 17 +++- .../Network/TCP/Server/ClientHandler.java | 6 +- .../gc14/Network/TCP/Server/TCPServer.java | 4 +- .../it/polimi/ingsw/gc14/ServerLauncher.java | 89 ++++++++++++------- 8 files changed, 100 insertions(+), 52 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvent.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvent.java index abc510c..1a5d50c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvent.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvent.java @@ -1,7 +1,6 @@ package it.polimi.ingsw.gc14.Network; import it.polimi.ingsw.gc14.Controller.GameController; -import javafx.event.Event; import java.io.Serializable; @@ -12,9 +11,23 @@ public abstract class NetworkEvent implements Serializable { } protected EventType eventType; public EventType getEventType() {return eventType;} - protected NetworkEvent(String username, EventType eventType) { + protected boolean isError; + public boolean getIsError() {return isError;} + public void setIsError(boolean isError) {this.isError = isError;} + + protected NetworkEvent(String username, EventType eventType, boolean isError) { this.username = username; this.eventType = eventType; + this.isError = isError; + } + + @Override + public String toString() { + if(isError) { + return ("ERROR: action " + eventType.toString()); + } else { + return ("ACTION: action " + eventType.toString()); + } } public abstract boolean apply(GameController gameController); diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java index d6b54d7..871b653 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java @@ -23,13 +23,11 @@ public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCa @Override public void onAction(NetworkEvent event) throws RemoteException { - event.apply(clientController.localController); // delega tutto al controller - //clientController.view.update(); TODO + if(event.getIsError()) { + System.out.println(event.toString()); + } else { + event.apply(clientController.localController); // delega tutto al controller + //clientController.view.update(); TODO + } } - - @Override - public void onError(String message) throws RemoteException { - clientController.onError(message); - } - } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java index 5ff2b0b..0292fcc 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java @@ -8,5 +8,4 @@ import java.rmi.*; public interface IClientCallback extends Remote { void onGameInit(Game model) throws RemoteException; void onAction(NetworkEvent action) throws RemoteException; - void onError(String message) throws RemoteException; } \ No newline at end of file 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 fc74f3c..e575a8f 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 @@ -83,10 +83,6 @@ public class RMIServer implements IGameServer { cb.onGameInit(model); } } - public void notifyError(String username, String message) throws RemoteException { - IClientCallback cb = clients.get(username); - if (cb != null) cb.onError(message); - } 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 d29de4b..9a39808 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 @@ -1,6 +1,7 @@ package it.polimi.ingsw.gc14.Network.TCP.Client; import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; @@ -46,7 +47,21 @@ public class TCPClient implements Serializable{ private void ReceiveMessage(){ while(true){ try{ - ((NetworkEvent)(socketReceive.readObject())).apply(controller); + Object read = socketReceive.readObject(); + + if (read instanceof NetworkEvent) { //TODO non fare con instanceof + NetworkEvent event = (NetworkEvent) read; + if(event.getIsError()) { + System.out.println(event.toString()); + } else { + event.apply(controller); + //clientController.view.update(); TODO + } + } + else if (read instanceof Game) { + controller.setModel((Game) read); + } + } catch(IOException e){ e.printStackTrace(); 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 d471ab0..a989868 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 @@ -43,8 +43,8 @@ public class ClientHandler implements Runnable { while(true){ try{ input = (NetworkEvent) (in.readObject()); - if(actionQueue.add(input)){ - server.broadcastUpdate(input); + if(!actionQueue.add(input)){ + System.out.println("An error occurred in inserting an action into queue"); } } catch(java.io.IOException e){ @@ -53,8 +53,6 @@ public class ClientHandler implements Runnable { catch (ClassNotFoundException e){ throw new RuntimeException(e); } - - } } catch (IOException e) { 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 7c928c3..2a79695 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 @@ -118,11 +118,11 @@ public class TCPServer { this.playerList = players; } - public void broadcastUpdate(NetworkEvent event){ + public void notifAll(NetworkEvent event){ clientHandlers.forEach((x) -> x.notifyEvent(event)); } - public void broadcastModel(Game model){ + public void notifyAll(Game model){ clientHandlers.forEach((x) -> x.notifyModel(model)); } } diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 04de37c..dabe7a0 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -12,34 +12,58 @@ import java.rmi.RemoteException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -public class ServerLauncher { - /** - * Main server launcher that handles both TCP and RMI connections. - * The workflow is divided into two parts: game creation and game execution. - * - * The process flow for game creation is as follows: - * - The first client (TCP/RMI) requests to join the game by providing a username and the desired number of players - * - The TCP/RMI server checks {@link #playerList} and, if it is empty, sets the number of players according to the first user's request using {@link LimitedList#setLimit(int)} - * - The TCP/RMI server creates the {@link Game} with the requested number of players and adds the player to {@link #playerList} - * - Other players request to join the game (their requested number of players is ignored) - * - When the number of players in {@link #playerList} reaches the {@link LimitedList}'s limit, the list calls {@link #run()} - * - All players are notified with the {@link Game} - * - * The process flow for game execution is as follows: - * - The TCP/RMI server receives a {@link NetworkEvent} from a client and adds it to the {@link #actionQueue} - * - The {@link #run()} method repeatedly calls {@link #doFirstEvent()}, which takes the first event in the {@link #actionQueue} and tries to apply it - * - If the event is successfully applied to the model, all players receive the event - * - Otherwise, the player who sent the action receives an error notification - */ +/** + * Main server launcher that handles both TCP and RMI connections. + * The workflow is divided into two parts: game creation and game execution. + * + * The process flow for game creation is as follows: + * - The first client (TCP/RMI) requests to join the game by providing a username and the desired number of players + * - The TCP/RMI server checks {@link #playerList} and, if it is empty, sets the number of players according to the first user's request using {@link LimitedList#setLimit(int)} + * - The TCP/RMI server creates the {@link Game} with the requested number of players and adds the player to {@link #playerList} + * - Other players request to join the game (their requested number of players is ignored) + * - When the number of players in {@link #playerList} reaches the {@link LimitedList}'s limit, the list calls {@link #run()} + * - All players are notified with the {@link Game} + * + * The process flow for game execution is as follows: + * - The TCP/RMI server receives a {@link NetworkEvent} from a client and adds it to the {@link #actionQueue} + * - The {@link #run()} method repeatedly calls {@link #doFirstEvent()}, which takes the first event in the {@link #actionQueue} and tries to apply it + * - If the event is successfully applied to the model, all players receive the event + * - Otherwise, the player who sent the action receives an error notification + */ +public class ServerLauncher { + + /** + * List containing the events that have to be applied to the game's model. + * Thread safe by design. + */ BlockingQueue actionQueue; + + /** Game controller. Used to apply events */ GameController gameController; + + /** Server RMI. Handles RMI clients */ RMIServer serverRMI; + + /** Server TCP. Handles TCP clients */ TCPServer serverTCP; + + /** + * List containing the username of joined players. + * {@link LimitedList}'s limit defines at which size the list calls its action + * Both limit and action can be set with {@link LimitedList#setLimit(int)} and {@link LimitedList#setAction(Runnable)} + * The limit is set by the first player joining the game. The action consists in calling {@link #run()} + */ static LimitedList playerList; - + /** + * Class constructor that initializes the attributes. + * @param actionQueue is the list containing the events + * @param gameController is the game controller + * @param serverRMI is the server RMI + * @param serverTCP is the server TCP + */ public ServerLauncher(BlockingQueue actionQueue, GameController gameController, RMIServer serverRMI, TCPServer serverTCP) { this.actionQueue = actionQueue; this.serverRMI = serverRMI; @@ -47,17 +71,22 @@ public class ServerLauncher { this.serverTCP = serverTCP; } + + /** + * Takes the first event in the actionQueue and attempt to apply it to the game controller. + * If the event can be applied, all clients (both TCP and RMI) are notified with the event. Otherwise, the user who sent the action will be notified with an error. + * @return the outcome of attempting to apply the event to the controller + * @throws InterruptedException if any problem in accessing actionQueue is issued + * @throws RemoteException if any RMI problem is issued + */ public boolean doFirstEvent() throws InterruptedException, RemoteException { NetworkEvent event = actionQueue.take(); - if(event.apply(gameController)) { - serverRMI.notifyAll(event); - serverTCP.broadcastUpdate(event); - return true; - } else { - serverRMI.notifyError(event.getUsername(), "Mossa non valida"); // TODO Converrebbe mettere in network event un booleano che dice se è stato accettato e fare una notifyAll anche per errori - //serverTCP // TODO non esiste un notify error (guarda sopra) - return false; - } + event.setIsError(!event.apply(gameController)); + + serverRMI.notifyAll(event); + serverTCP.notifAll(event); + + return !event.getIsError(); } @@ -91,7 +120,7 @@ public class ServerLauncher { public void run() throws InterruptedException, RemoteException { serverRMI.notifyAll(gameController.getModel()); - serverTCP.broadcastModel(gameController.getModel()); + serverTCP.notifyAll(gameController.getModel()); // Game execution From 27903f1738756cd6f911ff2907a09b32bd90e476 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sat, 25 Apr 2026 17:36:24 +0200 Subject: [PATCH 17/41] Fix: compilation errors due to wrong number of parameters --- .../it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java | 2 +- .../ingsw/gc14/Network/NetworkEvents/DrawLowerBuildingCard.java | 2 +- .../ingsw/gc14/Network/NetworkEvents/DrawLowerTribeCard.java | 2 +- .../ingsw/gc14/Network/NetworkEvents/DrawUpperBuildingCard.java | 2 +- .../ingsw/gc14/Network/NetworkEvents/DrawUpperTribeCard.java | 2 +- .../gc14/Network/NetworkEvents/PickOptionalBuildingCard.java | 2 +- .../ingsw/gc14/Network/NetworkEvents/PickOptionalTribeCard.java | 2 +- .../it/polimi/ingsw/gc14/Network/NetworkEvents/SlotChoice.java | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java index d8ab797..8466942 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/AddPlayer.java @@ -13,7 +13,7 @@ public class AddPlayer extends NetworkEvent implements Serializable { return proposedNPlayer; } public AddPlayer(String username, int proposedNPlayer) { - super(username, EventType.ADD_PLAYER); + super(username, EventType.ADD_PLAYER, false); this.proposedNPlayer = proposedNPlayer; } @Override diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawLowerBuildingCard.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawLowerBuildingCard.java index 2456a6a..5656ac8 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawLowerBuildingCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawLowerBuildingCard.java @@ -11,7 +11,7 @@ public class DrawLowerBuildingCard extends NetworkEvent implements Serializable private int pos; public DrawLowerBuildingCard(String username, int pos){ - super(username, EventType.DRAW_LOWER_BUILD); + super(username, EventType.DRAW_LOWER_BUILD, false); this.pos = pos; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawLowerTribeCard.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawLowerTribeCard.java index 64b0a17..277627a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawLowerTribeCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawLowerTribeCard.java @@ -11,7 +11,7 @@ public class DrawLowerTribeCard extends NetworkEvent implements Serializable{ private int pos; public DrawLowerTribeCard(String username, int pos){ - super(username, EventType.DRAW_LOWER_TRIBE); + super(username, EventType.DRAW_LOWER_TRIBE, false); this.pos = pos; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawUpperBuildingCard.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawUpperBuildingCard.java index 5f0a985..6fb06cf 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawUpperBuildingCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawUpperBuildingCard.java @@ -11,7 +11,7 @@ public class DrawUpperBuildingCard extends NetworkEvent implements Serializable private int pos; public DrawUpperBuildingCard(String username, int pos){ - super(username, EventType.DRAW_UPPER_BUILD); + super(username, EventType.DRAW_UPPER_BUILD, false); this.pos = pos; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawUpperTribeCard.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawUpperTribeCard.java index 69ab281..8d37f02 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawUpperTribeCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DrawUpperTribeCard.java @@ -11,7 +11,7 @@ public class DrawUpperTribeCard extends NetworkEvent implements Serializable{ private int pos; public DrawUpperTribeCard(String username, int pos){ - super(username, EventType.DRAW_UPPER_TRIBE); + super(username, EventType.DRAW_UPPER_TRIBE, false); this.pos = pos; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/PickOptionalBuildingCard.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/PickOptionalBuildingCard.java index a1fde73..36be45c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/PickOptionalBuildingCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/PickOptionalBuildingCard.java @@ -11,7 +11,7 @@ public class PickOptionalBuildingCard extends NetworkEvent implements Serializa private int pos; public PickOptionalBuildingCard(String username, int pos){ - super(username, EventType.PICK_OPTIONAL_BUILD); + super(username, EventType.PICK_OPTIONAL_BUILD, false); this.pos = pos; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/PickOptionalTribeCard.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/PickOptionalTribeCard.java index d739e3c..f2dadac 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/PickOptionalTribeCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/PickOptionalTribeCard.java @@ -11,7 +11,7 @@ public class PickOptionalTribeCard extends NetworkEvent implements Serializable private int pos; public PickOptionalTribeCard(String username, int pos){ - super(username, EventType.PICK_OPTIONAL_TRIBE); + super(username, EventType.PICK_OPTIONAL_TRIBE, false); this.pos = pos; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/SlotChoice.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/SlotChoice.java index 97000d9..4bf0d12 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/SlotChoice.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/SlotChoice.java @@ -11,7 +11,7 @@ public class SlotChoice extends NetworkEvent implements Serializable { private int pos; public SlotChoice(String username, int pos) { - super(username, EventType.SLOT_CHOICE); + super(username, EventType.SLOT_CHOICE, false); this.pos = pos; } From 6ebfd4d0260780548f597d7c82a15d0e690a6388 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sat, 25 Apr 2026 18:16:13 +0200 Subject: [PATCH 18/41] Add: complete JavaDOC to ServerLauncher --- .../gc14/Network/RMI/Server/RMIServer.java | 2 +- .../gc14/Network/TCP/Server/TCPServer.java | 2 +- .../it/polimi/ingsw/gc14/ServerLauncher.java | 60 +++++++++++-------- 3 files changed, 38 insertions(+), 26 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 e575a8f..1770da4 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 @@ -52,7 +52,7 @@ public class RMIServer implements IGameServer { if (controller.addPlayer(username)) { if(playerList.size()==0) { - Game game= new Game(preferredInt); + Game game = new Game(preferredInt); controller.setModel(game); playerList.setLimit(preferredInt); } 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 2a79695..fc86f84 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 @@ -118,7 +118,7 @@ public class TCPServer { this.playerList = players; } - public void notifAll(NetworkEvent event){ + public void notifyAll(NetworkEvent event){ clientHandlers.forEach((x) -> x.notifyEvent(event)); } diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index dabe7a0..df3c776 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -23,18 +23,18 @@ import java.util.concurrent.LinkedBlockingQueue; * - The TCP/RMI server creates the {@link Game} with the requested number of players and adds the player to {@link #playerList} * - Other players request to join the game (their requested number of players is ignored) * - When the number of players in {@link #playerList} reaches the {@link LimitedList}'s limit, the list calls {@link #run()} - * - All players are notified with the {@link Game} + * - All players are notified of the {@link Game} * * The process flow for game execution is as follows: * - The TCP/RMI server receives a {@link NetworkEvent} from a client and adds it to the {@link #actionQueue} * - The {@link #run()} method repeatedly calls {@link #doFirstEvent()}, which takes the first event in the {@link #actionQueue} and tries to apply it - * - If the event is successfully applied to the model, all players receive the event - * - Otherwise, the player who sent the action receives an error notification + * - If the event cannot be successfully applied to the model, its {@code isError} flag is set to {@code true} + * - All players are notified of the event */ public class ServerLauncher { /** - * List containing the events that have to be applied to the game's model. + * Queue containing the events to be applied to the game model. * Thread safe by design. */ BlockingQueue actionQueue; @@ -49,9 +49,9 @@ public class ServerLauncher { TCPServer serverTCP; /** - * List containing the username of joined players. + * List containing the usernames of joined players. * {@link LimitedList}'s limit defines at which size the list calls its action - * Both limit and action can be set with {@link LimitedList#setLimit(int)} and {@link LimitedList#setAction(Runnable)} + * Both the limit and the action can be set using {@link LimitedList#setLimit(int)} and {@link LimitedList#setAction(Runnable)} * The limit is set by the first player joining the game. The action consists in calling {@link #run()} */ static LimitedList playerList; @@ -59,10 +59,10 @@ public class ServerLauncher { /** * Class constructor that initializes the attributes. - * @param actionQueue is the list containing the events - * @param gameController is the game controller - * @param serverRMI is the server RMI - * @param serverTCP is the server TCP + * @param actionQueue The queue containing the events + * @param gameController The game controller + * @param serverRMI The server RMI + * @param serverTCP The server TCP */ public ServerLauncher(BlockingQueue actionQueue, GameController gameController, RMIServer serverRMI, TCPServer serverTCP) { this.actionQueue = actionQueue; @@ -73,29 +73,34 @@ public class ServerLauncher { /** - * Takes the first event in the actionQueue and attempt to apply it to the game controller. - * If the event can be applied, all clients (both TCP and RMI) are notified with the event. Otherwise, the user who sent the action will be notified with an error. - * @return the outcome of attempting to apply the event to the controller - * @throws InterruptedException if any problem in accessing actionQueue is issued - * @throws RemoteException if any RMI problem is issued + * Takes the first event in the actionQueue and attempts to apply it to the game controller. + * If the event cannot be applied, its isError flag is set to true; otherwise, it is set to false. + * 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 { NetworkEvent event = actionQueue.take(); event.setIsError(!event.apply(gameController)); serverRMI.notifyAll(event); - serverTCP.notifAll(event); + serverTCP.notifyAll(event); return !event.getIsError(); } - public static void main() throws RemoteException, InterruptedException { - // TODO - // Deve avere una coda con gli eventi. - // Il server RMI e il server TCP quando ricevono un doEvent devono aggiungere l'evento alla coda condivisa - // Questa classe esegue gli eventi nella coda e chiama il notify all e notify error sia RMI che TCP - + /** + * The first method executed when the server program is launched. + * It creates all the objects needed: playerList, actionQueue, gameController, serverRMI, serverTCP, launcher. + * Then sets the playerList's action to execute launcher.run() and starts the TCP/RMI servers. + * Note: the model is initialized and set in the controller in TCP/RMI servers when the first user decides the number of players. + * + * @throws InterruptedException if this exception is issued by run method + * @throws RemoteException if this exception is issued by run method + */ + public static void main(String[] args) throws InterruptedException, RemoteException { playerList = new LimitedList<>(5, ()->{}); BlockingQueue actionQueue = new LinkedBlockingQueue<>(); GameController gameController = new GameController(); @@ -117,12 +122,19 @@ public class ServerLauncher { new Thread(()->{serverTCP.start();}).start(); } - public void run() throws InterruptedException, RemoteException { + /** + * Creates and executes the game. + * 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 creation serverRMI.notifyAll(gameController.getModel()); serverTCP.notifyAll(gameController.getModel()); - // Game execution while (true) { try { From 87691764959914f96f20fbca5f3110c181587b68 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Sat, 25 Apr 2026 18:21:31 +0200 Subject: [PATCH 19/41] Fix: Fixed "toString" Method In Character.java. --- .../polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java | 2 +- .../ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java index 9cdb9ae..d8d1284 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java @@ -57,7 +57,7 @@ public abstract class Character extends TribeCard implements Cloneable { */ @Override public String toString() { - return super.toString()+" "+type.toString(); + return type.toString() + " -- " + super.toString(); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java index 3fb9706..deef818 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java @@ -86,7 +86,9 @@ public class Builder extends Character * @return the string representation of this Builder card. */ @Override - public String toString() { return super.toString()+" Reduction Value: " + String.valueOf(reductionValue) + "\n Prestige Value: " + String.valueOf(prestigeValue); } + public String toString() { + return super.toString() + " Reduction Value: " + String.valueOf(reductionValue) + " Prestige Value: " + String.valueOf(prestigeValue); + } /** * Creates and returns a copy of this Builder card. From e1386287b2faf62246b377651412a45d4051f6f0 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sat, 25 Apr 2026 18:41:14 +0200 Subject: [PATCH 20/41] Fix: ASCII Builder --- .../ingsw/gc14/Model/Orders/Order3.java | 31 +++++++++++++++++++ .../ingsw/gc14/View/TUI/AsciiTable.java | 14 +++++---- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java index fc7f6d2..3eb13b9 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java @@ -2,8 +2,11 @@ package it.polimi.ingsw.gc14.Model.Orders; import it.polimi.ingsw.gc14.Model.OrderLogicCard; import it.polimi.ingsw.gc14.Model.Player; +import it.polimi.ingsw.gc14.View.TUI.AsciiTable; +import it.polimi.ingsw.gc14.View.TUI.BorderStyle; import java.util.ArrayList; +import java.util.List; import java.util.NoSuchElementException; public class Order3 extends OrderLogicCard { @@ -49,4 +52,32 @@ public class Order3 extends OrderLogicCard { } } } + @Override + public String toString() + { + + var table = new AsciiTable(BorderStyle.UNICODE, 3); + List tempPlayer=new ArrayList<>(players); + List stringList=new ArrayList<>(); + + for(int i=0;i<3;i++) + { + try { + tempPlayer.get(i); + stringList.add(i+". "+tempPlayer.get(i).getUserName()); + } + catch (IndexOutOfBoundsException e) { + stringList.add(i+". "); + } + } + table.addRow(stringList); + stringList=new ArrayList<>(); + stringList.add("+2 Food"); + stringList.add(" --"); + stringList.add("-1 Food / -2 Prestige"); + table.addRow(stringList); + + + return "TURN ORDER\n" + table.build() + "\n"; + } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java index 7f6b1fc..0688727 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -19,23 +19,25 @@ public class AsciiTable { public String build() { var sb = new StringBuilder(); - sb.append(hline(s.tl(), s.mt(), s.tr())).append('\n'); + int maxWidth = rows.stream().mapToInt(x->x.stream().mapToInt(y->y.length()).max().getAsInt()).max().getAsInt()+1; + sb.append(hline(s.tl(), s.mt(), s.tr(),maxWidth)).append('\n'); + for (int i = 0; i < rows.size(); i++) { sb.append(s.v()); for (String cell : rows.get(i)) - sb.append(rpad(" " + cell, colWidth)).append(s.v()); + sb.append(rpad(" " + cell, maxWidth)).append(s.v()); sb.append('\n'); if (separators.contains(i) && i < rows.size() - 1) - sb.append(hline(s.sl(), s.sx(), s.sr())).append('\n'); + sb.append(hline(s.sl(), s.sx(), s.sr(),maxWidth)).append('\n'); } - sb.append(hline(s.bl(), s.mb(), s.br())); + sb.append(hline(s.bl(), s.mb(), s.br(), maxWidth)); return sb.toString(); } - private String hline(String l, String m, String r) { + private String hline(String l, String m, String r,int maxWidth) { var sb = new StringBuilder(l); for (int i = 0; i < cols; i++) { - sb.append(s.h().repeat(colWidth)); + sb.append(s.h().repeat(maxWidth)); if (i < cols - 1) sb.append(m); } return sb.append(r).toString(); From 79aaaf6f335ecd8505c6dc46a8eff8ffcfcc4054 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sat, 25 Apr 2026 18:44:40 +0200 Subject: [PATCH 21/41] Fix: ASCII Builder --- src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java index 0688727..e26018c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -4,12 +4,12 @@ import java.util.*; // Helper generale per costruire tabelle ASCII public class AsciiTable { private final BorderStyle s; - private final int cols, colWidth; + private final int cols; private final List> rows = new ArrayList<>(); private final List separators = new ArrayList<>(); - public AsciiTable(BorderStyle s, int cols, int colWidth) { - this.s = s; this.cols = cols; this.colWidth = colWidth; + public AsciiTable(BorderStyle s, int cols) { + this.s = s; this.cols = cols; } public void addRow(String... cells) { rows.add(Arrays.asList(cells)); } From 269ce0d13bf1419267a46d908df5c892e2461e1e Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sat, 25 Apr 2026 18:55:28 +0200 Subject: [PATCH 22/41] Add: partial JavaDOC to RMIServer --- .../gc14/Network/RMI/Server/RMIServer.java | 75 ++++++++++++------- 1 file changed, 50 insertions(+), 25 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 1770da4..d960cc1 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 @@ -15,19 +15,47 @@ import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; - import java.rmi.*; + +/** + * Server RMI. Exposes a method to join the game and one to execute an event. + */ public class RMIServer implements IGameServer { + /** Server game's controller */ private GameController controller; + + /** Server game's model */ + private Game model; + + /** RMI registry */ private Registry registry; + + /** RMI port */ private int nPort; + + /** Map containing the associations between a player's username and its callback */ private final Map clients = new ConcurrentHashMap<>(); + + /** Queue containing the events to be applied to the game model */ BlockingQueue actionQueue; + + /** + * List containing the usernames of joined players. + * {@link LimitedList}'s limit defines at which size the list calls its action. The limit can be set using {@link LimitedList#setLimit(int)}. + */ private LimitedList playerList; - // Costruttore + + /** + * Class constructor that initializes the attributes. + * @param controller The game controller + * @param nPort The RMI port + * @param actionQueue The action queue + * @param playerList The player's usernames list + * @throws RemoteException if an RMI error occurs + */ public RMIServer(GameController controller, int nPort, BlockingQueue actionQueue,LimitedList playerList) throws RemoteException { this.controller = controller; this.nPort = nPort; @@ -36,26 +64,29 @@ public class RMIServer implements IGameServer { } - - - - - // Metodi esposti RMI - public void setController (GameController controller) { - this.controller = controller; - } + // RMI's exposed methods + /** + * Allows a player to join the game. + * If the desired number of player is invalid, the request is rejected. + * If this is the first player, a new game model is created and passed to the controller. Additionally, the playerList's limit is set. + * Then, if the controller successfully adds the player, the username is added to {@link #playerList} and {@link #clients}. + * @param username The player's name + * @param preferredInt The desired number of players + * @param callback The client's callback interface + * @return true if the player successfully joined the game, false otherwise + */ @Override - public boolean joinGame(String username, int preferredInt,IClientCallback callback) { + public boolean joinGame(String username, int preferredInt, IClientCallback callback) { + if (preferredInt<2 || preferredInt>5) { + return false; + } synchronized (controller) { - if(playerList.size()==0 && (preferredInt<2||preferredInt>5)) - return false; + if(playerList.isEmpty()){ + model = new Game(preferredInt); + controller.setModel(model); + playerList.setLimit(preferredInt); + } if (controller.addPlayer(username)) { - if(playerList.size()==0) - { - Game game = new Game(preferredInt); - controller.setModel(game); - playerList.setLimit(preferredInt); - } playerList.add(username); clients.put(username, callback); return true; @@ -69,9 +100,6 @@ public class RMIServer implements IGameServer { } - - - // Metodi interni del server public void notifyAll(NetworkEvent action) throws RemoteException { for (IClientCallback cb : clients.values()) { @@ -85,9 +113,6 @@ public class RMIServer implements IGameServer { } - - - // Metodi per avviare server RMI public boolean start() { try { From 3f727335a9c4e28d2131ce7c647ab1634e959cd9 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sat, 25 Apr 2026 19:11:33 +0200 Subject: [PATCH 23/41] Add: Complete JavaDOC to RMIServer --- .../gc14/Network/RMI/Server/RMIServer.java | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 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 d960cc1..3578350 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 @@ -64,6 +64,7 @@ public class RMIServer implements IGameServer { } + // RMI's exposed methods /** * Allows a player to join the game. @@ -94,18 +95,36 @@ public class RMIServer implements IGameServer { return false; } } + + + /** + * Push an action in actionQueue. + * @param action The desired actio + * @return true if the action was successfully added, false otherwise + */ @Override - public boolean doEvent(NetworkEvent event) throws RemoteException { - return actionQueue.offer(event); + public boolean doEvent(NetworkEvent action) { + return actionQueue.offer(action); } - // Metodi interni del server + + // RMI's internal methods + /** + * Sends an action to all RMI clients. + * @param action The desired action + */ public void notifyAll(NetworkEvent action) throws RemoteException { for (IClientCallback cb : clients.values()) { cb.onAction(action); } } + + + /** + * Sends a model game to all RMI clients. + * @param model The desired model + */ public void notifyAll(Game model) throws RemoteException { for (IClientCallback cb : clients.values()) { cb.onGameInit(model); @@ -113,12 +132,17 @@ public class RMIServer implements IGameServer { } + // Metodi per avviare server RMI + /** + * Starts the RMI server. + * @return true if the server starts successfully, false otherwise + */ public boolean start() { try { registry = LocateRegistry.createRegistry(nPort); registry.rebind("RMIGameServer", this); - System.out.println("RMI Server avviato sulla porta "+nPort); + System.out.println("RMI Server started on port: "+nPort); return true; } catch (Exception e) { @@ -126,6 +150,12 @@ public class RMIServer implements IGameServer { return false; } } + + + /** + * Stops the RMI server. + * @return true if the server stops successfully, false otherwise + */ public boolean stop() { try { registry.unbind("RMIGameServer"); From 2f6a20b9f8a7d458a445a068ebbe9f245c88158b Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sat, 25 Apr 2026 19:23:26 +0200 Subject: [PATCH 24/41] Add: Complete JavaDOC of RMIClient and ClientCallbackImpl --- .../RMI/Client/ClientCallbackImpl.java | 31 ++++++++++- .../gc14/Network/RMI/Client/RMIClient.java | 53 ++++++++++++------- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java index 871b653..928fa52 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java @@ -8,25 +8,52 @@ import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; + +/** + * RMI client callback implementation of {@link IClientCallback}. + * Receives notifications from the server and updates the client game model. + */ public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCallback { + /** The client controller used to apply events and update the model */ private final ClientController clientController; + + /** + * Class constructor. + * @param clientController the client controller + * @throws RemoteException if any RMI error occurs + */ public ClientCallbackImpl(ClientController clientController) throws RemoteException { this.clientController = clientController; } + + /** + * Called by the server when the game is initialized. + * Sets the client game model in the {@link ClientController}. + * @param model the initialized {@link Game} model + * @throws RemoteException if any RMI error occurs + */ @Override public void onGameInit(Game model) throws RemoteException { - clientController.setModel(model); // setta il model + clientController.setModel(model); } + + /** + * Called by the server when an action has been accepted. + * If the event contains an error, it is printed to the console. + * Otherwise, the event is applied to the local model. + * @param event the {@link NetworkEvent} sent by the server + * @throws RemoteException if any RMI error occurs + */ @Override public void onAction(NetworkEvent event) throws RemoteException { if(event.getIsError()) { System.out.println(event.toString()); } else { - event.apply(clientController.localController); // delega tutto al controller + event.apply(clientController.localController); //clientController.view.update(); TODO } } 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 8d0721c..84d797f 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 @@ -1,43 +1,56 @@ package it.polimi.ingsw.gc14.Network.RMI.Client; +import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Network.NetworkEvent; +import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer; +import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer; -public class RMIClient { +/** + * Client RMI. Uses the methods exposed by the server RMI. + */ +public class RMIClient { + /** The host address of the RMI server */ private final String host; + + /** The port of the RMI server */ private final int port; + + /** The remote stub used to call methods on the server */ private IGameServer stub; + + /** + * Class constructor. + * @param host the host address of the RMI server + * @param port the port of the RMI server + */ public RMIClient(String host, int port) { this.host = host; this.port = port; } - public boolean connect(String username,int preferredInt,ClientController clientController) { - // 1. Connettiti al registry + /** + * Connects to the RMI server and attempts to join the game. + * Looks up the RMI registry to retrieve the {@link IGameServer} stub. + * Then, creates a {@link ClientCallbackImpl} and calls {@link RMIServer#joinGame(String, int, IClientCallback)}. + * @param username the player's username + * @param preferredInt the desired number of players + * @param clientController the client controller used to create the callback + * @return true if the player successfully joined the game, false otherwise + */ + public boolean connect(String username,int preferredInt, ClientController clientController) { try { Registry registry = LocateRegistry.getRegistry(host, port); - - // 2. Prendi lo stub del server this.stub = (IGameServer) registry.lookup("RMIGameServer"); - - // 3. Crea il callback e registralo ClientCallbackImpl callback = new ClientCallbackImpl(clientController); - if (!stub.joinGame(username,preferredInt, callback)) - { - stub = null; - return false; - } - else - { - return true; - } + return stub.joinGame(username, preferredInt, callback); } catch (Exception e) { e.printStackTrace(); @@ -46,8 +59,12 @@ public class RMIClient { } - - public void doEvent(NetworkEvent event) throws Exception { + /** + * Sends a {@link NetworkEvent} to the server. + * @param event the event to send + * @throws RemoteException if any RMI error occurs + */ + public void doEvent(NetworkEvent event) throws RemoteException { stub.doEvent(event); } From d2f3a549b35031644a3a9d9175132007b4ce8690 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Sat, 25 Apr 2026 20:17:05 +0200 Subject: [PATCH 25/41] Fix: "toString" Testing For Player.java. --- .../it/polimi/ingsw/gc14/Model/Player.java | 56 ++++++++++++++----- .../polimi/ingsw/gc14/Model/PlayerTest.java | 15 ++--- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Player.java b/src/main/java/it/polimi/ingsw/gc14/Model/Player.java index bef8cbd..8a79130 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Player.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Player.java @@ -3,10 +3,14 @@ package it.polimi.ingsw.gc14.Model; import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.*; +import it.polimi.ingsw.gc14.View.TUI.AsciiTable; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; + +import static it.polimi.ingsw.gc14.View.TUI.BorderStyle.*; /** * Default Player class; contains all identifiers and methods needed. @@ -224,21 +228,47 @@ public class Player implements Serializable { // endregion constructors // region Functions - // TODO tostring usr + food + prestige \n tab foreach(characters.cards + spazio) @Override public String toString() { - String toPrint = ""; - toPrint = this.getUserName() - + ":\n\tFood: " + this.getFoodValue() - + "\n\tPrestige: " + this.getPrestigeValue() - + "\n\tArtists: " + this.artists.toString() - + "\n\tBuilders: " + this.builders.toString() - + "\n\tGatherers: " + this.gatherers.toString() - + "\n\tShamans: " + this.shamans.toString() - + "\n\tHunters: " + this.hunters.toString() - + "\n\tBuildings: " - + this.buildingCards.toString(); - return toPrint; + var table = new AsciiTable(UNICODE, 1); + + table.addHeader(this.getUserName()); + table.addRow("RESOURCES:"); + table.addRow("Food: " + this.getFoodValue()); + table.addSeparator(); + table.addRow("Prestige: " + this.getPrestigeValue()); + + + table.addRow("CHARACTERS:"); + if(!this.artists.isEmpty()){ + table.addRow("Artists: " + this.artists.toString()); + } + + if(!this.builders.isEmpty()){ + table.addRow("Builders: " + this.builders.toString()); + } + + if(!this.gatherers.isEmpty()){ + table.addRow("Gatherers: " + this.gatherers.toString()); + } + + if(!this.shamans.isEmpty()){ + table.addRow("Shamans: " + this.shamans.toString()); + } + + if(!this.hunters.isEmpty()){ + table.addRow("Hunters: " + this.hunters.toString()); + } + + //TODO fix ? + table.addSeparator(); + table.addRow("BUILDING CARDS:"); + + if(!this.buildingCards.isEmpty()){ + table.addRow("Buildings: " + this.buildingCards.toString()); + } + + return table.build(); } // endregion functions } diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java b/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java index 79990ec..9696ec7 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java @@ -200,17 +200,14 @@ class PlayerTest { p.addPrestige(15); p.addFood(7); p.artists.add(new Artist(1)); + p.artists.add(new Artist(1)); + p.artists.add(new Artist(1)); + p.artists.add(new Artist(1)); + p.artists.add(new Artist(1)); + p.artists.add(new Artist(1)); p.artists.add(new Artist(2)); p.buildingCards.add(new BuildingCard(2, 1,2, 5)); p.buildingCards.add(new BuildingCard(2, 2,3, 6)); - assertEquals("test_usr:"+ "\n\t" + - "Food: 7" + "\n\t" + - "Prestige: 15" + "\n\t" + - "Artists: [Era:1 ARTIST, Era:2 ARTIST]" + "\n\t" + "Builders: []" + "\n\t" + - "Gatherers: []" + "\n\t" + - "Shamans: []" + "\n\t" + - "Hunters: []" + "\n\t" + - "Buildings: [Era:1 Price:2 Prestige:5, Era:2 Price:3 Prestige:6]", - p.toString()); + System.out.println(p.toString()); } } \ No newline at end of file From 1f44e415e4626256c74dc38753b674cb46a7458a Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sun, 26 Apr 2026 16:16:05 +0200 Subject: [PATCH 26/41] Fix: major changes to TCP server/client stack. --- .../gc14/Network/TCP/Client/TCPClient.java | 31 +++--- .../Network/TCP/Server/ClientHandler.java | 39 +++----- .../gc14/Network/TCP/Server/TCPServer.java | 95 ++++++++----------- 3 files changed, 68 insertions(+), 97 deletions(-) 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 9a39808..adf63f6 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 @@ -8,11 +8,10 @@ import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; import java.io.*; import java.net.*; -public class TCPClient implements Serializable{ - Socket communicationSocket = null; +public class TCPClient { + Socket communicationSocket; ObjectInputStream socketReceive; ObjectOutputStream socketSend; - GameController controller; String hostname; int port; @@ -23,43 +22,44 @@ public class TCPClient implements Serializable{ this.port = port; } - public boolean start(String user, int players){ + public boolean start(String user, int proposedNPlayers){ try{ communicationSocket = new Socket(hostname, port); socketSend = new ObjectOutputStream(communicationSocket.getOutputStream()); socketReceive = new ObjectInputStream(communicationSocket.getInputStream()); - socketSend.writeObject(new AddPlayer(user, players)); + sendEvent(new AddPlayer(user, proposedNPlayers)); if(communicationSocket.getInputStream().read() == -1){ + System.out.println("Could not connect to server"); return false; } else{ - Thread listener = new Thread(() -> ReceiveMessage()); + Thread listener = new Thread(() -> receiveMessage()); listener.start(); return true; } - } - catch(Exception e){ + } catch (IOException e) { + e.printStackTrace(); return false; } + } - private void ReceiveMessage(){ + private void receiveMessage(){ while(true){ try{ Object read = socketReceive.readObject(); - if (read instanceof NetworkEvent) { //TODO non fare con instanceof - NetworkEvent event = (NetworkEvent) read; + if (read instanceof NetworkEvent event) { //TODO non fare con instanceof if(event.getIsError()) { - System.out.println(event.toString()); + System.out.println(event); } else { event.apply(controller); //clientController.view.update(); TODO } } - else if (read instanceof Game) { - controller.setModel((Game) read); + else if (read instanceof Game model) { + controller.setModel(model); } } @@ -69,11 +69,10 @@ public class TCPClient implements Serializable{ catch(ClassNotFoundException e){ throw new RuntimeException(e); } - return; } } - private void SendEvent(NetworkEvent event){ + private void sendEvent(NetworkEvent event){ try{ socketSend.writeObject(event); } 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 a989868..1a98f12 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 @@ -1,9 +1,7 @@ package it.polimi.ingsw.gc14.Network.TCP.Server; -import it.polimi.ingsw.gc14.Controller.GameController; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; -import it.polimi.ingsw.gc14.Network.EventType; import java.io.*; import java.net.*; @@ -12,12 +10,10 @@ import java.util.concurrent.BlockingQueue; public class ClientHandler implements Runnable { private Socket clientSocket; - private TCPServer server; - public ObjectInputStream in = null; - public ObjectOutputStream out = null; + public ObjectInputStream in; + public ObjectOutputStream out; List clientHandlers; BlockingQueue actionQueue; - private EventType eventType; public Socket getClientSocket() { return clientSocket; @@ -31,33 +27,24 @@ public class ClientHandler implements Runnable { @Override public void run(){ - clientLoop(); - } - - private void clientLoop(){ try{ - NetworkEvent input = null; - synchronized(in){ - in = new ObjectInputStream(clientSocket.getInputStream()); - } + in = new ObjectInputStream(clientSocket.getInputStream()); + out = new ObjectOutputStream(clientSocket.getOutputStream()); + while(true){ - try{ - input = (NetworkEvent) (in.readObject()); - if(!actionQueue.add(input)){ - System.out.println("An error occurred in inserting an action into queue"); - } - } - catch(java.io.IOException e){ - e.printStackTrace(); - } - catch (ClassNotFoundException e){ - throw new RuntimeException(e); + NetworkEvent event = (NetworkEvent) in.readObject(); + if(!actionQueue.add(event)){ + System.out.println("Error inserting action into queue"); } } } - catch (IOException e) { + catch(IOException e){ + clientHandlers.remove(this); e.printStackTrace(); } + catch(ClassNotFoundException e){ + throw new RuntimeException(e); + } } public void notifyEvent(NetworkEvent event){ 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 fc86f84..a8698c2 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 @@ -3,6 +3,7 @@ package it.polimi.ingsw.gc14.Network.TCP.Server; import it.polimi.ingsw.gc14.Controller.GameController; import it.polimi.ingsw.gc14.LimitedList; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Network.EventType; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; @@ -14,32 +15,29 @@ import java.util.concurrent.BlockingQueue; public class TCPServer { - int port = -1; - int ConnectedPlayers = 0; - ServerSocket serverTCP = null; - GameController gameController; + int port; + int ConnectedPlayers; + ServerSocket serverTCP; + GameController controller; BlockingQueue actionQueue; private LimitedList playerList; private List clientHandlers; - - private int getConnectedPlayers(){ return ConnectedPlayers; } public void start(){ - clientHandlers = new ArrayList<>(); try{ serverTCP = new ServerSocket(port); } catch (IOException e){ - System.out.println("Could not listen on port: " + port); + System.out.println("Could not start the server TCP on port: " + port); e.printStackTrace(); return; } - System.out.println("Listening on port: " + port); + System.out.println("Server TCP started on port: " + port); while(true){ Socket clientSocket = null; @@ -49,34 +47,42 @@ public class TCPServer { ObjectInputStream clientSocketObj = new ObjectInputStream(clientSocket.getInputStream()); NetworkEvent event = (NetworkEvent) clientSocketObj.readObject(); - synchronized (gameController){ - if(!(event instanceof AddPlayer) || (gameController.getModel() != null && gameController.getModel().getCurrentPlayerNumber() >= gameController.getModel().getNPlayers())){ - clientSocket.getOutputStream().write((int)(-1)); + if(!(event.getEventType() == EventType.ADD_PLAYER)){ + clientSocket.getOutputStream().write((int)(-1)); + clientSocket.close(); + System.out.println("Invalid parameters. Connection terminated.\n"); + } + else{ + AddPlayer eventAddPlayer = (AddPlayer) event; + if (eventAddPlayer.getProposedNPlayer() < 2 || eventAddPlayer.getProposedNPlayer() > 5) { + clientSocket.getOutputStream().write((int) (-1)); clientSocket.close(); System.out.println("Invalid parameters. Connection terminated.\n"); } - else{ - synchronized (gameController) { - AddPlayer addPlayer = (AddPlayer) event; - if(playerList.isEmpty() && (addPlayer.getProposedNPlayer() < 2 || addPlayer.getProposedNPlayer() > 5)){ - clientSocket.getOutputStream().write((int)(-1)); - clientSocket.close(); - System.out.println("Invalid parameters. Connection terminated.\n"); - } - else if(gameController.addPlayer(addPlayer.getUsername())){ - if(playerList.isEmpty()){ - Game game = new Game(addPlayer.getProposedNPlayer()); - gameController.setModel(game); - playerList.setLimit(addPlayer.getProposedNPlayer()); - } - playerList.add(addPlayer.getUsername()); - clientSocket.getOutputStream().write((int)(1)); - } + synchronized (controller) { + if (playerList.isEmpty()){ + Game model = new Game(eventAddPlayer.getProposedNPlayer()); + controller.setModel(model); + playerList.setLimit(eventAddPlayer.getProposedNPlayer()); } + if (controller.addPlayer(eventAddPlayer.getUsername())) { + playerList.add(eventAddPlayer.getUsername()); + clientSocket.getOutputStream().write((int) (1)); + System.out.println("Accepted player: " + eventAddPlayer.getUsername()); + ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, actionQueue); + clientHandlers.add(clientHandler); + ConnectedPlayers++; + + Thread t = new Thread(clientHandler); + t.start(); + } else { + clientSocket.getOutputStream().write((int) (-1)); + clientSocket.close(); + System.out.println("Player could not be added. Connection terminated.\n"); + } } } - // gestione di ADD_PLAYER } catch(IOException e){ e.printStackTrace(); @@ -84,38 +90,17 @@ public class TCPServer { catch(ClassNotFoundException e){ throw new RuntimeException(e); } - - System.out.println("Accepted player: " + gameController.getModel().getPlayerByUsername(clientSocket.getInetAddress().toString())); - - ConnectedPlayers++; - ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, actionQueue); - clientHandlers.add(clientHandler); - - //Sending model to clients - if(ConnectedPlayers == gameController.getModel().getNPlayers()){ - for (ClientHandler handler : clientHandlers) { - try { - synchronized(handler.out){ - ObjectOutputStream socketTx = new ObjectOutputStream(handler.getClientSocket().getOutputStream()); - socketTx.writeObject(gameController.getModel()); - } - } - catch(IOException e){ - e.printStackTrace(); - } - } - } - - Thread t = new Thread(clientHandler); - t.start(); } } public TCPServer(GameController gameController, int port, BlockingQueue actionQueue, LimitedList players){ this.port = port; - this.gameController = gameController; + this.ConnectedPlayers = 0; + this.serverTCP = null; + this.controller = gameController; this.actionQueue = actionQueue; this.playerList = players; + this.clientHandlers = new ArrayList<>(); } public void notifyAll(NetworkEvent event){ From d707f16d0bcc43c0ddb077f97cbdae4c916265d9 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Sun, 26 Apr 2026 16:24:55 +0200 Subject: [PATCH 27/41] Fix: Fixed "toString" Method Of Player.java. --- .../it/polimi/ingsw/gc14/Model/Player.java | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Player.java b/src/main/java/it/polimi/ingsw/gc14/Model/Player.java index 8a79130..76db84c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Player.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Player.java @@ -230,6 +230,8 @@ public class Player implements Serializable { // region Functions @Override public String toString() { + int Last = 5; + var table = new AsciiTable(UNICODE, 1); table.addHeader(this.getUserName()); @@ -238,32 +240,64 @@ public class Player implements Serializable { table.addSeparator(); table.addRow("Prestige: " + this.getPrestigeValue()); + if(!this.hunters.isEmpty()){ + Last = 5; + } + else if(!this.shamans.isEmpty()){ + Last = 4; + } + else if(!this.gatherers.isEmpty()){ + Last = 3; + } + else if(!this.builders.isEmpty()){ + Last = 2; + } + else if(!this.inventors.isEmpty()){ + Last = 1; + } + else{ + Last = 0; + } + if(Last == 0){ + table.addSeparator(); + } table.addRow("CHARACTERS:"); if(!this.artists.isEmpty()){ + if(Last == 1){ + table.addSeparator(); + } table.addRow("Artists: " + this.artists.toString()); } if(!this.builders.isEmpty()){ + if(Last == 2){ + table.addSeparator(); + } table.addRow("Builders: " + this.builders.toString()); } if(!this.gatherers.isEmpty()){ + if(Last == 3){ + table.addSeparator(); + } table.addRow("Gatherers: " + this.gatherers.toString()); } if(!this.shamans.isEmpty()){ + if(Last == 4){ + table.addSeparator(); + } table.addRow("Shamans: " + this.shamans.toString()); } + if(!this.hunters.isEmpty()){ + table.addSeparator(); table.addRow("Hunters: " + this.hunters.toString()); } - //TODO fix ? - table.addSeparator(); table.addRow("BUILDING CARDS:"); - if(!this.buildingCards.isEmpty()){ table.addRow("Buildings: " + this.buildingCards.toString()); } From 07584ec5a3450200a95a1245da9214c9dd643df8 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sun, 26 Apr 2026 16:33:10 +0200 Subject: [PATCH 28/41] Fix: removed unused class in ClientHandler Add: complete JavaDOC to TCPServer --- .../gc14/Network/RMI/Server/RMIServer.java | 2 +- .../Network/TCP/Server/ClientHandler.java | 3 - .../gc14/Network/TCP/Server/TCPServer.java | 62 +++++++++++++++---- 3 files changed, 51 insertions(+), 16 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 3578350..05152c1 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 @@ -122,7 +122,7 @@ public class RMIServer implements IGameServer { /** - * Sends a model game to all RMI clients. + * Sends a game model to all RMI clients. * @param model The desired model */ public void notifyAll(Game model) throws RemoteException { 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 1a98f12..d6de535 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 @@ -15,9 +15,6 @@ public class ClientHandler implements Runnable { List clientHandlers; BlockingQueue actionQueue; - public Socket getClientSocket() { - return clientSocket; - } public ClientHandler(Socket clientSocket, List clientHandlers, BlockingQueue actionQueue) { this.clientSocket = clientSocket; 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 a8698c2..3c1d442 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 @@ -13,24 +13,50 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; - +/** + * Server TCP. Accepts connections and manages all client handlers. + */ public class TCPServer { + + /** TCP port */ int port; + + /** Number of currently connected clients */ int ConnectedPlayers; - ServerSocket serverTCP; + + /** Socket TCP */ + ServerSocket socketTCP; + + /** Server game's controller */ GameController controller; + + /** Queue containing the events to be applied to the game model */ BlockingQueue actionQueue; + + /** + * List containing the usernames of joined players. + * {@link LimitedList}'s limit defines at which size the list calls its action. The limit can be set using {@link LimitedList#setLimit(int)}. + */ private LimitedList playerList; + + /** List containing all client's handlers */ private List clientHandlers; - private int getConnectedPlayers(){ - return ConnectedPlayers; - } + /** + * Starts the TCP server. + * If the first event is not AddPlayer, the request is rejected. + * If the desired number of player is invalid, the request is rejected. + * + * If this is the first player to connect, a new game model is created and passed to the controller. Additionally, the playerList's limit is set. + * If the controller successfully adds the player, the username is added to {@link #playerList} and the handler is added to {@link #clientHandlers}. + * + * If any error occurs, the server sends -1 back to the client. Otherwise, it sends 1. + */ public void start(){ try{ - serverTCP = new ServerSocket(port); + socketTCP = new ServerSocket(port); } catch (IOException e){ System.out.println("Could not start the server TCP on port: " + port); @@ -38,12 +64,12 @@ public class TCPServer { return; } System.out.println("Server TCP started on port: " + port); + Socket clientSocket; while(true){ - Socket clientSocket = null; try{ - clientSocket = serverTCP.accept(); + clientSocket = socketTCP.accept(); ObjectInputStream clientSocketObj = new ObjectInputStream(clientSocket.getInputStream()); NetworkEvent event = (NetworkEvent) clientSocketObj.readObject(); @@ -93,20 +119,32 @@ public class TCPServer { } } - public TCPServer(GameController gameController, int port, BlockingQueue actionQueue, LimitedList players){ + + /** + * Class constructor that initializes the attributes. + * @param controller The game controller + * @param port The TCP port + * @param actionQueue The action queue + * @param playerList The player's usernames list + */ + public TCPServer(GameController controller, int port, BlockingQueue actionQueue, LimitedList playerList){ this.port = port; this.ConnectedPlayers = 0; - this.serverTCP = null; - this.controller = gameController; + this.socketTCP = null; + this.controller = controller; this.actionQueue = actionQueue; - this.playerList = players; + this.playerList = playerList; this.clientHandlers = new ArrayList<>(); } + + /** Sends an action to all TCP clients */ public void notifyAll(NetworkEvent event){ clientHandlers.forEach((x) -> x.notifyEvent(event)); } + + /** Sends a game model to all TCP clients */ public void notifyAll(Game model){ clientHandlers.forEach((x) -> x.notifyModel(model)); } From 5aeefa72bb5f589d21b6b0e1b39517c21e5fd8d3 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sun, 26 Apr 2026 16:34:31 +0200 Subject: [PATCH 29/41] Add: Order To String --- .../ingsw/gc14/Model/Orders/Order2.java | 34 +++++++++++++++++ .../ingsw/gc14/Model/Orders/Order3.java | 22 +++++++---- .../ingsw/gc14/Model/Orders/Order4.java | 36 ++++++++++++++++++ .../ingsw/gc14/Model/Orders/Order5.java | 37 +++++++++++++++++++ .../ingsw/gc14/Model/Orders/OrderPlayer.java | 21 +++++++++++ .../ingsw/gc14/Model/Orders/Order2Test.java | 19 ++++++++-- .../ingsw/gc14/Model/Orders/Order3Test.java | 32 ++++++++++++++-- .../ingsw/gc14/Model/Orders/Order4Test.java | 31 ++++++---------- .../ingsw/gc14/Model/Orders/Order5Test.java | 18 +++++++++ 9 files changed, 218 insertions(+), 32 deletions(-) create mode 100644 src/main/java/it/polimi/ingsw/gc14/Model/Orders/OrderPlayer.java diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java index 387eb1a..1a97e98 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java @@ -2,8 +2,11 @@ package it.polimi.ingsw.gc14.Model.Orders; import it.polimi.ingsw.gc14.Model.OrderLogicCard; import it.polimi.ingsw.gc14.Model.Player; +import it.polimi.ingsw.gc14.View.TUI.AsciiTable; +import it.polimi.ingsw.gc14.View.TUI.BorderStyle; import java.util.*; +import java.util.stream.IntStream; public class Order2 extends OrderLogicCard { @@ -49,4 +52,35 @@ public class Order2 extends OrderLogicCard { } } } + @Override + public String toString() + { + + var table = new AsciiTable(BorderStyle.UNICODE, 2); + List stringUp=new ArrayList<>(); + List stringDown=new ArrayList<>(); + for(int i=0;i<2;i++) + { + try { + playerList.get(i); + stringUp.add(i+". "+playerList.get(i).player.getUserName()); + if(playerList.get(i).played) + stringDown.add(" Placed"); + else + stringDown.add(" Not Placed"); + } + catch (IndexOutOfBoundsException e) { + stringUp.add(""); + stringDown.add(""); + } + } + table.addRow(stringUp); + table.addRow(stringDown); + + List stringList=new ArrayList<>(); + stringList.add("+1 Food"); + stringList.add("-1 Food / -2 Prestige"); + table.addRow(stringList); + return "TURN ORDER\n" + table.build() + "\n"; + } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java index 3eb13b9..de7797e 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java @@ -57,21 +57,29 @@ public class Order3 extends OrderLogicCard { { var table = new AsciiTable(BorderStyle.UNICODE, 3); - List tempPlayer=new ArrayList<>(players); - List stringList=new ArrayList<>(); + List stringUp=new ArrayList<>(); + List stringDown=new ArrayList<>(); for(int i=0;i<3;i++) { try { - tempPlayer.get(i); - stringList.add(i+". "+tempPlayer.get(i).getUserName()); + playerList.get(i); + stringUp.add(i+". "+playerList.get(i).player.getUserName()); + if(playerList.get(i).played) + stringDown.add(" Placed"); + else + stringDown.add(" Not Placed"); } catch (IndexOutOfBoundsException e) { - stringList.add(i+". "); + stringUp.add(""); + stringDown.add(""); } } - table.addRow(stringList); - stringList=new ArrayList<>(); + table.addRow(stringUp); + table.addRow(stringDown); + + List stringList=new ArrayList<>(); + stringList.add("+2 Food"); stringList.add(" --"); stringList.add("-1 Food / -2 Prestige"); diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java index 06bb44a..7b22706 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java @@ -2,8 +2,11 @@ package it.polimi.ingsw.gc14.Model.Orders; import it.polimi.ingsw.gc14.Model.OrderLogicCard; import it.polimi.ingsw.gc14.Model.Player; +import it.polimi.ingsw.gc14.View.TUI.AsciiTable; +import it.polimi.ingsw.gc14.View.TUI.BorderStyle; import java.util.ArrayList; +import java.util.List; import java.util.NoSuchElementException; public class Order4 extends OrderLogicCard { @@ -57,4 +60,37 @@ public class Order4 extends OrderLogicCard { } } } + @Override + public String toString() + { + + var table = new AsciiTable(BorderStyle.UNICODE, 4); + List stringUp=new ArrayList<>(); + List stringDown=new ArrayList<>(); + for(int i=0;i<4;i++) + { + try { + playerList.get(i); + stringUp.add(i+". "+playerList.get(i).player.getUserName()); + if(playerList.get(i).played) + stringDown.add(" Placed"); + else + stringDown.add(" Not Placed"); + } + catch (IndexOutOfBoundsException e) { + stringUp.add(""); + stringDown.add(""); + } + } + table.addRow(stringUp); + table.addRow(stringDown); + + List stringList=new ArrayList<>(); + stringList.add("+2 Food"); + stringList.add("+1 Food"); + stringList.add(" --"); + stringList.add("-1 Food / -2 Prestige"); + table.addRow(stringList); + return "TURN ORDER\n" + table.build() + "\n"; + } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java index 41b7228..d69e0dd 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java @@ -2,8 +2,11 @@ package it.polimi.ingsw.gc14.Model.Orders; import it.polimi.ingsw.gc14.Model.OrderLogicCard; import it.polimi.ingsw.gc14.Model.Player; +import it.polimi.ingsw.gc14.View.TUI.AsciiTable; +import it.polimi.ingsw.gc14.View.TUI.BorderStyle; import java.util.ArrayList; +import java.util.List; import java.util.NoSuchElementException; public class Order5 extends OrderLogicCard { @@ -58,4 +61,38 @@ public class Order5 extends OrderLogicCard { } } } + @Override + public String toString() + { + + var table = new AsciiTable(BorderStyle.UNICODE, 5); + List stringUp=new ArrayList<>(); + List stringDown=new ArrayList<>(); + for(int i=0;i<5;i++) + { + try { + playerList.get(i); + stringUp.add(i+". "+playerList.get(i).player.getUserName()); + if(playerList.get(i).played) + stringDown.add(" Placed"); + else + stringDown.add(" Not Placed"); + } + catch (IndexOutOfBoundsException e) { + stringUp.add(""); + stringDown.add(""); + } + } + table.addRow(stringUp); + table.addRow(stringDown); + + List stringList=new ArrayList<>(); + stringList.add("+3 Food"); + stringList.add("+1 Food"); + stringList.add(" --"); + stringList.add(" --"); + stringList.add("-1 Food / -2 Prestige"); + table.addRow(stringList); + return "TURN ORDER\n" + table.build() + "\n"; + } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/OrderPlayer.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/OrderPlayer.java new file mode 100644 index 0000000..360bebc --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/OrderPlayer.java @@ -0,0 +1,21 @@ +package it.polimi.ingsw.gc14.Model.Orders; + +import it.polimi.ingsw.gc14.Model.Player; + +/** + * Abstract base class for all order logic cards. + * An OrderLogicCard manages a queue of players and defines the effects + * applied when players are pushed back into the queue. + */ +public class OrderPlayer{ + public Player player; + public boolean played; + public OrderPlayer(Player player,boolean played){ + this.player=player; + this.played=played; + } + @Override + public String toString() { + return player.getUserName()+" "+played; + } +} diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order2Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order2Test.java index f089711..22347b3 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order2Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order2Test.java @@ -4,9 +4,10 @@ import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Player; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.NoSuchElementException; + +import java.lang.reflect.Field; +import java.util.*; + import static org.junit.jupiter.api.Assertions.*; class Order2Test { @@ -154,4 +155,16 @@ class Order2Test { assertEquals(p1, order.getFirst()); assertEquals(p1, order.getFirst()); } + @Test + void toStringTest() throws NoSuchFieldException, IllegalAccessException { + Player p1 = new Player("wPIshEUhiOpRRnIBFfM89s2$@q$9FGbz"); + Player p2 = new Player("L*Ncw1rjjrF2xn%H@4P1iC@&NNIooQQk"); + Order2 order = new Order2(new ArrayList<>(Arrays.asList(p1, p2))); + order.pull(); + order.pull(); + order.push(p2); + order.push(p1); + order.pull().getUserName(); + System.out.println(order); + } } \ No newline at end of file diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order3Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order3Test.java index d5cb5d4..34c2e3e 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order3Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order3Test.java @@ -4,9 +4,10 @@ import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Player; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.NoSuchElementException; + +import java.lang.reflect.Field; +import java.util.*; + import static org.junit.jupiter.api.Assertions.*; class Order3Test { @@ -206,5 +207,30 @@ class Order3Test { assertEquals(p1, order.getFirst()); assertEquals(p1, order.getFirst()); } + @Test + void toStringTest() throws NoSuchFieldException, IllegalAccessException { + Player p1 = new Player("wPIshEUhiOpRRnIBFfM89s2$@q$9FGbz"); + Player p2 = new Player("L*Ncw1rjjrF2xn%H@4P1iC@&NNIooQQk"); + Player p3 = new Player("L*Ncw1ryyrF2xn%H@4P1iC@&NNIooQQk"); + Order3 order = new Order3(new ArrayList<>(Arrays.asList(p1, p2,p3))); + Field field = Order3.class.getSuperclass().getDeclaredField("playerList"); + field.setAccessible(true); + List values =(ArrayList)field.get(order); + + String userPulled=order.pull().getUserName(); + userPulled=order.pull().getUserName(); + userPulled=order.pull().getUserName(); + + System.out.println(values); + order.push(p1); + order.push(p2); + values =(ArrayList)field.get(order); + System.out.println(order); +// assertEquals("TURN ORDER\n" + +// "╔════════════════════════════════════╦════════════════════════════════════╦════════════════════════════════════╗\n" + +// "║ 0. ║ 1. "+values.get(1).getUserName() +"║ 2. "+values.get(2).getUserName()+"║\n" + +// "║ +2 Food ║ -- ║ -1 Food / -2 Prestige ║\n"+ +// "╚════════════════════════════════════╩════════════════════════════════════╩════════════════════════════════════╝\n", order.toString()); + } } diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order4Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order4Test.java index 3ae1ac2..c562f60 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order4Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order4Test.java @@ -4,9 +4,10 @@ import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Player; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.NoSuchElementException; + +import java.lang.reflect.Field; +import java.util.*; + import static org.junit.jupiter.api.Assertions.*; class Order4Test { @@ -272,22 +273,14 @@ class Order4Test { } @Test - void getFirst() { - Player p1 = new Player("p1"); - Player p2 = new Player("p2"); - Player p3 = new Player("p3"); - Player p4 = new Player("p4"); - Order4 order = new Order4(new ArrayList<>(Arrays.asList(p1, p2, p3, p4))); + void toStringTest() throws NoSuchFieldException, IllegalAccessException { + Player p1 = new Player("wPIshNQhiOpRRnIBFfM89s2$@q$9FGbz"); + Player p2 = new Player("L*Ncw1rjjrF2xn%H@4P1iC@&NNIooQQk"); + Player p3 = new Player("wPIshEUhiOpRRnIBFfM89s2$@q$9FGbz"); + Player p4 = new Player("wPIshOThiOpRRnIBFfM89s2$@q$9FGbz"); + Order4 order = new Order4(new ArrayList<>(Arrays.asList(p1, p2,p3,p4))); + String userPulled=order.pull().getUserName(); + System.out.println(order); - order.pull(); - order.pull(); - order.pull(); - order.pull(); - assertNull(order.getFirst()); - - order.push(p1); - - assertEquals(p1, order.getFirst()); - assertEquals(p1, order.getFirst()); } } \ No newline at end of file diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order5Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order5Test.java index 929bc6a..0dceb69 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order5Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order5Test.java @@ -5,6 +5,7 @@ import it.polimi.ingsw.gc14.Model.Player; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.lang.reflect.Field; import java.util.*; import static org.junit.jupiter.api.Assertions.*; @@ -364,6 +365,23 @@ class Order5Test { assertEquals(p1, order.getFirst()); assertEquals(p1, order.getFirst()); } + @Test + void toStringTest() throws NoSuchFieldException, IllegalAccessException { + Player p1 = new Player("wPIshUEhiOpRRnIBFfM89s2$@q$9FGbz"); + Player p2 = new Player("L*Ncw1rjjrF2xn%H@4P1iC@&NNIooQQk"); + Player p3 = new Player("wPIshOUhiOpRRnIBFfM89s2$@q$9FGbz"); + Player p4 = new Player("wPIshNUhiOpRRnIBFfM89s2$@q$9FGbz"); + Player p5 = new Player("wPIshKUhiOpRRnIBFfM89s2$@q$9FGbz"); + Order5 order = new Order5(new ArrayList<>(Arrays.asList(p1, p2,p3,p4,p5))); + order.pull(); + order.pull(); + order.pull(); + order.pull(); + order.pull(); + order.push(p1); + System.out.println(order); + + } } From 7da3b1f0d9e3bce052b34a351e15c36903ec8df1 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sun, 26 Apr 2026 16:35:20 +0200 Subject: [PATCH 30/41] Fix: Order --- .../ingsw/gc14/Model/OrderLogicCard.java | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) 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 7a51f3e..84eb72c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java @@ -1,21 +1,22 @@ package it.polimi.ingsw.gc14.Model; import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; +import it.polimi.ingsw.gc14.Model.Orders.OrderPlayer; +import it.polimi.ingsw.gc14.View.TUI.AsciiTable; +import it.polimi.ingsw.gc14.View.TUI.BorderStyle; import java.io.Serializable; import java.util.*; +import java.util.stream.Collectors; -/** - * Abstract base class for all order logic cards. - * An OrderLogicCard manages a queue of players and defines the effects - * applied when players are pushed back into the queue. - */ public abstract class OrderLogicCard implements Serializable { /** * The queue of players associated with this order logic card. */ - private Queue players; + protected Queue players; + protected List playerList; + /** * Creates an order logic card with the specified list of players. @@ -26,6 +27,8 @@ public abstract class OrderLogicCard implements Serializable { public OrderLogicCard(ArrayList players) { Collections.shuffle(players); this.players = new LinkedList<>(players); + + this.playerList=new ArrayList<>(players.stream().map(x->new OrderPlayer(x,false)).toList()); } /** @@ -36,7 +39,15 @@ public abstract class OrderLogicCard implements Serializable { */ public void push(Player player){ effect(player,players.size()); + if(players.size()==0) + { + playerList=new ArrayList<>(); + + } + playerList.add(new OrderPlayer(player,false)); players.add(player); + + } /** @@ -45,6 +56,13 @@ public abstract class OrderLogicCard implements Serializable { * @return the first player in the queue, or {@code null} if the queue is empty. */ public Player pull(){ + for(OrderPlayer p:playerList){ + if(p.played==false) + { + p.played=true; + break; + } + } return players.poll(); } @@ -79,4 +97,17 @@ public abstract class OrderLogicCard implements Serializable { for(BuildingCard b : player.buildingCards.stream().filter(x->x.getEffectId()==3).toList()) player.addFood(1); } + + protected int getPosition(String username) + { + int pos = 0; + for (Player p : players) { + if (p.getUserName().equals(username)) + return pos; + pos++; + } + return -1; + } + + } From bce90c2640a16a0a7a517ea72f96c6487e1dc77a Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sun, 26 Apr 2026 16:40:49 +0200 Subject: [PATCH 31/41] Add: complete JavaDOC to ClientHandler --- .../Network/TCP/Server/ClientHandler.java | 78 +++++++++++++------ .../gc14/Network/TCP/Server/TCPServer.java | 36 ++++----- 2 files changed, 73 insertions(+), 41 deletions(-) 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 d6de535..d576816 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 @@ -8,66 +8,98 @@ import java.net.*; import java.util.List; import java.util.concurrent.BlockingQueue; +/** + * Handles the TCP connection with a single client. + * Each instance runs on a dedicated thread and is responsible for receiving {@link NetworkEvent} from its client and adding them + * to the {@link #actionQueue}. + * It is also responsible to send events and game model updates back to the client. + */ public class ClientHandler implements Runnable { + + /** The TCP socket */ private Socket clientSocket; + + /** Input stream used to receive requests from the client */ public ObjectInputStream in; + + /** Output stream used to send objects to the client */ public ObjectOutputStream out; + + /** + * Shared list of all client handlers. + * This handler removes itself from the list when disconnected. + */ List clientHandlers; + + /** Queue containing the events to be applied to the game model */ BlockingQueue actionQueue; + /** + * Class constructor that initializes the attributes. + * @param clientSocket The socket representing the client's TCP connection + * @param clientHandlers The shared list of all active client handlers + * @param actionQueue The queue containing incoming events + */ public ClientHandler(Socket clientSocket, List clientHandlers, BlockingQueue actionQueue) { this.clientSocket = clientSocket; this.clientHandlers = clientHandlers; this.actionQueue = actionQueue; } + + /** + * Listens for incoming {@link NetworkEvent}s from the client and adds them to the {@link #actionQueue}. + * Upon disconnection, this handler removes itself from {@link #clientHandlers}. + */ @Override - public void run(){ - try{ + public void run() { + try { in = new ObjectInputStream(clientSocket.getInputStream()); out = new ObjectOutputStream(clientSocket.getOutputStream()); - - while(true){ + while (true) { NetworkEvent event = (NetworkEvent) in.readObject(); - if(!actionQueue.add(event)){ + if (!actionQueue.add(event)) { System.out.println("Error inserting action into queue"); } } - } - catch(IOException e){ + } catch (IOException e) { clientHandlers.remove(this); e.printStackTrace(); - } - catch(ClassNotFoundException e){ + } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } - public void notifyEvent(NetworkEvent event){ - synchronized(out){ - try{ + + /** + * Sends a {@link NetworkEvent} to the client. + * @param event The network event to send to the client. + */ + public void notifyEvent(NetworkEvent event) { + synchronized (out) { + try { out = new ObjectOutputStream(clientSocket.getOutputStream()); out.writeObject(event); - } - catch(IOException e){ + } catch (IOException e) { e.printStackTrace(); } } } - public void notifyModel(Game game){ - synchronized(out){ - try{ + + /** + * Sends the current game model to this client. + * @param game The current state of the game to send to the client. + */ + public void notifyModel(Game game) { + synchronized (out) { + try { out = new ObjectOutputStream(clientSocket.getOutputStream()); out.writeObject(game); - } - catch(IOException e){ + } catch (IOException e) { e.printStackTrace(); } } } - -} - - +} \ No newline at end of file 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 3c1d442..16c4cfb 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 @@ -43,6 +43,24 @@ public class TCPServer { private List clientHandlers; + /** + * Class constructor that initializes the attributes. + * @param controller The game controller + * @param port The TCP port + * @param actionQueue The action queue + * @param playerList The player's usernames list + */ + public TCPServer(GameController controller, int port, BlockingQueue actionQueue, LimitedList playerList){ + this.port = port; + this.ConnectedPlayers = 0; + this.socketTCP = null; + this.controller = controller; + this.actionQueue = actionQueue; + this.playerList = playerList; + this.clientHandlers = new ArrayList<>(); + } + + /** * Starts the TCP server. * If the first event is not AddPlayer, the request is rejected. @@ -120,24 +138,6 @@ public class TCPServer { } - /** - * Class constructor that initializes the attributes. - * @param controller The game controller - * @param port The TCP port - * @param actionQueue The action queue - * @param playerList The player's usernames list - */ - public TCPServer(GameController controller, int port, BlockingQueue actionQueue, LimitedList playerList){ - this.port = port; - this.ConnectedPlayers = 0; - this.socketTCP = null; - this.controller = controller; - this.actionQueue = actionQueue; - this.playerList = playerList; - this.clientHandlers = new ArrayList<>(); - } - - /** Sends an action to all TCP clients */ public void notifyAll(NetworkEvent event){ clientHandlers.forEach((x) -> x.notifyEvent(event)); From 1260c58bb6fe0b4ff472236f8baf97486484dfa8 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Sun, 26 Apr 2026 17:03:44 +0200 Subject: [PATCH 32/41] Add: complete JavaDOC to TCPClient --- .../gc14/Network/TCP/Client/TCPClient.java | 88 +++++++++++++------ .../Network/TCP/Server/ClientHandler.java | 2 +- 2 files changed, 62 insertions(+), 28 deletions(-) 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 adf63f6..c69734e 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 @@ -8,32 +8,62 @@ import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; import java.io.*; import java.net.*; +/** + * Client TCP. Sends and receives messages with the TCP server. + */ public class TCPClient { + + /** Socket TCP */ Socket communicationSocket; + + /** Input stream used receive objects from the server */ ObjectInputStream socketReceive; + + /** Output stream used to send objects to the server */ ObjectOutputStream socketSend; + + /** Client game's controller */ GameController controller; + + /** IP address of the server to connect to */ String hostname; + + /** TCP port */ int port; - public TCPClient(GameController controller, String hostname, int port){ + + /** + * Class constructor that initializes the attributes. + * @param controller The game controller + * @param hostname The IP address of the server + * @param port The TCP port of the server + */ + public TCPClient(GameController controller, String hostname, int port) { this.controller = controller; this.hostname = hostname; this.port = port; } - public boolean start(String user, int proposedNPlayers){ - try{ + + /** + * Starts the TCP connection with the server. + * Sends an {@link AddPlayer} event, if the server responds with {@code -1}, the connection is refused and the method returns {@code false}. + * Otherwise, a listener thread is started. + * @param user The username of the player + * @param proposedNPlayers The desired number of players for the game + * @return true if the connection is successful, false otherwise. + */ + public boolean start(String user, int proposedNPlayers) { + try { communicationSocket = new Socket(hostname, port); socketSend = new ObjectOutputStream(communicationSocket.getOutputStream()); socketReceive = new ObjectInputStream(communicationSocket.getInputStream()); sendEvent(new AddPlayer(user, proposedNPlayers)); - if(communicationSocket.getInputStream().read() == -1){ + if (communicationSocket.getInputStream().read() == -1) { System.out.println("Could not connect to server"); return false; - } - else{ + } else { Thread listener = new Thread(() -> receiveMessage()); listener.start(); return true; @@ -42,43 +72,47 @@ public class TCPClient { e.printStackTrace(); return false; } - } - private void receiveMessage(){ - while(true){ - try{ - Object read = socketReceive.readObject(); - if (read instanceof NetworkEvent event) { //TODO non fare con instanceof - if(event.getIsError()) { + /** + * Listens continuously for incoming objects from the server. + * - If the received object is a {@link NetworkEvent} flagged as an error, it is printed. + * - If the received object is a valid {@link NetworkEvent}, it is applied to the game controller. + * - If the received object is a {@link Game} model, the controller's model is set. + */ + private void receiveMessage() { + while (true) { + try { + Object read = socketReceive.readObject(); + if (read instanceof NetworkEvent event) { //TODO: avoid instanceof + if (event.getIsError()) { System.out.println(event); } else { event.apply(controller); - //clientController.view.update(); TODO + //clientController.view.update(); TODO } - } - else if (read instanceof Game model) { + } else if (read instanceof Game model) { controller.setModel(model); } - - } - catch(IOException e){ + } catch (IOException e) { e.printStackTrace(); - } - catch(ClassNotFoundException e){ + } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } } - private void sendEvent(NetworkEvent event){ - try{ + + /** + * Sends a {@link NetworkEvent} to the server. + * @param event The NetworkEvent to send. + */ + private void sendEvent(NetworkEvent event) { + try { socketSend.writeObject(event); - } - catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); } } - -} +} \ 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 d576816..07864f0 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 @@ -19,7 +19,7 @@ public class ClientHandler implements Runnable { /** The TCP socket */ private Socket clientSocket; - /** Input stream used to receive requests from the client */ + /** Input stream used to receive objects from the client */ public ObjectInputStream in; /** Output stream used to send objects to the client */ From ef82b217188f0141cf39c96d4d06d4d018626761 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Sun, 26 Apr 2026 17:15:20 +0200 Subject: [PATCH 33/41] Fix: Fixed "toString" Methods For Most Classes + AsciiTable.java Attempted Fix. --- .../ingsw/gc14/Model/Cards/BuildingCard.java | 2 +- .../gc14/Model/Cards/TribeCards/Character.java | 2 +- .../Model/Cards/TribeCards/Characters/Builder.java | 2 +- .../Model/Cards/TribeCards/Characters/Hunter.java | 6 +++++- .../Cards/TribeCards/Characters/Inventor.java | 2 +- .../Model/Cards/TribeCards/Characters/Shaman.java | 2 +- .../it/polimi/ingsw/gc14/Model/OrderLogicCard.java | 2 +- .../it/polimi/ingsw/gc14/Model/PlayableCard.java | 2 +- .../java/it/polimi/ingsw/gc14/Model/Player.java | 14 ++++++++++++-- .../it/polimi/ingsw/gc14/View/TUI/AsciiTable.java | 2 +- 10 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java index 352f25a..2167441 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java @@ -182,6 +182,6 @@ public class BuildingCard extends PlayableCard implements Cloneable , BuildingEf */ @Override public String toString() { - return "Era:"+String.valueOf(getEra())+" Price:"+String.valueOf(getPrice())+" Prestige:"+String.valueOf(getPrestigeValue()); + return "Era:"+String.valueOf(getEra())+" P:"+String.valueOf(getPrice())+" PR:"+String.valueOf(getPrestigeValue()); } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java index d8d1284..99c8bba 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java @@ -57,7 +57,7 @@ public abstract class Character extends TribeCard implements Cloneable { */ @Override public String toString() { - return type.toString() + " -- " + super.toString(); + return super.toString(); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java index deef818..0bbacc0 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java @@ -87,7 +87,7 @@ public class Builder extends Character */ @Override public String toString() { - return super.toString() + " Reduction Value: " + String.valueOf(reductionValue) + " Prestige Value: " + String.valueOf(prestigeValue); + return super.toString() + " RV: " + String.valueOf(reductionValue) + " PV: " + String.valueOf(prestigeValue); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java index b956a18..18977a0 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java @@ -47,7 +47,11 @@ public class Hunter extends Character { */ @Override public String toString() { - return super.toString() + "Icon: " + String.valueOf(icon); + String toPrint = super.toString(); + if(this.icon){ + toPrint += " 🏹"; + } + return toPrint; } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java index d8c5f45..39eba77 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java @@ -52,7 +52,7 @@ public class Inventor extends Character { */ @Override public String toString() { - return super.toString() + " Symbol:" + String.valueOf(icon); + return super.toString() + " I_ID:" + String.valueOf(icon); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java index b04098f..f70dc94 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java @@ -49,7 +49,7 @@ public class Shaman extends Character { */ @Override public String toString() { - return super.toString() + "Icon: " + String.valueOf(icon); + return super.toString() + " ★: " + String.valueOf(icon); } /** 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 7a51f3e..22a8678 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/OrderLogicCard.java @@ -15,7 +15,7 @@ public abstract class OrderLogicCard implements Serializable { /** * The queue of players associated with this order logic card. */ - private Queue players; + protected Queue players; /** * Creates an order logic card with the specified list of players. diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java index a6c61d7..0382754 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java @@ -43,6 +43,6 @@ public abstract class PlayableCard implements Serializable { */ @Override public String toString() { - return "Era:"+String.valueOf(Era); + return "⌛:"+String.valueOf(Era); } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Player.java b/src/main/java/it/polimi/ingsw/gc14/Model/Player.java index 76db84c..fd0a3ba 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Player.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Player.java @@ -230,7 +230,7 @@ public class Player implements Serializable { // region Functions @Override public String toString() { - int Last = 5; + int Last = 6; var table = new AsciiTable(UNICODE, 1); @@ -241,6 +241,9 @@ public class Player implements Serializable { table.addRow("Prestige: " + this.getPrestigeValue()); if(!this.hunters.isEmpty()){ + Last = 6; + } + else if(!this.inventors.isEmpty()){ Last = 5; } else if(!this.shamans.isEmpty()){ @@ -252,7 +255,7 @@ public class Player implements Serializable { else if(!this.builders.isEmpty()){ Last = 2; } - else if(!this.inventors.isEmpty()){ + else if(!this.artists.isEmpty()){ Last = 1; } else{ @@ -291,6 +294,13 @@ public class Player implements Serializable { table.addRow("Shamans: " + this.shamans.toString()); } + if(!this.inventors.isEmpty()){ + if(Last == 5){ + table.addSeparator(); + } + table.addRow("Inventors: " + this.inventors.toString()); + } + if(!this.hunters.isEmpty()){ table.addSeparator(); diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java index e26018c..f3258a2 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -45,6 +45,6 @@ public class AsciiTable { private String rpad(String s, int w) { if (s.length() >= w) return s.substring(0, w); - return s + " ".repeat(w - s.length()); + return s + " ".repeat(w - s.length()) + "\t"; } } \ No newline at end of file From 23c155d0b1df84e88d85ac9a14aafadddb90ccb5 Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Sun, 26 Apr 2026 17:15:47 +0200 Subject: [PATCH 34/41] temp --- .../it/polimi/ingsw/gc14/View/TUI/TUI.java | 186 +++++++++--------- .../polimi/ingsw/gc14/Model/PlayerTest.java | 10 + 2 files changed, 103 insertions(+), 93 deletions(-) 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 1880c51..8d25fa3 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 @@ -1,93 +1,93 @@ -package it.polimi.ingsw.gc14.View.TUI; -import it.polimi.ingsw.gc14.Model.Game; - -public class TUI { - - // ── dati di stato ─────────────────────────────────────────── - private BorderStyle style = BorderStyle.UNICODE; - private Game model; - // ── punto di ingresso ─────────────────────────────────────── - public String render() { - var sb = new StringBuilder(); - sb.append(renderHeader()); - sb.append(renderTurnOrder()); - sb.append(renderOfferTrack()); - sb.append(renderCardRows()); - sb.append(renderTableaux()); - sb.append(renderFooter()); - return sb.toString(); - } - - // ── sezioni ───────────────────────────────────────────────── - private String renderTurnOrder() { - var table = new AsciiTable(style, 4, 10); // 4 colonne, largh 10 - table.addRow(model.getPlayers().stream() - .map(p -> + ". " + p.getUserName()) - .toList()); - table.addRow(state.getPlayers().stream() - .map(p -> p.getTotemPosition() != null - ? "totem: " + p.getTotemPosition() - : "(da piaz)") - .toList()); - return " TURN ORDER\n" + table.build() + "\n"; - } - - private String renderOfferTrack() { - var table = new AsciiTable(style, 5, 14); - table.addRow(state.getOfferTiles().stream() - .map(t -> t.getId() + ": " + t.getLabel()).toList()); - table.addRow(state.getOfferTiles().stream() - .map(OfferTile::getRowsLabel).toList()); - table.addRow(state.getOfferTiles().stream() - .map(t -> state.getTotemOnTile(t.getId())).toList()); - return " OFFER TRACK\n" + table.build() + "\n"; - } - - private String renderCardRows() { - int cols = state.getTopRow().size(); - var table = new AsciiTable(style, cols, 13); - table.addRow(state.getTopRow().stream() - .map(c -> "[" + c.getTypeLabel() + "]").toList()); - table.addRow(state.getTopRow().stream() - .map(Card::getName).toList()); - table.addSeparator(); - table.addRow(state.getBotRow().stream() - .map(c -> "[" + c.getTypeLabel() + "]").toList()); - table.addRow(state.getBotRow().stream() - .map(Card::getName).toList()); - return " CARTE IN GIOCO\n" + prefix("TOP ", "BOT ", table.build()) + "\n"; - } - - private String renderTableaux() { - var sb = new StringBuilder(" TABLEAU GIOCATORI\n\n"); - for (Player p : state.getPlayers()) { - String marker = p.isActive() ? ">>>" : " "; - sb.append(String.format(" %s %s%s Food:%d PP:%d%n", - marker, p.getName(), - p.isActive() ? " [TUO TURNO]" : "", - p.getFood(), p.getPP())); - sb.append(renderPlayerTableau(p)); - sb.append("\n"); - } - return sb.toString(); - } - - private String renderPlayerTableau(Player p) { - var table = new AsciiTable(style, 3, 14); - table.addHeader("PERSONAGGI", "EDIFICI", "RISORSE"); - int rows = Math.max(p.getChars().size(), - Math.max(p.getBuildings().size(), 3)); - for (int i = 0; i < rows; i++) { - String ch = i < p.getChars().size() ? p.getChars().get(i) : ""; - String bd = i < p.getBuildings().size() ? p.getBuildings().get(i) : ""; - String rs = switch (i) { - case 0 -> "Food: " + "O".repeat(p.getFood()); - case 1 -> "PP: " + p.getPP(); - case 2 -> "Chars:" + p.getChars().size() + " Edif:" + p.getBuildings().size(); - default -> ""; - }; - table.addRow(ch, bd, rs); - } - return " " + table.build().replace("\n", "\n "); - } -} +//package it.polimi.ingsw.gc14.View.TUI; +//import it.polimi.ingsw.gc14.Model.Game; +// +//public class TUI { +// +// // ── dati di stato ─────────────────────────────────────────── +// private BorderStyle style = BorderStyle.UNICODE; +// private Game model; +// // ── punto di ingresso ─────────────────────────────────────── +// public String render() { +// var sb = new StringBuilder(); +// sb.append(renderHeader()); +// sb.append(renderTurnOrder()); +// sb.append(renderOfferTrack()); +// sb.append(renderCardRows()); +// sb.append(renderTableaux()); +// sb.append(renderFooter()); +// return sb.toString(); +// } +// +// // ── sezioni ───────────────────────────────────────────────── +// private String renderTurnOrder() { +// var table = new AsciiTable(style, 4, 10); // 4 colonne, largh 10 +// table.addRow(model.getPlayers().stream() +// .map(p -> + ". " + p.getUserName()) +// .toList()); +// table.addRow(state.getPlayers().stream() +// .map(p -> p.getTotemPosition() != null +// ? "totem: " + p.getTotemPosition() +// : "(da piaz)") +// .toList()); +// return " TURN ORDER\n" + table.build() + "\n"; +// } +// +// private String renderOfferTrack() { +// var table = new AsciiTable(style, 5, 14); +// table.addRow(state.getOfferTiles().stream() +// .map(t -> t.getId() + ": " + t.getLabel()).toList()); +// table.addRow(state.getOfferTiles().stream() +// .map(OfferTile::getRowsLabel).toList()); +// table.addRow(state.getOfferTiles().stream() +// .map(t -> state.getTotemOnTile(t.getId())).toList()); +// return " OFFER TRACK\n" + table.build() + "\n"; +// } +// +// private String renderCardRows() { +// int cols = state.getTopRow().size(); +// var table = new AsciiTable(style, cols, 13); +// table.addRow(state.getTopRow().stream() +// .map(c -> "[" + c.getTypeLabel() + "]").toList()); +// table.addRow(state.getTopRow().stream() +// .map(Card::getName).toList()); +// table.addSeparator(); +// table.addRow(state.getBotRow().stream() +// .map(c -> "[" + c.getTypeLabel() + "]").toList()); +// table.addRow(state.getBotRow().stream() +// .map(Card::getName).toList()); +// return " CARTE IN GIOCO\n" + prefix("TOP ", "BOT ", table.build()) + "\n"; +// } +// +// private String renderTableaux() { +// var sb = new StringBuilder(" TABLEAU GIOCATORI\n\n"); +// for (Player p : state.getPlayers()) { +// String marker = p.isActive() ? ">>>" : " "; +// sb.append(String.format(" %s %s%s Food:%d PP:%d%n", +// marker, p.getName(), +// p.isActive() ? " [TUO TURNO]" : "", +// p.getFood(), p.getPP())); +// sb.append(renderPlayerTableau(p)); +// sb.append("\n"); +// } +// return sb.toString(); +// } +// +// private String renderPlayerTableau(Player p) { +// var table = new AsciiTable(style, 3, 14); +// table.addHeader("PERSONAGGI", "EDIFICI", "RISORSE"); +// int rows = Math.max(p.getChars().size(), +// Math.max(p.getBuildings().size(), 3)); +// for (int i = 0; i < rows; i++) { +// String ch = i < p.getChars().size() ? p.getChars().get(i) : ""; +// String bd = i < p.getBuildings().size() ? p.getBuildings().get(i) : ""; +// String rs = switch (i) { +// case 0 -> "Food: " + "O".repeat(p.getFood()); +// case 1 -> "PP: " + p.getPP(); +// case 2 -> "Chars:" + p.getChars().size() + " Edif:" + p.getBuildings().size(); +// default -> ""; +// }; +// table.addRow(ch, bd, rs); +// } +// return " " + table.build().replace("\n", "\n "); +// } +//} diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java b/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java index 9696ec7..d0544df 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java @@ -1,5 +1,6 @@ package it.polimi.ingsw.gc14.Model; +import it.polimi.ingsw.gc14.Model.Cards.Building.Effects.Building1; import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.*; @@ -206,8 +207,17 @@ class PlayerTest { p.artists.add(new Artist(1)); p.artists.add(new Artist(1)); p.artists.add(new Artist(2)); + p.builders.add(new Builder(2, 5, 1)); + p.gatherers.add(new Gatherer(1, 3)); + p.shamans.add(new Shaman(2, 3, 3)); + p.shamans.add(new Shaman(2, 3, 4)); + p.inventors.add(new Inventor(3, 1)); + p.hunters.add(new Hunter(3, true)); + p.hunters.add(new Hunter(2, false)); + p.buildingCards.add(new BuildingCard(2, 1,2, 5)); p.buildingCards.add(new BuildingCard(2, 2,3, 6)); + p.buildingCards.add(new Building1(2, 5, 5, CharacterType.INVENTOR)); System.out.println(p.toString()); } } \ No newline at end of file From 0acf76dcb95ba79e66a279201164657eb606ca60 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sun, 26 Apr 2026 17:51:52 +0200 Subject: [PATCH 35/41] Add: Slot toStringTUI --- .../java/it/polimi/ingsw/gc14/Model/Game.java | 30 +++++++++++++++++++ .../java/it/polimi/ingsw/gc14/Model/Slot.java | 20 ++++++++++++- .../it/polimi/ingsw/gc14/Model/GameTest.java | 30 +++++++++++++++++-- .../it/polimi/ingsw/gc14/Model/SlotTest.java | 22 +++++++++----- 4 files changed, 91 insertions(+), 11 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 4da7f49..cf2a8f4 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -18,6 +18,9 @@ import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; import it.polimi.ingsw.gc14.Network.Observer; +import it.polimi.ingsw.gc14.View.TUI.AsciiTable; +import it.polimi.ingsw.gc14.View.TUI.BorderStyle; + /** * Represents the main game model. * A Game object stores the players, the current state of the match, @@ -36,6 +39,15 @@ public class Game implements Serializable { o.update(this); } } + + /** + * Returns the list of players participating in the game. + * @return + */ + public List getPlayers() { + return playersList; + } + /** * The current number of players. */ @@ -691,4 +703,22 @@ public class Game implements Serializable { return true; } + @Override + public String toString() { + var table = new AsciiTable(BorderStyle.UNICODE, slotMap.size()); + List stringUp=new ArrayList<>(); + List stringDown=new ArrayList<>(); + for(Map.Entry entry:slotMap.entrySet()) + { + + stringDown.add(entry.getKey().toStringTUI()); + if(entry.getValue()!=null) + stringUp.add(entry.getValue().getUserName()); + else + stringUp.add(" "); + } + table.addRow(stringUp); + table.addRow(stringDown); + return orderLogicCard.toString()+"\nOFFER TRACK\n"+ table.build(); + } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Slot.java b/src/main/java/it/polimi/ingsw/gc14/Model/Slot.java index 5cc2f2f..456ee1a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Slot.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Slot.java @@ -152,7 +152,25 @@ public class Slot implements Serializable { */ @Override public String toString() { - return ("SlotID: "+this.getSlotId()+"\nNUpper: "+this.getNUpper()+"\nNLower: "+this.getNLower()+"\nFood: "+this.getFood()+"\nNMinPlayer: "+this.getNMinPlayer()+"\n"); + return ("SlotID: "+this.getSlotId()+"\nNUpper: "+this.getNUpper()+"\nNLower: "+this.getNLower()+"\nFood: "+this.getFood()+"\n"); + } + + + public String toStringTUI() + { + StringBuilder s = new StringBuilder(); + s.append(this.getSlotId()+" "); + for(int i=0;i!x.IsEventCard()).findFirst().get()); //assertTrue(game.DrawUpperTribeCardByIndex(temp_player,index)); List buildings=game.getUpperListBuilding(); @@ -195,4 +198,27 @@ class GameTest { @Test void noOptionalCard() { } + @Test + void toStringModel() + { + Game game=new Game(5); + Player p1=new Player("p1"); + Player p2=new Player("p2"); + Player p3=new Player("p3"); + Player p4=new Player("p4"); + Player p5=new Player("p5"); + + assertTrue(game.addPlayer(p1)); + assertTrue(game.addPlayer(p2)); + assertTrue(game.addPlayer(p3)); + assertTrue(game.addPlayer(p4)); + assertTrue(game.addPlayer(p5)); + + Queueplayers=new LinkedList<>(); + for(int i=0;i<5;i++) { + players.add( game.getCurrentState().getCurrentPlayer()); + assertTrue(game.SlotChoiceByIndex(game.getCurrentState().getCurrentPlayer(), i)); + } + System.out.println(game); + } } \ No newline at end of file diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/SlotTest.java b/src/test/java/it/polimi/ingsw/gc14/Model/SlotTest.java index 5d44ca9..ca32b35 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/SlotTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/SlotTest.java @@ -46,7 +46,8 @@ class SlotTest { assertEquals(0, s.getNLower()); assertEquals(0, s.getNUpper()); assertEquals(5, s.getNMinPlayer()); - assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\nNMinPlayer: "+s.getNMinPlayer()+"\n", s.toString()); + System.out.println(s); + assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\n", s.toString()); } @Test @@ -59,7 +60,8 @@ class SlotTest { assertEquals(1, s.getNLower()); assertEquals(0, s.getNUpper()); assertEquals(0, s.getNMinPlayer()); - assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\nNMinPlayer: "+s.getNMinPlayer()+"\n", s.toString()); + System.out.println(s); + assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\n", s.toString()); } @Test @@ -72,8 +74,8 @@ class SlotTest { assertEquals(0, s.getNLower()); assertEquals(1, s.getNUpper()); assertEquals(0, s.getNMinPlayer()); - assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\nNMinPlayer: "+s.getNMinPlayer()+"\n", s.toString()); - } + System.out.println(s); + assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\n", s.toString()); } @Test void SlotIdD() { @@ -85,7 +87,8 @@ class SlotTest { assertEquals(2, s.getNLower()); assertEquals(0, s.getNUpper()); assertEquals(3, s.getNMinPlayer()); - assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\nNMinPlayer: "+s.getNMinPlayer()+"\n", s.toString()); + System.out.println(s); + assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\n", s.toString()); } @Test @@ -98,7 +101,8 @@ class SlotTest { assertEquals(1, s.getNLower()); assertEquals(1, s.getNUpper()); assertEquals(0, s.getNMinPlayer()); - assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\nNMinPlayer: "+s.getNMinPlayer()+"\n", s.toString()); + System.out.println(s); + assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\n", s.toString()); } @Test @@ -111,7 +115,8 @@ class SlotTest { assertEquals(0, s.getNLower()); assertEquals(2, s.getNUpper()); assertEquals(0, s.getNMinPlayer()); - assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\nNMinPlayer: "+s.getNMinPlayer()+"\n", s.toString()); + System.out.println(s); + assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\n", s.toString()); } @Test @@ -124,6 +129,7 @@ class SlotTest { assertEquals(1, s.getNLower()); assertEquals(2, s.getNUpper()); assertEquals(4, s.getNMinPlayer()); - assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\nNMinPlayer: "+s.getNMinPlayer()+"\n", s.toString()); + System.out.println(s); + assertEquals("SlotID: "+slotID+"\nNUpper: "+s.getNUpper()+"\nNLower: "+s.getNLower()+"\nFood: "+s.getFood()+"\n", s.toString()); } } \ No newline at end of file From 698d1c9e48787272f0e1ba159408a6d347a5194a Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sun, 26 Apr 2026 18:53:12 +0200 Subject: [PATCH 36/41] Fixed: Order toString --- .../ingsw/gc14/Model/Orders/Order2.java | 2 +- .../ingsw/gc14/Model/Orders/Order3.java | 4 ++-- .../ingsw/gc14/Model/Orders/Order4.java | 4 ++-- .../ingsw/gc14/Model/Orders/Order5.java | 6 ++--- .../ingsw/gc14/View/TUI/AsciiTable.java | 24 +++++++++++++++++-- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java index 1a97e98..6d926c4 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java @@ -79,7 +79,7 @@ public class Order2 extends OrderLogicCard { List stringList=new ArrayList<>(); stringList.add("+1 Food"); - stringList.add("-1 Food / -2 Prestige"); + stringList.add("-1 Food / -2 PP"); table.addRow(stringList); return "TURN ORDER\n" + table.build() + "\n"; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java index de7797e..fb4c71a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java @@ -81,8 +81,8 @@ public class Order3 extends OrderLogicCard { List stringList=new ArrayList<>(); stringList.add("+2 Food"); - stringList.add(" --"); - stringList.add("-1 Food / -2 Prestige"); + stringList.add("--"); + stringList.add("-1 Food / -2 PP"); table.addRow(stringList); diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java index 7b22706..966f15a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java @@ -88,8 +88,8 @@ public class Order4 extends OrderLogicCard { List stringList=new ArrayList<>(); stringList.add("+2 Food"); stringList.add("+1 Food"); - stringList.add(" --"); - stringList.add("-1 Food / -2 Prestige"); + stringList.add("--"); + stringList.add("-1 Food / -2 PP"); table.addRow(stringList); return "TURN ORDER\n" + table.build() + "\n"; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java index d69e0dd..468c626 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java @@ -89,9 +89,9 @@ public class Order5 extends OrderLogicCard { List stringList=new ArrayList<>(); stringList.add("+3 Food"); stringList.add("+1 Food"); - stringList.add(" --"); - stringList.add(" --"); - stringList.add("-1 Food / -2 Prestige"); + stringList.add("--"); + stringList.add("--"); + stringList.add("-1 Food / -2 PP"); table.addRow(stringList); return "TURN ORDER\n" + table.build() + "\n"; } diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java index f3258a2..33e93ad 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -43,8 +43,28 @@ public class AsciiTable { return sb.append(r).toString(); } - private String rpad(String s, int w) { + private static String rpad(String s, int w) { if (s.length() >= w) return s.substring(0, w); - return s + " ".repeat(w - s.length()) + "\t"; + return s + " ".repeat(w - s.length()); } + public static String sideBySide(List left, List right, int gap) { + int leftWidth = left.stream().mapToInt(String::length).max().orElse(0); + int maxHeight = Math.max(left.size(), right.size()); + String padding = " ".repeat(gap); + + var sb = new StringBuilder(); + for (int i = 0; i < maxHeight; i++) { + String l = i < left.size() + ? left.get(i) + : " ".repeat(leftWidth); + + // padda la riga sinistra se è più corta delle altre + l = rpad(l, leftWidth); + + String r = i < right.size() ? right.get(i) : ""; + sb.append(l).append(padding).append(r).append('\n'); + } + return sb.toString(); + } + } \ No newline at end of file From dfc15fcf45ad46a8e958039a46f9a0e1bc732440 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Sun, 26 Apr 2026 18:54:06 +0200 Subject: [PATCH 37/41] Added: Game To String --- .../java/it/polimi/ingsw/gc14/Model/Game.java | 21 +++++++++++++++++-- .../it/polimi/ingsw/gc14/Model/GameTest.java | 13 +++++------- 2 files changed, 24 insertions(+), 10 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 cf2a8f4..4985a2d 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -707,10 +707,11 @@ public class Game implements Serializable { public String toString() { var table = new AsciiTable(BorderStyle.UNICODE, slotMap.size()); List stringUp=new ArrayList<>(); + List stringEmpty=new ArrayList<>(); List stringDown=new ArrayList<>(); for(Map.Entry entry:slotMap.entrySet()) { - + stringEmpty.add(" "); stringDown.add(entry.getKey().toStringTUI()); if(entry.getValue()!=null) stringUp.add(entry.getValue().getUserName()); @@ -718,7 +719,23 @@ public class Game implements Serializable { stringUp.add(" "); } table.addRow(stringUp); + table.addRow(stringEmpty); table.addRow(stringDown); - return orderLogicCard.toString()+"\nOFFER TRACK\n"+ table.build(); + StringBuilder s=new StringBuilder(); + ListtempLines=new ArrayList<>(); + List> playersString=new ArrayList<>(); + for(Player p:playersList) + { + tempLines=List.of(p.toString().split("\n")); + playersString.add(tempLines); + } + + + Listlines=List.of(orderLogicCard.toString().split("\n")); + List lines2=new ArrayList<>(); + lines2.add("OFFER TRACK"); + lines2.addAll(List.of(table.build().split("\n"))); + return AsciiTable.sideBySide(lines,lines2,1)+AsciiTable.sideBySide(playersString.get(0),playersString.get(1),1); + //return s.toString()+"\n"++"\nOFFER TRACK\n"+ table.build()+"\n" ; } } diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java b/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java index 98db8ee..5c57dcf 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java @@ -115,7 +115,7 @@ class GameTest { assertTrue(game.SlotChoiceByIndex(game.getCurrentState().getCurrentPlayer(), i)); } Player temp_player; - + System.out.println(game); temp_player=players.poll(); assertEquals(temp_player,game.getCurrentState().getCurrentPlayer()); @@ -156,6 +156,7 @@ class GameTest { index=cards.indexOf(cards.stream().filter(x->!x.IsEventCard()).findFirst().get()); assertFalse(game.DrawUpperTribeCardByIndex(temp_player,index)); + System.out.println(game); } private void drawTribeTest(HashMapnCardsByType,int nCards,int countCards,TribeCard temp_card,Player temp_player,Game game) { @@ -201,24 +202,20 @@ class GameTest { @Test void toStringModel() { - Game game=new Game(5); + Game game=new Game(3); Player p1=new Player("p1"); Player p2=new Player("p2"); Player p3=new Player("p3"); - Player p4=new Player("p4"); - Player p5=new Player("p5"); assertTrue(game.addPlayer(p1)); assertTrue(game.addPlayer(p2)); assertTrue(game.addPlayer(p3)); - assertTrue(game.addPlayer(p4)); - assertTrue(game.addPlayer(p5)); Queueplayers=new LinkedList<>(); - for(int i=0;i<5;i++) { + for(int i=0;i<3;i++) { players.add( game.getCurrentState().getCurrentPlayer()); assertTrue(game.SlotChoiceByIndex(game.getCurrentState().getCurrentPlayer(), i)); } - System.out.println(game); + //System.out.println(game); } } \ No newline at end of file From 87d7cf6a5f4bb3c4868a632afb3dc8411ff0b43e Mon Sep 17 00:00:00 2001 From: GabrieleRadice <265572328+GabrieleRadice@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:39:26 +0200 Subject: [PATCH 38/41] Fix: Fixed Various "toString" Method Issues + Relative Tests. --- .../Cards/Building/Effects/Building1.java | 2 +- .../Cards/Building/Effects/Building11.java | 2 +- .../ingsw/gc14/Model/Cards/BuildingCard.java | 2 +- .../Cards/TribeCards/Characters/Builder.java | 2 +- .../Cards/TribeCards/Characters/Hunter.java | 2 +- .../Cards/TribeCards/Characters/Shaman.java | 2 +- .../polimi/ingsw/gc14/Model/PlayableCard.java | 2 +- .../ingsw/gc14/View/TUI/AsciiTable.java | 2 +- .../polimi/ingsw/gc14/Model/PlayerTest.java | 25 +++++++++++++++++-- 9 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1.java index 6bb3579..e0b064c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building1.java @@ -46,6 +46,6 @@ public class Building1 extends BuildingCard { @Override public String toString() { - return super.toString() + " Icon: " + this.icon.toString(); + return super.toString() + " Icon: " + this.icon.toString().charAt(0); } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11.java index 59f86c0..543adcf 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/Effects/Building11.java @@ -70,6 +70,6 @@ public class Building11 extends BuildingCard { @Override public String toString() { - return super.toString() + " Icon: " + this.icon.toString(); + return super.toString() + " Icon: " + this.icon.toString().charAt(0) + " MP: " + this.PrestigeMul; } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java index 2167441..24e41a1 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java @@ -182,6 +182,6 @@ public class BuildingCard extends PlayableCard implements Cloneable , BuildingEf */ @Override public String toString() { - return "Era:"+String.valueOf(getEra())+" P:"+String.valueOf(getPrice())+" PR:"+String.valueOf(getPrestigeValue()); + return "⎕:" + " ID:" + String.valueOf(getEffectId())+ " $:"+String.valueOf(getPrice())+" PV:"+String.valueOf(getPrestigeValue()); } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java index 0bbacc0..efdc01d 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java @@ -87,7 +87,7 @@ public class Builder extends Character */ @Override public String toString() { - return super.toString() + " RV: " + String.valueOf(reductionValue) + " PV: " + String.valueOf(prestigeValue); + return super.toString() + " RV:" + String.valueOf(reductionValue) + " PV:" + String.valueOf(prestigeValue); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java index 18977a0..15aa9fe 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java @@ -49,7 +49,7 @@ public class Hunter extends Character { public String toString() { String toPrint = super.toString(); if(this.icon){ - toPrint += " 🏹"; + toPrint += " I"; } return toPrint; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java index f70dc94..158a1de 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java @@ -49,7 +49,7 @@ public class Shaman extends Character { */ @Override public String toString() { - return super.toString() + " ★: " + String.valueOf(icon); + return super.toString() + " *:" + String.valueOf(icon); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java index 0382754..09439cb 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java @@ -43,6 +43,6 @@ public abstract class PlayableCard implements Serializable { */ @Override public String toString() { - return "⌛:"+String.valueOf(Era); + return "⎕:"; } } diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java index f3258a2..e26018c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -45,6 +45,6 @@ public class AsciiTable { private String rpad(String s, int w) { if (s.length() >= w) return s.substring(0, w); - return s + " ".repeat(w - s.length()) + "\t"; + return s + " ".repeat(w - s.length()); } } \ No newline at end of file diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java b/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java index d0544df..31cd1b0 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/PlayerTest.java @@ -1,6 +1,6 @@ package it.polimi.ingsw.gc14.Model; -import it.polimi.ingsw.gc14.Model.Cards.Building.Effects.Building1; +import it.polimi.ingsw.gc14.Model.Cards.Building.Effects.*; import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.*; @@ -218,6 +218,27 @@ class PlayerTest { p.buildingCards.add(new BuildingCard(2, 1,2, 5)); p.buildingCards.add(new BuildingCard(2, 2,3, 6)); p.buildingCards.add(new Building1(2, 5, 5, CharacterType.INVENTOR)); - System.out.println(p.toString()); + p.buildingCards.add(new Building1(2, 5, 5, CharacterType.SHAMAN)); + p.buildingCards.add(new Building11(1, 5, 7, CharacterType.ARTIST , 3)); + //System.out.println(p.toString()); + assertEquals(""+ + "╔═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗\n" + + "║ test_usr ║\n" + + "├═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════┤\n" + + "║ RESOURCES: ║\n" + + "║ Food: 7 ║\n" + + "║ Prestige: 15 ║\n" + + "├═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════┤\n" + + "║ CHARACTERS: ║\n" + + "║ Artists: [⎕:, ⎕:, ⎕:, ⎕:, ⎕:, ⎕:, ⎕:] ║\n" + + "║ Builders: [⎕: RV:5 PV:1] ║\n" + + "║ Gatherers: [⎕:] ║\n" + + "║ Shamans: [⎕: *:3, ⎕: *:3] ║\n" + + "║ Inventors: [⎕: I_ID:1] ║\n" + + "║ Hunters: [⎕: I, ⎕:] ║\n" + + "├═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════┤\n" + + "║ BUILDING CARDS: ║\n" + + "║ Buildings: [⎕: ID:2 $:2 PV:5, ⎕: ID:2 $:3 PV:6, ⎕: ID:1 $:5 PV:5 Icon: I, ⎕: ID:1 $:5 PV:5 Icon: S, ⎕: ID:11 $:5 PV:7 Icon: A MP: 3]║\n" + + "╚═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝", p.toString()); } } \ No newline at end of file From 73b5b6eba555240ffdb5d20459636a9117c3c4e6 Mon Sep 17 00:00:00 2001 From: AleandroPagani Date: Wed, 29 Apr 2026 17:14:45 +0200 Subject: [PATCH 39/41] Add: ClientLauncherTUI. Connection and model sending works. Note: ClientController.view is commented out since class TUI is still missing --- .../it/polimi/ingsw/gc14/ClientLauncher.java | 28 ---------- .../polimi/ingsw/gc14/ClientLauncherTUI.java | 54 +++++++++++++++++++ .../gc14/Controller/ClientController.java | 12 +++-- .../ingsw/gc14/Model/GamePackage/Board.java | 4 +- .../RMI/Client/ClientCallbackImpl.java | 3 +- .../gc14/Network/RMI/Client/RMIClient.java | 1 - .../Network/RMI/Common/IClientCallback.java | 3 +- .../gc14/Network/RMI/Server/RMIServer.java | 5 +- .../it/polimi/ingsw/gc14/ServerLauncher.java | 19 ++++--- src/main/java/module-info.java | 9 +++- 10 files changed, 91 insertions(+), 47 deletions(-) delete mode 100644 src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java create mode 100644 src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java deleted file mode 100644 index fd8a3f8..0000000 --- a/src/main/java/it/polimi/ingsw/gc14/ClientLauncher.java +++ /dev/null @@ -1,28 +0,0 @@ -package it.polimi.ingsw.gc14; -import java.util.Scanner; - -public class ClientLauncher { - public void main() { - Scanner scanner = new Scanner(System.in); - - System.out.println("Selezionare nome utente: "); - String username = scanner.next(); - System.out.println(username); - - System.out.println("Selezionare numero di giocatori desiderato: "); - int proposedNumPlayers = scanner.nextInt(); - System.out.println(proposedNumPlayers); - - System.out.println("Selezionare RMI[0] o TCP[1]: "); - int networkType = scanner.nextInt(); - System.out.println(networkType); - - scanner.close(); // chiudi solo alla fine - - if (networkType == 0) { - return; - } else if (networkType == 1) { - return; - } - } -} \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java new file mode 100644 index 0000000..bb89ac2 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java @@ -0,0 +1,54 @@ +package it.polimi.ingsw.gc14; +import it.polimi.ingsw.gc14.Controller.ClientController; +import it.polimi.ingsw.gc14.Network.RMI.Client.RMIClient; +import it.polimi.ingsw.gc14.View.IView; + +import java.util.Scanner; + +public class ClientLauncherTUI { + public void main() throws InterruptedException { + ClientController controller = new ClientController(); + + Scanner scanner = new Scanner(System.in); + + System.out.println("Selezionare nome utente: "); + String username = scanner.next(); + System.out.println(username); + + System.out.println("Selezionare numero di giocatori desiderato: "); + int proposedNumPlayers = scanner.nextInt(); + System.out.println(proposedNumPlayers); + + System.out.println("Selezionare RMI[0] o TCP[1]: "); + int networkType = scanner.nextInt(); + System.out.println(networkType); + + scanner.close(); + + if (networkType == 0) { + RMIClient client = new RMIClient("localhost", 1099); + if (client.connect(username, proposedNumPlayers, controller)) { + System.out.println("CLIENT CONNESSO DAJE"); + } else { + System.out.println("NON CONNESSO D:"); + } + + while(true) { + System.out.flush(); + if (controller.localModel!=null) { + System.out.println("MODEL SETTATO"); + } + Thread.sleep(500); + } + + + + + + + + } else if (networkType == 1) { + return; + } + } +} \ No newline at end of file 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 d206d22..1da7933 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java +++ b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java @@ -6,9 +6,9 @@ import it.polimi.ingsw.gc14.View.IView; public class ClientController { - private Game localModel; + public Game localModel; public GameController localController; - public final IView view; + public IView view=null; public ClientController(IView view,Game localModel) { this.view = view; @@ -16,12 +16,18 @@ public class ClientController { this.localController = new GameController(localModel); } + public ClientController() { + this.localController = new GameController(localModel); + } + public void setModel(Game model) { this.localModel = model; localController.setModel(model); - localModel.addObserver((Observer) view); // registra la view come observer + // localModel.addObserver((Observer) view); // registra la view come observer } + + public void onError(String message) { view.showError(message); } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/Board.java b/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/Board.java index 55a17ee..4fda653 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/Board.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/Board.java @@ -111,9 +111,9 @@ public class Board implements Serializable { ArrayList buildingDeck = new ArrayList<>(DecksCreator.loadBuildingDeckByEra(1)); Collections.shuffle(buildingDeck); if(nTotem==2) - upperListBuilding= buildingDeck.subList(0,1); + upperListBuilding = new ArrayList<>(buildingDeck.subList(0,1)); else - upperListBuilding= buildingDeck.subList(0,2); + upperListBuilding = new ArrayList<>(buildingDeck.subList(0,2)); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java index 928fa52..5b16b76 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java @@ -5,6 +5,7 @@ import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; +import java.io.Serializable; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; @@ -13,7 +14,7 @@ import java.rmi.server.UnicastRemoteObject; * RMI client callback implementation of {@link IClientCallback}. * Receives notifications from the server and updates the client game model. */ -public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCallback { +public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCallback, Serializable { /** The client controller used to apply events and update the model */ private final ClientController clientController; 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 84d797f..19bd574 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,7 +7,6 @@ import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer; -import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer; /** * Client RMI. Uses the methods exposed by the server RMI. diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java index 0292fcc..c7fa94d 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java @@ -3,9 +3,10 @@ package it.polimi.ingsw.gc14.Network.RMI.Common; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; +import java.io.Serializable; import java.rmi.*; -public interface IClientCallback extends Remote { +public interface IClientCallback extends Remote, Serializable { void onGameInit(Game model) throws RemoteException; void onAction(NetworkEvent action) throws RemoteException; } \ No newline at end of file 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 05152c1..6fadf03 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 @@ -21,7 +21,7 @@ import java.rmi.*; /** * Server RMI. Exposes a method to join the game and one to execute an event. */ -public class RMIServer implements IGameServer { +public class RMIServer extends UnicastRemoteObject implements IGameServer { /** Server game's controller */ private GameController controller; @@ -88,12 +88,13 @@ public class RMIServer implements IGameServer { playerList.setLimit(preferredInt); } if (controller.addPlayer(username)) { - playerList.add(username); clients.put(username, callback); + playerList.add(username); return true; } return false; } + } diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index df3c776..d1650d9 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -34,7 +34,7 @@ import java.util.concurrent.LinkedBlockingQueue; public class ServerLauncher { /** - * Queue containing the events to be applied to the game model. + * Queue containinetworkTypeng the events to be applied to the game model. * Thread safe by design. */ BlockingQueue actionQueue; @@ -109,13 +109,15 @@ public class ServerLauncher { ServerLauncher launcher = new ServerLauncher(actionQueue, gameController, serverRMI, serverTCP); playerList.setAction(()->{ - try { - launcher.run(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + new Thread(()->{ + try { + launcher.run(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + }).start(); }); serverRMI.start(); @@ -132,6 +134,7 @@ public class ServerLauncher { */ public void run() throws InterruptedException, RemoteException { // Game creation + System.out.println("NOTIFICO MODEL"); serverRMI.notifyAll(gameController.getModel()); serverTCP.notifyAll(gameController.getModel()); diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 732a715..e178647 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -8,7 +8,14 @@ module it.polimi.ingsw.gc14 { opens it.polimi.ingsw.gc14 to javafx.fxml, com.google.gson; opens it.polimi.ingsw.gc14.Model to com.google.gson; + opens it.polimi.ingsw.gc14.Model.GamePackage to com.google.gson; exports it.polimi.ingsw.gc14; - opens it.polimi.ingsw.gc14.Model.GamePackage to com.google.gson; + + // RMI + exports it.polimi.ingsw.gc14.Network.RMI.Common to java.rmi; + exports it.polimi.ingsw.gc14.Network.RMI.Server to java.rmi; + exports it.polimi.ingsw.gc14.Network.RMI.Client to java.rmi; + exports it.polimi.ingsw.gc14.Network to java.rmi; + exports it.polimi.ingsw.gc14.Model to java.rmi, com.google.gson; } \ No newline at end of file From 609229058f02ce4fe414b40af1163c1d19e92e6d Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Wed, 29 Apr 2026 17:46:58 +0200 Subject: [PATCH 40/41] Fix: TUI --- .../Model/Cards/TribeCards/Character.java | 6 ++ .../Cards/TribeCards/Characters/Builder.java | 6 ++ .../Cards/TribeCards/Characters/Hunter.java | 9 +++ .../Cards/TribeCards/Characters/Inventor.java | 4 + .../Cards/TribeCards/Characters/Shaman.java | 5 ++ .../Model/Cards/TribeCards/EventCard.java | 6 +- .../TribeCards/Events/CavePaintings.java | 5 ++ .../Model/Cards/TribeCards/Events/Hunt.java | 4 + .../TribeCards/Events/ShamanicRitual.java | 5 +- .../Cards/TribeCards/Events/Sustenance.java | 5 ++ .../java/it/polimi/ingsw/gc14/Model/Game.java | 73 ++++++++++++++++--- .../polimi/ingsw/gc14/Model/PlayableCard.java | 4 + .../it/polimi/ingsw/gc14/Model/GameTest.java | 2 +- 13 files changed, 120 insertions(+), 14 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java index 99c8bba..ba405ce 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Character.java @@ -60,6 +60,12 @@ public abstract class Character extends TribeCard implements Cloneable { return super.toString(); } + @Override + public String toStringBoard() + { + return super.toStringBoard()+" "+getType().toString()+" "; + } + /** * Creates and returns a copy of this character card. * diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java index efdc01d..975fa6f 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Builder.java @@ -89,6 +89,12 @@ public class Builder extends Character public String toString() { return super.toString() + " RV:" + String.valueOf(reductionValue) + " PV:" + String.valueOf(prestigeValue); } + @Override + public String toStringBoard() + { + return super.toStringBoard()+" "+ " RV:" + String.valueOf(reductionValue) + " PV:" + String.valueOf(prestigeValue); + } + /** * Creates and returns a copy of this Builder card. diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java index 15aa9fe..0137dd2 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Hunter.java @@ -53,6 +53,15 @@ public class Hunter extends Character { } return toPrint; } + @Override + public String toStringBoard() { + String toPrint = super.toStringBoard(); + if(this.icon){ + toPrint += " I"; + } + return toPrint; + } + /** * Creates and returns a copy of this Hunter card. diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java index 39eba77..4d6b77b 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java @@ -54,6 +54,10 @@ public class Inventor extends Character { public String toString() { return super.toString() + " I_ID:" + String.valueOf(icon); } + @Override + public String toStringBoard() { + return super.toStringBoard() + " I_ID:" + String.valueOf(icon); + } /** * Creates and returns a copy of this Inventor card. diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java index 158a1de..10b3360 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java @@ -51,6 +51,11 @@ public class Shaman extends Character { public String toString() { return super.toString() + " *:" + String.valueOf(icon); } + @Override + public String toStringBoard() { + return super.toStringBoard() + " *:" + String.valueOf(icon); + } + /** * Creates and returns a copy of this Shaman card. diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventCard.java index 82d10b6..43b937a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventCard.java @@ -62,7 +62,11 @@ public abstract class EventCard extends TribeCard { */ @Override public String toString() { - return super.toString()+", "+type.toString(); + return super.toString()+" "+type.toString(); + } + @Override + public String toStringBoard() { + return super.toString()+" "+type.toString(); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/CavePaintings.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/CavePaintings.java index cbb1458..5a70bfb 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/CavePaintings.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/CavePaintings.java @@ -85,4 +85,9 @@ public class CavePaintings extends EventCard { { return new CavePaintings(getEra(), NLower, NPrestigeRem, NPrestigeMul) ; } + + @Override + public String toStringBoard() { + return super.toString()+" 0-"+(NLower-1)+":"+NPrestigeRem+" "+NLower+"+:"+NPrestigeMul; + } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Hunt.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Hunt.java index cfe472d..59898d3 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Hunt.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Hunt.java @@ -70,5 +70,9 @@ public class Hunt extends EventCard { public EventCard clone() { return new Hunt(getEra(), prestigeMultiplier); } + @Override + public String toStringBoard() { + return super.toString()+" 1F+"+prestigeMultiplier+"PP"+" X N Hunter"; + } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/ShamanicRitual.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/ShamanicRitual.java index b447c13..573f1f0 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/ShamanicRitual.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/ShamanicRitual.java @@ -96,6 +96,9 @@ public class ShamanicRitual extends EventCard { public EventCard clone() { return new ShamanicRitual(getEra(), prestigeToAdd, prestigeToRemove); } - + @Override + public String toStringBoard() { + return super.toString()+" *>:"+prestigeToAdd+" *<:"+prestigeToRemove; + } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Sustenance.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Sustenance.java index 59be90f..0d92015 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Sustenance.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Sustenance.java @@ -89,4 +89,9 @@ public class Sustenance extends EventCard { public EventCard clone() { return new Sustenance(getEra(), PrestigeDebt); } + + @Override + public String toStringBoard() { + return super.toString()+" -1F/-"+PrestigeDebt+"PP"; + } } 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 4985a2d..893ea24 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -721,21 +721,72 @@ public class Game implements Serializable { table.addRow(stringUp); table.addRow(stringEmpty); table.addRow(stringDown); - StringBuilder s=new StringBuilder(); - ListtempLines=new ArrayList<>(); - List> playersString=new ArrayList<>(); - for(Player p:playersList) - { - tempLines=List.of(p.toString().split("\n")); - playersString.add(tempLines); - } - Listlines=List.of(orderLogicCard.toString().split("\n")); List lines2=new ArrayList<>(); lines2.add("OFFER TRACK"); lines2.addAll(List.of(table.build().split("\n"))); - return AsciiTable.sideBySide(lines,lines2,1)+AsciiTable.sideBySide(playersString.get(0),playersString.get(1),1); - //return s.toString()+"\n"++"\nOFFER TRACK\n"+ table.build()+"\n" ; + + String boardToString=AsciiTable.sideBySide(lines,lines2,1); + + + + var table2 = new AsciiTable(BorderStyle.UNICODE, Math.max(getUpperListTribeCards().size(),getLowerListTribeCards().size())); + List stringUp2=new ArrayList<>(); + List stringDown2=new ArrayList<>(); + for(int i=0;i stringUp3=new ArrayList<>(); + List stringDown3=new ArrayList<>(); + for(int i=0;i Date: Wed, 29 Apr 2026 17:48:16 +0200 Subject: [PATCH 41/41] Fix: output --- .../java/it/polimi/ingsw/gc14/ClientLauncherTUI.java | 9 ++++----- src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java index bb89ac2..8da0d9e 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java @@ -28,21 +28,20 @@ public class ClientLauncherTUI { if (networkType == 0) { RMIClient client = new RMIClient("localhost", 1099); if (client.connect(username, proposedNumPlayers, controller)) { - System.out.println("CLIENT CONNESSO DAJE"); + System.out.println("Succesfully connected to RMI server\n\n"); } else { - System.out.println("NON CONNESSO D:"); + System.out.println("RMI connection refused\n\n"); } while(true) { System.out.flush(); if (controller.localModel!=null) { - System.out.println("MODEL SETTATO"); + break; } Thread.sleep(500); } - - + System.out.println("Model set\n\n"); diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index d1650d9..9c8a10e 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -134,7 +134,7 @@ public class ServerLauncher { */ public void run() throws InterruptedException, RemoteException { // Game creation - System.out.println("NOTIFICO MODEL"); + System.out.println("\n\nNotifying model"); serverRMI.notifyAll(gameController.getModel()); serverTCP.notifyAll(gameController.getModel());