From 779b72275cbb521832257d982d18812274a511b4 Mon Sep 17 00:00:00 2001 From: rubenpirreram Date: Tue, 12 May 2026 23:21:06 +0200 Subject: [PATCH] Fix: Replaced Model With MiniModel in the client implementation and in the view --- .../gc14/Controller/ClientController.java | 32 ++--- .../java/it/polimi/ingsw/gc14/Model/Game.java | 102 +-------------- .../it/polimi/ingsw/gc14/Model/MiniModel.java | 8 +- .../RMI/Client/ClientCallbackImpl.java | 5 +- .../Network/RMI/Common/IClientCallback.java | 7 +- .../gc14/Network/RMI/Server/RMIServer.java | 24 ++-- .../gc14/Network/TCP/Client/TCPClient.java | 5 +- .../Network/TCP/Server/ClientHandler.java | 5 +- .../gc14/Network/TCP/Server/TCPServer.java | 11 +- .../it/polimi/ingsw/gc14/ServerLauncher.java | 25 +++- .../it/polimi/ingsw/gc14/View/GUI/GUI.java | 7 +- .../gc14/View/GUI/MainFXMLController.java | 52 ++++---- .../polimi/ingsw/gc14/View/GUI/MainView.java | 5 +- .../java/it/polimi/ingsw/gc14/View/IView.java | 3 +- .../it/polimi/ingsw/gc14/View/TUI/TUI.java | 122 ++++++++++++++++-- .../it/polimi/ingsw/gc14/Model/GameTest.java | 28 ---- 16 files changed, 224 insertions(+), 217 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java index d9717dc..4184710 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java +++ b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java @@ -1,11 +1,14 @@ package it.polimi.ingsw.gc14.Controller; -import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.*; +import it.polimi.ingsw.gc14.Model.GamePackage.Board; +import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState; import it.polimi.ingsw.gc14.Network.IClient; import it.polimi.ingsw.gc14.Network.NetworkEvents.*; import it.polimi.ingsw.gc14.View.IView; import java.rmi.RemoteException; +import java.util.Map; import java.util.Objects; /** @@ -15,7 +18,7 @@ import java.util.Objects; public class ClientController { /** Game Controller of the client */ - public GameController localController; + public MiniModel miniModel; /** View of the client */ public IView view; @@ -31,7 +34,6 @@ public class ClientController { */ public ClientController(IView view) { this.view = view; - this.localController = new GameController(); this.client = null; } @@ -49,9 +51,9 @@ public class ClientController { * Sets the model in the GameController and updates the view. * @param model the model to set */ - public void setModel(Game model) { - localController.setModel(model); - view.setModel(localController.getModel()); + public void setModel(MiniModel model) { + this.miniModel = model; + view.setModel(miniModel); } @@ -72,7 +74,7 @@ public class ClientController { */ public void drawUpperTribeCard(String playerUsername, int pos) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) { view.showError("It's not your turn!"); } @@ -94,7 +96,7 @@ public class ClientController { * @param pos the index of the card to draw */ public void drawLowerTribeCard(String playerUsername,int pos) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else try { @@ -112,7 +114,7 @@ public class ClientController { * @param pos the index of the card to draw */ public void drawUpperBuildingCard(String playerUsername,int pos) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { try { @@ -132,7 +134,7 @@ public class ClientController { * @param pos the index of the card to draw */ public void drawLowerBuildingCard(String playerUsername,int pos) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername,miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { try { @@ -150,7 +152,7 @@ public class ClientController { * @param playerUsername the name of the player performing the action */ public void skipTurn(String playerUsername) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername,miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { try { @@ -171,7 +173,7 @@ public class ClientController { * @param pos the index of the card to draw */ public void pickOptionalTribeCard(String playerUsername,int pos) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername,miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { try { @@ -190,7 +192,7 @@ public class ClientController { * @param pos the index of the card to draw */ public void pickOptionalBuildingCard(String playerUsername,int pos) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { try { @@ -208,7 +210,7 @@ public class ClientController { * @param playerUsername the name of the player performing the action */ public void noOptionalCard(String playerUsername) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { try { @@ -226,7 +228,7 @@ public class ClientController { * @param pos the index of the selected slot */ public void slotChoice(String playerUsername,int pos) { - if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) + if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName())) view.showError("It's not your turn!"); else { try { 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 2c74d4c..d037ce2 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -128,6 +128,8 @@ public class Game implements Serializable { * The board associated with this game. */ private Board board; + //TODO + public Board getBoard() {return board;} /** * Returns clones of the upper tribe cards currently available on the board. @@ -919,105 +921,5 @@ public class Game implements Serializable { return true; } - /** - * Prints a string representation of the {@code Game}. Used in the TUI implementation to draw: - *
  • {@link it.polimi.ingsw.gc14.Model.GamePackage.Board Board} - *
  • {@link it.polimi.ingsw.gc14.Model.Player Players} - *
  • {@link #getUpperListTribeCards() Upper TribeCard List}
  • {@link #getUpperListBuilding() Upper Building List} - *
  • {@link #getLowerListTribeCards() Lower TribeCard List}
  • {@link #getLowerListBuilding() Lower Building List} - *
  • {@link it.polimi.ingsw.gc14.Model.OrderLogicCard Offer Track} - * - * @return {@code String} - a string representation of the {@code Game}. - */ - @Override - public String toString() { - return PlayersStamp()+"\n"+BoardStamp()+"\n"; - } - /** - * Returns a string representation of all the players currently in the game, - * arranged side by side in pairs. - * If the number of players is odd, the last player is printed on its own line. - * - * @return {@code String} - a string representation of all the players. - */ - public String PlayersStamp() - { - StringBuilder stringBuilder=new StringBuilder(); - for(int i=0;i stringUpOffer=new ArrayList<>(); - List stringDownOffer=new ArrayList<>(); - - int index=0; - for(Map.Entry entry:slotMap.entrySet()) - { - stringDownOffer.add((index++)+"."+entry.getKey().toStringTUI()); - if(entry.getValue()!=null) - stringUpOffer.add(entry.getValue().getUserName()); - else - stringUpOffer.add(" "); - } - - var TribeTableUpper = new AsciiTable(BorderStyle.UNICODE,1); - var TribeTableLower = new AsciiTable(BorderStyle.UNICODE,1); - - List stringUpperListTribe=new ArrayList<>(); - List stringLowerListTribe=new ArrayList<>(); - stringUpperListTribe.add("Char/Events"); - stringLowerListTribe.add("Char/Events"); - for(int i=0;iTribeTableUpper.addRow(x)); - stringLowerListTribe.forEach(x->TribeTableLower.addRow(x)); - offerTrack.addRow(stringUpOffer); - offerTrack.addRow(stringDownOffer); - return "CURRENT STATE\n"+getCurrentState()+"\n"+orderLogicCard.toString()+"\n"+ AsciiTable.sideBySide(Arrays.stream((TribeTableUpper.build().split("\n"))).toList(), Arrays.stream(BuildTableUpper.build().split("\n")).toList(),2)+"\n"+offerTrack.build()+"\n"+AsciiTable.sideBySide(List.of(TribeTableLower.build().split("\n")), Arrays.stream(BuildTableLower.build().split("\n")).toList(),2); - } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java b/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java index 9347ace..ff67a32 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java @@ -6,21 +6,23 @@ import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character; import it.polimi.ingsw.gc14.Model.GamePackage.Board; import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState; +import java.io.Serializable; import java.rmi.RemoteException; import java.util.*; //TODO -public class MiniModel { +public class MiniModel implements Serializable { public Board board; public Map slotPlayerMap; public OrderLogicCard orderLogicCard; public CurrentState currentState; public Map players; - public MiniModel(Board board, Map slotPlayerMap, OrderLogicCard orderLogicCard, CurrentState currentState, Map players) { + public MiniModel(Board board, Map slotPlayerMap, OrderLogicCard orderLogicCard, CurrentState currentState, List players) { this.board = board; this.slotPlayerMap = slotPlayerMap; this.orderLogicCard = orderLogicCard; this.currentState = currentState; - this.players = players; + this.players=new HashMap<>(); + setPlayers(players); } public void setBoard(Board board) { this.board = board; 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 817e3d3..c9c3224 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 @@ -2,6 +2,7 @@ package it.polimi.ingsw.gc14.Network.RMI.Client; import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; @@ -37,7 +38,7 @@ public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCa * @throws RemoteException if any RMI error occurs */ @Override - public void onGameInit(Game model) throws RemoteException { + public void onGameInit(MiniModel model) throws RemoteException { clientController.setModel(model); clientController.view.render(); } @@ -55,7 +56,7 @@ public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCa if(event.getIsError()) { clientController.view.showError(event.toString()); } else { - event.apply(clientController.localController); + event.apply(clientController.miniModel); clientController.view.render(); } } 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 c44c309..c68c5b9 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 @@ -1,10 +1,13 @@ package it.polimi.ingsw.gc14.Network.RMI.Common; -import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.*; +import it.polimi.ingsw.gc14.Model.GamePackage.Board; +import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState; import it.polimi.ingsw.gc14.Network.NetworkEvent; import java.io.Serializable; import java.rmi.*; +import java.util.Map; /** * Callback interface used by the server to notify an RMI client about @@ -21,7 +24,7 @@ public interface IClientCallback extends Remote, Serializable { * @param model the current game model. * @throws RemoteException if an RMI communication error occurs. */ - void onGameInit(Game model) throws RemoteException; + void onGameInit(MiniModel miniModel) throws RemoteException; /** * Notifies the client about a network action to process. 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 e9862ad..099d391 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 @@ -3,6 +3,8 @@ package it.polimi.ingsw.gc14.Network.RMI.Server; import it.polimi.ingsw.gc14.Controller.GameController; import it.polimi.ingsw.gc14.LimitedMap; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState; +import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvents.*; import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; @@ -25,7 +27,6 @@ import java.rmi.*; public class RMIServer extends UnicastRemoteObject implements IGameServer { private String host; private GameController controller; - private Game model; private Registry registry; private int nPort; @@ -89,7 +90,8 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { clients.put(username, callback); System.out.println("Reconnected player: " + username); startWatchdog(username); - callback.onGameInit(controller.getModel()); + Game game = controller.getModel(); + callback.onGameInit(new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers())); System.out.println("Model sent: " + username); actionQueue.add(new ReconnectPlayer(username)); return true; @@ -98,8 +100,7 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { else { if (playerList.isEmpty()) { - model = new Game(preferredInt); - controller.setModel(model); + controller.setModel(new Game(preferredInt)); playerList.setLimit(preferredInt); } if (controller.addPlayer(username)) { @@ -115,7 +116,8 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { clients.put(username, callback); System.out.println("Reconnected player: " + username); startWatchdog(username); - callback.onGameInit(controller.getModel()); + Game game = controller.getModel(); + callback.onGameInit(new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers())); System.out.println("Model sent: " + username); actionQueue.add(new ReconnectPlayer(username)); return true; @@ -165,10 +167,11 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { * Mirrors {@code TCPServer.notifyAll(Game)} + the {@code ClientHandler.notifyModel} * call that stores the model for disconnect-turn checking. */ - public void notifyAll(Game model) throws RemoteException { - this.model = model; + public void notifyAll(MiniModel model) throws RemoteException { // Keep every watchdog's game reference up to date - watchdogs.values().forEach(wd -> wd.setGame(model)); + synchronized (controller){ + watchdogs.values().forEach(wd -> wd.setGame(controller.getModel())); + } for (IClientCallback cb : clients.values()) { cb.onGameInit(model); } @@ -326,7 +329,10 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { private void startWatchdog(String username) { RMIHeartbeat wd = new RMIHeartbeat( username, playerList, clients, actionQueue); - if (model != null) wd.setGame(model); + synchronized (controller) + { + if (controller.getModel() != null) wd.setGame(controller.getModel()); + } watchdogs.put(username, wd); wd.start(); } 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 498ced8..17f922b 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 @@ -2,6 +2,7 @@ package it.polimi.ingsw.gc14.Network.TCP.Client; import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.Network.IClient; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvents.*; @@ -165,11 +166,11 @@ public class TCPClient implements IClient { if (event.getIsError()) { controller.view.showError(event.toString()); } else { - event.apply(controller.localController); + event.apply(controller.miniModel); controller.view.render(); } - } else if (read instanceof Game model) { + } else if (read instanceof MiniModel model) { controller.setModel(model); controller.view.render(); } 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 d321664..63664c7 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 @@ -2,6 +2,7 @@ package it.polimi.ingsw.gc14.Network.TCP.Server; import it.polimi.ingsw.gc14.LimitedMap; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvents.DisconnectedPlayer; @@ -24,7 +25,6 @@ public class ClientHandler implements Runnable { private boolean running ; - private Game game; /** * Returns the username associated with this client. * @@ -120,8 +120,7 @@ public class ClientHandler implements Runnable { * Sends the current game model to this client. * @param game The current state of the game to send to the client. */ - public synchronized void notifyModel(Game game) { - this.game = game; + public synchronized void notifyMiniModel(MiniModel game) { try { out.writeObject(game); } 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 e2d5215..9de535c 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.LimitedMap; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.Model.Player; import it.polimi.ingsw.gc14.Network.ClientPlayer; import it.polimi.ingsw.gc14.Network.EventType; @@ -124,7 +125,8 @@ public class TCPServer { ); clientSocket.getOutputStream().write(1); pendingHeartbeat.put(username, handler); - handler.notifyModel(controller.getModel()); + Game game = controller.getModel(); + handler.notifyMiniModel(new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers())); Thread thread = new Thread(handler); thread.start(); clientHandlers.add(handler); @@ -172,7 +174,8 @@ public class TCPServer { ); clientSocket.getOutputStream().write(1); pendingHeartbeat.put(username, handler); - handler.notifyModel(controller.getModel()); + Game game = controller.getModel(); + handler.notifyMiniModel(new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers())); Thread thread = new Thread(handler); thread.start(); clientHandlers.add(handler); @@ -232,7 +235,7 @@ public class TCPServer { }); } - public void notifyAll(Game model) { - clientHandlers.forEach(h -> h.notifyModel(model)); + public void notifyAll(MiniModel model) { + clientHandlers.forEach(h -> h.notifyMiniModel(model)); } } \ 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 6f30116..7d29e2c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -4,9 +4,11 @@ package it.polimi.ingsw.gc14; import it.polimi.ingsw.gc14.Controller.GameController; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; +import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.Model.Player; import it.polimi.ingsw.gc14.Network.EventType; import it.polimi.ingsw.gc14.Network.NetworkEvent; +import it.polimi.ingsw.gc14.Network.NetworkEvents.ApplyNextRound; import it.polimi.ingsw.gc14.Network.NetworkEvents.DisconnectedPlayer; import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer; import it.polimi.ingsw.gc14.Network.TCP.Server.TCPServer; @@ -110,10 +112,22 @@ public class ServerLauncher { disconnectionTimer.cancel(false); disconnectionTimer = null; } + int roundPrec=gameController.getModel().getCurrentState().getRound(); synchronized(gameController){ event.setIsError(!event.apply(gameController)); + if(!event.getIsError()) + { + event.setData(gameController.getModel().getSlotMap(),gameController.getModel().orderLogicCard,gameController.getModel().getCurrentState(),gameController.getModel().getPlayerByUsername(event.getUsername())); + } serverRMI.notifyAll(event); serverTCP.notifyAll(event); + if(gameController.getModel().getCurrentState().getRound()!=roundPrec) + { + Game game=gameController.getModel(); + ApplyNextRound nextRound=new ApplyNextRound(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayers()); + serverRMI.notifyAll(nextRound); + serverTCP.notifyAll(nextRound); + } if(!event.getIsError()){ if(this.gameController.getModel().getCurrentState().getGameStage() == GameStages.ENDED){ this.deleteSave(); @@ -196,9 +210,14 @@ public class ServerLauncher { new Thread(()->{ try { System.out.println("\n\nNotifying model"); - serverRMI.notifyAll(gameController.getModel()); - serverTCP.notifyAll(gameController.getModel()); - view = new TUI(gameController.getModel()); + MiniModel miniModel; + synchronized (gameController) { + Game game = gameController.getModel(); + miniModel= new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers()); + } + serverRMI.notifyAll(miniModel); + serverTCP.notifyAll(miniModel); + view = new TUI(miniModel); view.fullRender(); } catch (RemoteException e) { throw new RuntimeException(e); diff --git a/src/main/java/it/polimi/ingsw/gc14/View/GUI/GUI.java b/src/main/java/it/polimi/ingsw/gc14/View/GUI/GUI.java index 9eaa70e..de4647c 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/GUI/GUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/GUI/GUI.java @@ -2,6 +2,7 @@ package it.polimi.ingsw.gc14.View.GUI; import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.View.GUI.MainView; import it.polimi.ingsw.gc14.View.IView; import javafx.application.Platform; @@ -11,7 +12,7 @@ public class GUI implements IView { // stessa interfaccia che implementa TUI private final Stage stage; private final MainView mainView; - private Game model; + private MiniModel model; private ClientController controller; private String username; @@ -21,9 +22,9 @@ public class GUI implements IView { // stessa interfaccia che implementa TUI } @Override - public void setModel(Game model) { + public void setModel(MiniModel model) { this.model = model; - mainView.setModel(model, controller, username); + mainView.setModel(model,controller, username); Platform.runLater(() -> { stage.setScene(mainView.getScene()); diff --git a/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainFXMLController.java b/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainFXMLController.java index fc9b1bf..73da0d8 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainFXMLController.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainFXMLController.java @@ -47,12 +47,12 @@ public class MainFXMLController { private Popup popup; private HBox popupCards; - private Game model; + private MiniModel model; private ClientController controller; private String username; private final Map cardCache = new HashMap<>(); - public void setModel(Game model) {this.model = model;} + public void setModel(MiniModel model) {this.model = model;} public void setController(ClientController controller) {this.controller = controller;} public void setUsername(String username) {this.username = username;} @@ -116,9 +116,9 @@ public class MainFXMLController { img.setClip(clip); StackPane wrapper = new StackPane(img); - Player player = model.getSlotMap().get(slot); + Player player = model.slotPlayerMap.get(slot); if (player != null) { - int index = model.getPlayers().indexOf(player); + int index = new ArrayList<>(model.players.values()).indexOf(player); ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + index + ".png"))); totem.setFitHeight(70); totem.setPreserveRatio(true); @@ -221,7 +221,7 @@ public class MainFXMLController { upperList.getChildren().clear(); int i = 0; - for (TribeCard card : model.getUpperListTribeCards()) { + for (TribeCard card : model.board.upperListTribe) { final int index = i; StackPane img = createCard(card, true, true); img.setOnMouseClicked(e -> controller.drawUpperTribeCard(username, index)); @@ -229,7 +229,7 @@ public class MainFXMLController { i++; } i = 0; - for (BuildingCard card : model.getUpperListBuilding()) { + for (BuildingCard card : model.board.upperListBuilding) { final int index = i; StackPane img = createCard(card, true, true); img.setOnMouseClicked(e -> controller.drawUpperBuildingCard(username, index)); @@ -238,7 +238,7 @@ public class MainFXMLController { } } private void renderOrder() { - StackPane card = createOrder(Integer.toString(model.getNPlayers()), false, false); + StackPane card = createOrder(Integer.toString(model.players.size()), false, false); VBox overlay = new VBox(-20); overlay.setPickOnBounds(false); @@ -246,13 +246,13 @@ public class MainFXMLController { StackPane.setMargin(overlay, new Insets(9, 0, 0, 57)); int i = 0; - for (Player player : model.getPlayers()) { + for (Player player : model.players.values()) { final int index = i; ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + index + ".png"))); totem.setFitHeight(70); totem.setPreserveRatio(true); - if (!(model.orderLogicCard.getPosition(player.getUserName()) != -1 && !model.getSlotMap().containsValue(player))) { + if (!(model.orderLogicCard.getPosition(player.getUserName()) != -1 && !model.slotPlayerMap.containsValue(player))) { totem.setOpacity(0.0); } overlay.getChildren().add(totem); @@ -267,7 +267,7 @@ public class MainFXMLController { board.getChildren().clear(); String path = ""; - switch (model.getCurrentState().getEra()) { + switch (model.currentState.getEra()) { case 1 -> path = "/GUIImages/Backs/back-001.png"; case 2 -> path = "/GUIImages/Backs/back-030.png"; case 3 -> path = "/GUIImages/Backs/back-058.png"; @@ -289,7 +289,7 @@ public class MainFXMLController { renderOrder(); int i = 0; - for (Map.Entry entry : model.getSlotMap().entrySet()) { + for (Map.Entry entry : model.slotPlayerMap.entrySet()) { Slot slot = entry.getKey(); final int index = i; StackPane img = createSlot(slot, true, true); @@ -304,7 +304,7 @@ public class MainFXMLController { lowerList.getChildren().clear(); int i = 0; - for (TribeCard card : model.getLowerListTribeCards()) { + for (TribeCard card : model.board.lowerListTribe) { final int index = i; StackPane img = createCard(card, true, true); img.setOnMouseClicked(e -> controller.drawLowerTribeCard(username, index)); @@ -312,7 +312,7 @@ public class MainFXMLController { i++; } i = 0; - for (BuildingCard card : model.getLowerListBuilding()) { + for (BuildingCard card : model.board.lowerListBuilding) { final int index = i; StackPane img = createCard(card, true, true); img.setOnMouseClicked(e -> controller.drawLowerBuildingCard(username, index)); @@ -327,13 +327,13 @@ public class MainFXMLController { myHand.setSpacing(14); myHand.setAlignment(Pos.CENTER); - drawMyHandList(myHand, model.getPlayerByUsername(username).artists); - drawMyHandList(myHand, model.getPlayerByUsername(username).gatherers); - drawMyHandList(myHand, model.getPlayerByUsername(username).inventors); - drawMyHandList(myHand, model.getPlayerByUsername(username).builders); - drawMyHandList(myHand, model.getPlayerByUsername(username).shamans); - drawMyHandList(myHand, model.getPlayerByUsername(username).hunters); - drawMyHandList(myHand, model.getPlayerByUsername(username).buildingCards); + drawMyHandList(myHand, model.players.get(username).artists); + drawMyHandList(myHand, model.players.get(username).gatherers); + drawMyHandList(myHand, model.players.get(username).inventors); + drawMyHandList(myHand, model.players.get(username).builders); + drawMyHandList(myHand, model.players.get(username).shamans); + drawMyHandList(myHand, model.players.get(username).hunters); + drawMyHandList(myHand, model.players.get(username).buildingCards); } private void drawMyHandList(HBox myHand, ArrayList cardList) { if (!cardList.isEmpty()) { @@ -361,16 +361,16 @@ public class MainFXMLController { sidePanel.getChildren().clear(); sidePanel.setSpacing(6); - era.setText(Integer.toString(model.getCurrentState().getEra())); - round.setText(Integer.toString(model.getCurrentState().getRound())); - player.setText(model.getCurrentState().getCurrentPlayer().getUserName()); + era.setText(Integer.toString(model.currentState.getEra())); + round.setText(Integer.toString(model.currentState.getRound())); + player.setText(model.currentState.getCurrentPlayer().getUserName()); VBox.setMargin(info, new Insets(5, 5, 5, 5)); sidePanel.getChildren().add(info); renderPlayers(sidePanel); } private void renderPlayers(VBox playersHand) { - for (Player player : model.getPlayers()) { + for (Player player : model.players.values()) { // Card container VBox card = new VBox(3); VBox.setMargin(card, new Insets(5)); @@ -382,7 +382,7 @@ public class MainFXMLController { // Riga 1: icona totem + nome HBox headerRow = new HBox(8); headerRow.setAlignment(Pos.CENTER); - int index = model.getPlayers().indexOf(player); + int index = new ArrayList<>(model.players.values()).indexOf(player); ImageView totem = new ImageView(new Image(getClass().getResourceAsStream("/GUIImages/Totems/totem_" + index + ".png"))); totem.setFitHeight(20); totem.setPreserveRatio(true); @@ -465,7 +465,7 @@ public class MainFXMLController { } } private ArrayList getPlayerCards(String username, String type) { - Player p = model.getPlayerByUsername(username); + Player p = model.players.get(username); return switch (type) { case "artists" -> new ArrayList<>(p.artists); case "gatherers" -> new ArrayList<>(p.gatherers); diff --git a/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainView.java b/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainView.java index 50f8d08..bc5bb86 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainView.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainView.java @@ -2,6 +2,7 @@ package it.polimi.ingsw.gc14.View.GUI; import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.MiniModel; import javafx.fxml.FXMLLoader; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -15,7 +16,7 @@ public class MainView { private final Scene scene; private final MainFXMLController fxmlController; - private Game model; + private MiniModel model; private ClientController controller; private String username; @@ -32,7 +33,7 @@ public class MainView { } public Scene getScene() { return scene; } - public void setModel(Game model, ClientController controller, String username) { + public void setModel(MiniModel model, ClientController controller, String username) { this.model = model; fxmlController.setModel(model); this.controller = controller; diff --git a/src/main/java/it/polimi/ingsw/gc14/View/IView.java b/src/main/java/it/polimi/ingsw/gc14/View/IView.java index 5025588..dc0aaa4 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/IView.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/IView.java @@ -1,10 +1,11 @@ package it.polimi.ingsw.gc14.View; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.Network.NetworkEvent; public interface IView { - public void setModel(Game game); + public void setModel(MiniModel miniModel); public void render(); public void showMessage(String message); public void showError(String message); 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 20bc0cc..d78577b 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,8 +1,14 @@ package it.polimi.ingsw.gc14.View.TUI; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.MiniModel; +import it.polimi.ingsw.gc14.Model.Player; +import it.polimi.ingsw.gc14.Model.Slot; import it.polimi.ingsw.gc14.View.IView; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; /** * Text-based User Interface (TUI) implementation of {@link IView}. @@ -30,9 +36,9 @@ import java.util.List; public class TUI implements IView { /** - * The {@link Game} model whose state is rendered. + * The {@link MiniModel} model whose state is rendered. */ - private Game model; + private MiniModel model; /** * The username of the local player, used to retrieve and display @@ -50,7 +56,7 @@ public class TUI implements IView { * * @param model the {@link Game} model to display; must not be {@code null} */ - public TUI(Game model) { + public TUI(MiniModel model) { this.model = model; this.username = ""; } @@ -76,7 +82,7 @@ public class TUI implements IView { * @param model the new {@link Game} model; must not be {@code null} */ @Override - public void setModel(Game model) { + public void setModel(MiniModel model) { this.model = model; } @@ -96,9 +102,9 @@ public class TUI implements IView { *

    Layout: *

      *
    • Top — player status table produced by - * {@link Game#PlayersStamp()}.
    • + * {@link #PlayersStamp()}. *
    • Bottom-left — board status produced by - * {@link Game#BoardStamp()}.
    • + * {@link #BoardStamp()}. *
    • Bottom-right — menu options legend and the local * player's hand.
    • *
    @@ -107,10 +113,10 @@ public class TUI implements IView { */ public void fullRender() { clearTerminal(); - List lines = List.of(model.BoardStamp().split("\n")); + List lines = List.of(BoardStamp().split("\n")); List lines2 = List.of((printMenuOptions() + "\n" + - model.getPlayerByUsername(username)).split("\n")); - System.out.println(model.PlayersStamp() + "\n" + + model.players.get(username)).split("\n")); + System.out.println(PlayersStamp() + "\n" + AsciiTable.sideBySide(lines, lines2, 3)); } @@ -120,7 +126,7 @@ public class TUI implements IView { *

    Layout: *

      *
    • Left panel — turn order, upper card row, offer track, - * and lower card row, as produced by {@link Game#BoardStamp()}.
    • + * and lower card row, as produced by {@link #BoardStamp()}. *
    • Right panel — menu options legend followed by the local * player's hand.
    • *
    @@ -129,9 +135,9 @@ public class TUI implements IView { */ public void renderBoard() { clearTerminal(); - List lines = List.of(model.BoardStamp().split("\n")); + List lines = List.of(BoardStamp().split("\n")); List lines2 = List.of((printMenuOptions() + "\nYOUR HAND\n" + - model.getPlayerByUsername(username)).split("\n")); + model.players.get(username)).split("\n")); System.out.println(AsciiTable.sideBySide(lines, lines2, 3)); } @@ -141,7 +147,7 @@ public class TUI implements IView { *

    Layout: *

      *
    • Left panel — prestige, food, character deck, and building - * deck for all players, as produced by {@link Game#PlayersStamp()}.
    • + * deck for all players, as produced by {@link #PlayersStamp()}. *
    • Right panel — menu options legend.
    • *
    * @@ -149,7 +155,7 @@ public class TUI implements IView { */ public void renderPlayer() { clearTerminal(); - List lines = List.of(model.PlayersStamp().split("\n")); + List lines = List.of(PlayersStamp().split("\n")); List lines2 = List.of(printMenuOptions().split("\n")); System.out.println(AsciiTable.sideBySide(lines, lines2, 3)); } @@ -212,4 +218,92 @@ public class TUI implements IView { pb.inheritIO().start().waitFor(); } catch (Exception ignored) {} } + + /** + * Returns a string representation of all the players currently in the game, + * arranged side by side in pairs. + * If the number of players is odd, the last player is printed on its own line. + * + * @return {@code String} - a string representation of all the players. + */ + public String PlayersStamp() + { + StringBuilder stringBuilder=new StringBuilder(); + ArrayList playersList=new ArrayList<>(model.players.values()); + for(int i = 0; i< model.players.size()/2; i++) + { + stringBuilder.append(AsciiTable.sideBySide(List.of(playersList.get((i*2)).toString().split("\n")),List.of(playersList.get((i*2+1)).toString().split("\n")),2)); + } + stringBuilder.append("\n"); + if(playersList.size()%2!=0) + { + stringBuilder.append(playersList.get(playersList.size()-1).toString()); + stringBuilder.append("\n"); + } + return stringBuilder.toString(); + } + + /** + * Returns a string representation of the board, including the current state, + * the offer track with slot assignments, the upper and lower tribe card lists, + * and the upper and lower building card lists. + * + * @return {@code String} - a string representation of the board. + */ + public String BoardStamp() + { + var offerTrack = new AsciiTable(BorderStyle.UNICODE, model.slotPlayerMap.size()); + List stringUpOffer=new ArrayList<>(); + List stringDownOffer=new ArrayList<>(); + + int index=0; + for(Map.Entry entry:model.slotPlayerMap.entrySet()) + { + stringDownOffer.add((index++)+"."+entry.getKey().toStringTUI()); + if(entry.getValue()!=null) + stringUpOffer.add(entry.getValue().getUserName()); + else + stringUpOffer.add(" "); + } + + var TribeTableUpper = new AsciiTable(BorderStyle.UNICODE,1); + var TribeTableLower = new AsciiTable(BorderStyle.UNICODE,1); + + List stringUpperListTribe=new ArrayList<>(); + List stringLowerListTribe=new ArrayList<>(); + stringUpperListTribe.add("Char/Events"); + stringLowerListTribe.add("Char/Events"); + for(int i=0;iTribeTableUpper.addRow(x)); + stringLowerListTribe.forEach(x->TribeTableLower.addRow(x)); + offerTrack.addRow(stringUpOffer); + offerTrack.addRow(stringDownOffer); + return "CURRENT STATE\n"+model.currentState+"\n"+model.orderLogicCard.toString()+"\n"+ AsciiTable.sideBySide(Arrays.stream((TribeTableUpper.build().split("\n"))).toList(), Arrays.stream(BuildTableUpper.build().split("\n")).toList(),2)+"\n"+offerTrack.build()+"\n"+AsciiTable.sideBySide(List.of(TribeTableLower.build().split("\n")), Arrays.stream(BuildTableLower.build().split("\n")).toList(),2); + } } \ No newline at end of file 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 ed83c8d..8aaa3a8 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java @@ -1480,35 +1480,7 @@ class GameTest { ); } - @Test - void playersStampShouldReturnPlayersInformation() { - Game game = new Game(3); - addPlayers(game, 3, "stamp_"); - - String result = game.PlayersStamp(); - - assertNotNull(result); - assertFalse(result.isBlank()); - assertTrue(result.contains("stamp_1")); - assertTrue(result.contains("stamp_2")); - assertTrue(result.contains("stamp_3")); - } - - @Test - void boardStampShouldReturnBoardInformation() { - Game game = new Game(3); - - addPlayers(game, 3, "board_stamp_"); - - String result = game.BoardStamp(); - - assertNotNull(result); - assertFalse(result.isBlank()); - assertTrue(result.contains("CURRENT STATE")); - assertTrue(result.contains("Char/Events")); - assertTrue(result.contains("Building")); - } @Test @Timeout(value = 20, unit = TimeUnit.SECONDS)