diff --git a/README.md b/README.md index 82776814..685d2168 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,10 @@ The group members are: | Complete Rules + TUI + GUI + RMI or Socket + 1 FA (Chat) | 24 | ☑️ | | Complete Rules + TUI + GUI + RMI + Socket + 1 FA (Chat) | 27 | ☑️ | | Complete Rules + TUI + GUI + RMI + Socket + 2 FA (Chat & Multiple match) | 30 | ☑️ | -| Complete Rules + TUI + GUI + RMI + Socket + 3 FA (Chat & Multiple match & Disconnection resilience) | 30L | ⚠️ | +| Complete Rules + TUI + GUI + RMI + Socket + 3 FA (Chat & Multiple match & Disconnection resilience) | 30L | ☑️ | ### Currently Known Issues -- 🟨 The branch with the correct version of the network stack is not yet merged. Therefore, the network is not informing the View if the initial connection was successful or not. -- 🟥 The branch with the correct version of the network stack is not yet merged. Therefore, the network is not activating the PingTask that allows (in both Client & Server) the disconnection discovery in RMI. - ## Code Coverage The average code coverage, between Model and Controller, is 96% for methods and 85% for lines, all (known) edge cases are covered. diff --git a/deliverables/FinalUML/ChatFinalUML.png b/deliverables/FinalUML/ChatFinalUML.png new file mode 100644 index 00000000..add61e9f Binary files /dev/null and b/deliverables/FinalUML/ChatFinalUML.png differ diff --git a/deliverables/FinalUML/ClientFinalUML.png b/deliverables/FinalUML/ClientFinalUML.png new file mode 100644 index 00000000..833ec873 Binary files /dev/null and b/deliverables/FinalUML/ClientFinalUML.png differ diff --git a/deliverables/FinalUML/ControllerFinalUML.png b/deliverables/FinalUML/ControllerFinalUML.png new file mode 100644 index 00000000..300f006b Binary files /dev/null and b/deliverables/FinalUML/ControllerFinalUML.png differ diff --git a/deliverables/FinalUML/MessageFinalUML.png b/deliverables/FinalUML/MessageFinalUML.png new file mode 100644 index 00000000..e302eaef Binary files /dev/null and b/deliverables/FinalUML/MessageFinalUML.png differ diff --git a/deliverables/FinalUML/ModelFinalUML.png b/deliverables/FinalUML/ModelFinalUML.png new file mode 100644 index 00000000..6fc5a877 Binary files /dev/null and b/deliverables/FinalUML/ModelFinalUML.png differ diff --git a/deliverables/FinalUML/ProjectFinalUML.png b/deliverables/FinalUML/ProjectFinalUML.png new file mode 100644 index 00000000..9119fd4d Binary files /dev/null and b/deliverables/FinalUML/ProjectFinalUML.png differ diff --git a/deliverables/FinalUML/UtilitiesFinalUML.png b/deliverables/FinalUML/UtilitiesFinalUML.png new file mode 100644 index 00000000..0e310e68 Binary files /dev/null and b/deliverables/FinalUML/UtilitiesFinalUML.png differ diff --git a/deliverables/InitialUML/ModelInitialUML.png b/deliverables/InitialUML/ModelInitialUML.png new file mode 100644 index 00000000..8ac33499 Binary files /dev/null and b/deliverables/InitialUML/ModelInitialUML.png differ diff --git a/src/main/java/it/polimi/ingsw/am32/client/Event.java b/src/main/java/it/polimi/ingsw/am32/client/Event.java index 97e92a19..c14dc362 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/Event.java +++ b/src/main/java/it/polimi/ingsw/am32/client/Event.java @@ -4,44 +4,199 @@ * Enumeration of the possible events that can occur during the game. */ public enum Event { - LOBBY(0), // STATUS - PREPARATION(1), // STATUS - PLAYING(2), // STATUS - TERMINATING(3), // STATUS - LAST_TURN(4), // STATUS - TERMINATED(5), // STATUS + /** + * Identifiers for the Lobby phase: the phase in which the players are waiting for the game to start. + * Associated with the number 0. + */ + LOBBY(0), + /** + * Identifiers for the preparation phase: the phase in which the players are selecting their starting card side and + * secret objective card. + * Associated with the number 1. + */ + PREPARATION(1), + /** + * Identifiers for the playing phase: the phase in which the players place their cards on the field and draw new + * cards if it is their turn. + * Associated with the number 2. + */ + PLAYING(2), + /** + * Identifiers for the terminating phase: when one of the players has gained 20 points or more. + * Associated with the number 3. + */ + TERMINATING(3), + /** + * Identifiers for the last turn phase: in which phase each player has one last turn to place a card on the field + * without drawing a new card. + * Associated with the number 4. + */ + LAST_TURN(4), + /** + * Identifiers for the game terminated phase: when the game is over and the final scores are displayed. + * Associated with the number 5. + */ + TERMINATED(5), + /** + * Indicates that the player should choose a connection type. + * Associated with the number 6. + */ CHOOSE_CONNECTION (6), + /** + * Indicates that the player should choose a game mode. + * Associated with the number 7. + */ SELECT_GAME_MODE(7), + /** + * Indicates that the player selected to create a new game. + * Associated with the number 8. + */ CREATE_GAME(8), + /** + * Indicates that the player selected to join an existing game. + * Associated with the number 9. + */ JOIN_GAME(9), + /** + * Indicates that the player selected to reconnect to a game. + * Associated with the number 10. + */ RECONNECT_GAME(10), + /** + * Indicates that the game has been created successfully. + * Associated with the number 11. + */ GAME_CREATED (11), + /** + * Indicates that the player has joined the game successfully. + * Associated with the number 12. + */ GAME_JOINED (12), + /** + * Indicates that the player has reconnected to the game successfully. + * Associated with the number 13. + */ GAME_RECONNECTED (13), + /** + * Indicates that a new player has joined the game. + * Associated with the number 14. + */ NEW_PLAYER_JOIN (14), + /** + * Indicates that a player has disconnected from the game. + * Associated with the number 15. + */ PLAYER_DISCONNECTED (15), + /** + * Indicates that the game is waiting for the start of the game, waiting for all players to join. + * Associated with the number 16. + */ WAITING_FOR_START (16), + /** + * Indicates that the game has started with all players joined. + * Associated with the number 17. + */ GAME_START (17), + /** + * Indicates that the player should select the side of the starter card. + * Associated with the number 18. + */ SELECT_STARTER_CARD_SIDE(18), + /** + * Indicates that the player has selected the side of the starter card not successfully. + * Associated with the number 19. + */ SELECT_STARTER_CARD_SIDE_FAILURE (19), + /** + * Indicates that the player should select the secret objective card. + * Associated with the number 20. + */ SELECT_SECRET_OBJ_CARD (20), + /** + * Indicates that the player has selected the secret objective card not successfully. + * Associated with the number 21. + */ SELECT_SECRET_OBJ_CARD_FAILURE (21), + /** + * Indicates that the player should place a card on the field. + * Associated with the number 22. + */ PLACE_CARD(22), + /** + * Indicates that the player has placed the card on the field not successfully. + * Associated with the number 23. + */ PLACE_CARD_FAILURE (23), + /** + * Indicates that the player should draw a card. + * Associated with the number 24. + */ DRAW_CARD(24), + /** + * Indicates that the player has reconnected to the game successfully. + * Associated with the number 25. + */ PLAYER_RECONNECTED(25), + /** + * Indicates that the player has drawn a card not successfully. + * Associated with the number 26. + */ DRAW_CARD_FAILURE(26), - WELCOME(27), // STATUS + /** + * Indicates phase in which the player is asked to select a game mode. + * Associated with the number 27. + */ + WELCOME(27), + /** + * Indicates that the player has completed the selection of the starter card side. + * Associated with the number 28. + */ SELECTED_STARTER_CARD_SIDE(28), + /** + * Indicates that the player has completed the selection of the secret objective card. + * Associated with the number 29. + */ SELECTED_SECRET_OBJ_CARD(29), + /** + * Indicates that the player has completed the selection of the card he wants to place on the field and the + * coordinates where he wants to place it. + * Associated with the number 30. + */ CARD_PLACED(30), + /** + * Indicates that the player has completed the selection of the card he wants to draw. + * Associated with the number 31. + */ CARD_DRAWN(31), + /** + * Indicates that the player is waiting for his turn to place a card on the field or the player is waiting for the + * start of playing phase. + * Associated with the number 32. + */ WAITING_FOR_TURN(32), + /** + * Indicates there was an error in the chat message. + * Associated with the number 33. + */ CHAT_ERROR(33), + /** + * Indicates that the game creation failed. + * Associated with the number 34. + */ CREATE_GAME_FAILURE(34), + /** + * Indicates that the player failed to join the game. + * Associated with the number 35. + */ JOIN_GAME_FAILURE(35), + /** + * Indicates that the player failed to reconnect to the game. + * Associated with the number 36. + */ RECONNECT_GAME_FAILURE(36); - + /** + * The integer value associated with the event. + */ private final int value; /** diff --git a/src/main/java/it/polimi/ingsw/am32/client/View.java b/src/main/java/it/polimi/ingsw/am32/client/View.java index 303f7735..1ad00679 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/View.java +++ b/src/main/java/it/polimi/ingsw/am32/client/View.java @@ -515,8 +515,16 @@ public abstract void updateRollback(String playerNickname, int removedCard, int */ public abstract void handleEvent(Event event, String nickname); + /** + * Method called when the node disconnects from the game. + * Called from the Network to notify the View that the connection to the server is lost. + */ public abstract void nodeDisconnected(); + /** + * Method called when the node reconnects to the game. + * Called from the Network to notify the View that the connection to the server is restored. + */ public abstract void nodeReconnected(); } diff --git a/src/main/java/it/polimi/ingsw/am32/client/listener/AskListener.java b/src/main/java/it/polimi/ingsw/am32/client/listener/AskListener.java index 12f78a1f..6bed922b 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/listener/AskListener.java +++ b/src/main/java/it/polimi/ingsw/am32/client/listener/AskListener.java @@ -212,7 +212,9 @@ private void processLobbyMessages() { } // If we successfully sent the message, remove it from the queue. synchronized (queuesLock) { - lobbyMessageQueue.removeFirst(); + if(!lobbyMessageQueue.isEmpty()) { + lobbyMessageQueue.removeFirst(); + } } logger.debug("LobbyMessage sent to the server: {}", currentLobbyMessage.getClass()); } catch (UploadFailureException e) { diff --git a/src/main/java/it/polimi/ingsw/am32/client/listener/AskListenerInterface.java b/src/main/java/it/polimi/ingsw/am32/client/listener/AskListenerInterface.java index 4c11087a..60e6751f 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/listener/AskListenerInterface.java +++ b/src/main/java/it/polimi/ingsw/am32/client/listener/AskListenerInterface.java @@ -3,8 +3,26 @@ import it.polimi.ingsw.am32.message.ClientToServer.CtoSLobbyMessage; import it.polimi.ingsw.am32.message.ClientToServer.CtoSMessage; +/** + * Interface for the AskListener class: used to manage the messages that clients want to send to the server. + * Listens for messages to be added to the queues (according to their type). + * There are two queues: one for CtoSMessage and one for CtoSLobbyMessage. + */ public interface AskListenerInterface { + /** + * Adds a CtoSMessage to the queue to be sent to the server. + * @param message The message to be added to the queue and which will be sent to the server. + */ void addMessage(CtoSMessage message); + + /** + * Adds a CtoSLobbyMessage to the queue of messages to be sent to the server. + * @param message The message to be added to the queue and which will be sent to the server. + */ void addMessage(CtoSLobbyMessage message); + + /** + * Flushes both the message and lobbyMessage queues. + */ void flushMessages(); } diff --git a/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java b/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java index 62b99639..6d643600 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java +++ b/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUI.java @@ -3,6 +3,7 @@ import it.polimi.ingsw.am32.client.*; import it.polimi.ingsw.am32.message.ClientToServer.*; import it.polimi.ingsw.am32.network.exceptions.ConnectionSetupFailedException; +import it.polimi.ingsw.am32.utilities.IPAddressFinder; import javafx.animation.*; import javafx.application.Application; import javafx.application.Platform; @@ -27,6 +28,7 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; + /** * The class GraphicalUI is the class that manages the graphical user interface of the game and interacts with the * GUIApplication class. The class extends the abstract class View and implements the methods of the View class. @@ -220,8 +222,10 @@ public class GraphicalUI extends View { "codex_rulebook_it_04.png", "codex_rulebook_it_05.png", "codex_rulebook_it_06.png", "codex_rulebook_it_07.png", "codex_rulebook_it_08.png", "codex_rulebook_it_09.png", "codex_rulebook_it_10.png", "codex_rulebook_it_11.png", "codex_rulebook_it_12.png"}; + /** * Method used to retrieve dynamically a resource URI from the correct context folder. + * @implSpec GUI-NON-CORE * @param resourceName The name of the resource to retrieve. * @return The URI of the resource converted to a String object to be used with JavaFX image loader. */ @@ -235,6 +239,7 @@ private static String retrieveResourceURI(String resourceName) { /** * Used to launch the GUIApplication class. + * @implSpec GUI-NON-CORE */ @Override public void launch() { @@ -243,6 +248,7 @@ public void launch() { /** * Constructor of the class. + * @implSpec GUI-NON-CORE */ public GraphicalUI() { super(); @@ -251,7 +257,7 @@ public GraphicalUI() { /** * Set the connection between the GUI and the GUIApplication. In this way the GUI can update the scene of the * GUIApplication using the reference of the GUIApplication and the methods of the GUIApplication. - * + * @implSpec GUI-NON-CORE * @param app The GUIApplication with which the GUI will be connected. */ protected void setApp(GraphicalUIApplication app) { @@ -260,6 +266,7 @@ protected void setApp(GraphicalUIApplication app) { /** * Get the root of the welcome page, which is the first page shown to the player. + * @implSpec GUI-NON-CORE */ protected StackPane getWelcomeRoot() { showWelcome(); @@ -268,6 +275,7 @@ protected StackPane getWelcomeRoot() { /** * Set up the welcome page of the GUI, which contains the welcome image and the button to show the rule book. + * @implSpec GUI-NON-CORE */ @Override public void showWelcome() { @@ -294,9 +302,11 @@ public void showWelcome() { welcomeRoot.getChildren().add(selectionPane); }); } + /** * Set up the rule book of the game. The player can navigate through the pages of the rule book using the buttons * “<” to go to the previous page and “>” to go to the next page. + * @implSpec GUI-NON-CORE */ private void showRuleBook() { StackPane ruleBookRoot = new StackPane(); @@ -326,7 +336,7 @@ private void showRuleBook() { /** * Get the buttons to navigate through the pages of the rule book and set the action of the buttons. - * + * @implSpec GUI-NON-CORE * @param ruleBook The image view of the rule book. * @return The array of buttons to navigate through the pages of the rule book. */ @@ -351,6 +361,7 @@ private Button[] getBox(ImageView ruleBook) { /** * Set the connection page of the GUI. The player can choose the connection type between socket and RMI. + * @implSpec GUI-CORE */ @Override public void chooseConnection() { @@ -388,10 +399,11 @@ public void chooseConnection() { // create the RMI connection root StackPane RMIRoot = new StackPane(); Label labelRMIIP = createLabel("RMI", -80, -80); // add the title - TextField RMIIp = createTextField("Enter the IP", 35, 250, -50, -30); // create the text field asks the player to enter the IP address - TextField RMIPort = createTextField("Enter the port", 35, 250, -50, 50); // create the text field asks the player to enter the port number + TextField RMIIp = createTextField("Server IP", 30, 250, -50, -35); // create the text field asks the player to enter the IP address + TextField RMIPort = createTextField("Server Port", 30, 250, -50, 30); // create the text field asks the player to enter the port number Button OkRMIButton = createButton("[OK]", 160, 0); // create the button Ok to confirm the input. - RMIRoot.getChildren().addAll(OkRMIButton, labelRMIIP, RMIIp, RMIPort); // the view when the player choose the socket connection + ComboBox localIPAddress = createComboBox(IPAddressFinder.getIPv4Addresses(), "Select Client IP",25, 250, -50, 90); // ComboBox used to select the correct IPv4 address associated with the current machine + RMIRoot.getChildren().addAll(OkRMIButton, labelRMIIP, RMIIp, RMIPort, localIPAddress); // the view when the player choose the socket connection // set the action of the buttons (Socket) socketButton.setOnAction(e -> { @@ -437,12 +449,14 @@ public void chooseConnection() { String ServerPort = RMIPort.getText(); try { int portNumber = Integer.parseInt(ServerPort); - if (isValid.isIpValid(ServerIP) && isValid.isPortValid(portNumber)) { // Check if the IP address is valid + if (isValid.isIpValid(ServerIP) && isValid.isPortValid(portNumber) + && localIPAddress.getValue() != null) { + System.setProperty("java.rmi.server.hostname", localIPAddress.getValue()); setRMIClient(ServerIP, portNumber); - selectionPane.getChildren().remove(RMIRoot); - askSelectGameMode(); + selectionPane.getChildren().remove(RMIRoot); + askSelectGameMode(); } else { - createAlert("Invalid IP/port number"); + createAlert("Check the configuration and try again!"); RMIIp.clear(); RMIPort.clear(); } @@ -460,6 +474,7 @@ public void chooseConnection() { /** * Set the socket connection between the client and the server. + * @implSpec GUI-NON-CORE * @param ServerIP the IP address of the server * @param portNumber the port number of the server */ @@ -470,6 +485,7 @@ public void setSocketClient(String ServerIP, int portNumber) throws ConnectionSe /** * Set the RMI connection between the client and the server. + * @implSpec GUI-NON-CORE * @param serverURL the URL of the server * @param port the port number of the server */ @@ -485,136 +501,172 @@ public void setRMIClient(String serverURL, int port) throws ConnectionSetupFaile */ @Override public void askSelectGameMode() { - StackPane gameModeRoot = new StackPane(); - Label label = createLabel("Game \n Mode", 150, 10); - VBox gameMode = new VBox(); - gameMode.setSpacing(10); - Button newGameButton = createButton("[New Game]"); - Button joinGameButton = createButton("[Join Game]"); - Button reconnectGameButton = createButton("[Reconnect]"); - gameMode.getChildren().addAll(newGameButton, joinGameButton, reconnectGameButton); - gameMode.setTranslateX(300); - gameMode.setTranslateY(300); - gameModeRoot.getChildren().addAll(label, gameMode); - selectionPane.getChildren().add(gameModeRoot); - newGameButton.setOnAction(e -> { - selectionPane.getChildren().remove(gameModeRoot); - askCreateGame(); - }); - joinGameButton.setOnAction(e -> { - selectionPane.getChildren().remove(gameModeRoot); - askJoinGame(); - }); - reconnectGameButton.setOnAction(e -> { - selectionPane.getChildren().remove(gameModeRoot); - askReconnectGame(); + Platform.runLater(() -> { + if(attemptingReconnection) { + resetSelectionPaneContext(); + selectionPane.getChildren().removeAll(); + attemptingReconnection = false; + } + + Status = Event.WELCOME; + currentEvent = Event.SELECT_GAME_MODE; + StackPane gameModeRoot = new StackPane(); + Label label = createLabel("Game \n Mode", 150, 10); + VBox gameMode = new VBox(); + gameMode.setSpacing(10); + Button newGameButton = createButton("[New Game]"); + Button joinGameButton = createButton("[Join Game]"); + Button reconnectGameButton = createButton("[Reconnect]"); + gameMode.getChildren().addAll(newGameButton, joinGameButton, reconnectGameButton); + gameMode.setTranslateX(300); + gameMode.setTranslateY(300); + gameModeRoot.getChildren().addAll(label, gameMode); + selectionPane.getChildren().add(gameModeRoot); + newGameButton.setOnAction(e -> { + selectionPane.getChildren().remove(gameModeRoot); + askCreateGame(); + }); + joinGameButton.setOnAction(e -> { + selectionPane.getChildren().remove(gameModeRoot); + askJoinGame(); + }); + reconnectGameButton.setOnAction(e -> { + selectionPane.getChildren().remove(gameModeRoot); + askReconnectGame(); + }); }); } /** * Set the page which asks the player to insert the nickname and the players number to create a new game. + * @implSpec GUI-CORE */ @Override public void askCreateGame() { - currentEvent = Event.CREATE_GAME; - StackPane createGameRoot = new StackPane(); - - Label labelNickname = createLabel("Nickname", -90, -80); - Label labelPlayers = createLabel("Players number", -60, 30); - - TextField nickname = createTextField("Enter the nickname", 35, 350, -40, -30); - - Button twoButton = createButton("[2]", 30, "#3A2111", -150, 70); - Button threeButton = createButton("[3]", 30, "#3A2111", -70, 70); - Button fourButton = createButton("[4]", 30, "#3A2111", 10, 70); - Button createButton = createButton("[Create]", 140, 65); - Light.Distant light = new Light.Distant(); - light.setColor(Color.CHOCOLATE); - Lighting lighting = new Lighting(); - lighting.setLight(light); - createGameRoot.getChildren().addAll(labelNickname, labelPlayers, nickname, twoButton, threeButton, fourButton, createButton); - twoButton.setOnAction(e -> { - playerNum = 2; - handleButtonClick(twoButton, threeButton, fourButton, lighting); - }); - threeButton.setOnAction(e -> { - playerNum = 3; - handleButtonClick(threeButton, twoButton, fourButton,lighting); - }); - fourButton.setOnAction(e -> { - playerNum = 4; - handleButtonClick(fourButton, threeButton, twoButton,lighting); - }); - createButton.setOnAction(e -> { - thisPlayerNickname = nickname.getText(); - if (thisPlayerNickname.isBlank()) { - createAlert("Nickname cannot be left blank"); - nickname.clear(); - } else if (thisPlayerNickname.length() > 20) { - createAlert("Nickname must be less than 20 characters"); - nickname.clear(); - } else { - if (playerNum == 2 || playerNum == 3 || playerNum == 4) { - notifyAskListener(new NewGameMessage(thisPlayerNickname, playerNum)); + Platform.runLater(() -> { + if(attemptingReconnection) { + resetSelectionPaneContext(); + selectionPane.getChildren().removeAll(); + attemptingReconnection = false; + } + + currentEvent = Event.CREATE_GAME; + StackPane createGameRoot = new StackPane(); + + Label labelNickname = createLabel("Nickname", -90, -80); + Label labelPlayers = createLabel("Players number", -60, 30); + + TextField nickname = createTextField("Enter the nickname", 35, 350, -40, -30); + + Button twoButton = createButton("[2]", 30, "#3A2111", -150, 70); + Button threeButton = createButton("[3]", 30, "#3A2111", -70, 70); + Button fourButton = createButton("[4]", 30, "#3A2111", 10, 70); + Button createButton = createButton("[Create]", 140, 65); + Light.Distant light = new Light.Distant(); + light.setColor(Color.CHOCOLATE); + Lighting lighting = new Lighting(); + lighting.setLight(light); + createGameRoot.getChildren().addAll(labelNickname, labelPlayers, nickname, twoButton, threeButton, fourButton, createButton); + twoButton.setOnAction(e -> { + playerNum = 2; + handleButtonClick(twoButton, threeButton, fourButton, lighting); + }); + threeButton.setOnAction(e -> { + playerNum = 3; + handleButtonClick(threeButton, twoButton, fourButton,lighting); + }); + fourButton.setOnAction(e -> { + playerNum = 4; + handleButtonClick(fourButton, threeButton, twoButton,lighting); + }); + createButton.setOnAction(e -> { + thisPlayerNickname = nickname.getText(); + if (thisPlayerNickname.isBlank()) { + createAlert("Nickname cannot be left blank"); + nickname.clear(); + } else if (thisPlayerNickname.length() > 20) { + createAlert("Nickname must be less than 20 characters"); + nickname.clear(); } else { - createAlert("Please select the number"); + if (playerNum == 2 || playerNum == 3 || playerNum == 4) { + notifyAskListener(new NewGameMessage(thisPlayerNickname, playerNum)); + } else { + createAlert("Please select the number"); + } } - } + }); + selectionPane.getChildren().add(createGameRoot); }); - selectionPane.getChildren().add(createGameRoot); } /** * Set the page which asks the player to insert the nickname and the game ID to reconnect to a game. + * @implSpec GUI-CORE */ @Override public void askJoinGame() { - currentEvent = Event.JOIN_GAME; - StackPane joinGameRoot = new StackPane(); + Platform.runLater(() -> { + if(attemptingReconnection) { + resetSelectionPaneContext(); + selectionPane.getChildren().removeAll(); + attemptingReconnection = false; + } - Label labelNickname = createLabel("Nickname&GameID", -80, -80); + currentEvent = Event.JOIN_GAME; + StackPane joinGameRoot = new StackPane(); - TextField nickname = createTextField("Enter the nickname", 35, 350, -40, -30); - TextField accessID = createTextField("Game ID", 35, 220, -100, 35); + Label labelNickname = createLabel("Nickname&GameID", -80, -80); - Button joinButton = createButton("[Join]", 140, 65); + TextField nickname = createTextField("Enter the nickname", 35, 350, -40, -30); + TextField accessID = createTextField("Game ID", 35, 220, -100, 35); - joinGameRoot.getChildren().addAll(labelNickname, nickname, accessID, joinButton); + Button joinButton = createButton("[Join]", 140, 65); - joinButton.setOnAction(e -> handleButtonJoinAndReconnectClick(nickname,accessID)); - selectionPane.getChildren().add(joinGameRoot); + joinGameRoot.getChildren().addAll(labelNickname, nickname, accessID, joinButton); + + joinButton.setOnAction(e -> handleButtonJoinAndReconnectClick(nickname,accessID)); + selectionPane.getChildren().add(joinGameRoot); + }); } /** * Set the page which asks the player to insert the nickname and the game ID to reconnect to a game. + * @implSpec GUI-CORE */ @Override public void askReconnectGame() { - currentEvent = Event.RECONNECT_GAME; - StackPane reconnectGameRoot = new StackPane(); + Platform.runLater(() -> { + if(attemptingReconnection) { + resetSelectionPaneContext(); + selectionPane.getChildren().removeAll(); + attemptingReconnection = false; + } - Label labelNickname = createLabel("Nickname&GameID", -80, -80); + currentEvent = Event.RECONNECT_GAME; + StackPane reconnectGameRoot = new StackPane(); - TextField nickname = createTextField("Enter the nickname", 35, 350, -40, -30); - TextField accessID = createTextField("Game ID", 35, 220, -100, 35); + Label labelNickname = createLabel("Nickname&GameID", -80, -80); - Button joinButton = createButton("[Reconnect]", 140, 65); + TextField nickname = createTextField("Enter the nickname", 35, 350, -40, -30); + TextField accessID = createTextField("Game ID", 35, 220, -100, 35); - reconnectGameRoot.getChildren().addAll(labelNickname, nickname, accessID, joinButton); + Button joinButton = createButton("[Reconnect]", 140, 65); - joinButton.setOnAction(e -> handleButtonJoinAndReconnectClick(nickname,accessID)); - selectionPane.getChildren().add(reconnectGameRoot); + reconnectGameRoot.getChildren().addAll(labelNickname, nickname, accessID, joinButton); + + joinButton.setOnAction(e -> handleButtonJoinAndReconnectClick(nickname,accessID)); + selectionPane.getChildren().add(reconnectGameRoot); + }); } /** * Handle the click on the confirmation button of the join game and reconnect game page. The method checks if the * nickname is valid and the game ID is a number. If the nickname is valid and the game ID is a number, the method * generates the AccessGameMessage or the ReconnectGameMessage based on the current event and notifies the listener. - * + * @implSpec GUI-NON-CORE * @param nickname the text field where the player inserts the nickname. * @param accessID the text field where the player inserts the game ID. */ - public void handleButtonJoinAndReconnectClick(TextField nickname, TextField accessID){ thisPlayerNickname = nickname.getText(); String ID = accessID.getText(); @@ -638,16 +690,16 @@ public void handleButtonJoinAndReconnectClick(TextField nickname, TextField acce } } } + /** * Once the player receives the NewGameConfirmationMessage from the server, the method is called by processMessage * to store the gameID, the nickname of the player who created the game, and add it in the list of players. * In addition, the method sets the currentEvent to WAITING_FOR_START and the Status to LOBBY, then it creates the * waiting page where the player can see the gameID and the list of players who joined the game. - * + * @implSpec GUI-CORE * @param gameID the game ID returned by the server after the confirmation of the new game * @param recipientNickname the nickname of the player who asked to create the new game */ - @Override public void updateNewGameConfirm(int gameID, String recipientNickname) { // use Platform.runLater to run the code in the JavaFX Application Thread @@ -684,7 +736,7 @@ public void updateNewGameConfirm(int gameID, String recipientNickname) { /** * Once the player receives the LobbyPlayerList message from the server, the method is called by * processMessage, to update the player's list in the Lobby phase and print the player's list updated. - * + * @implSpec GUI-NON-CORE * @param players the list updated of players in the game. */ @Override @@ -696,10 +748,12 @@ public void updatePlayerList(ArrayList players) { playerListView.setText(players.toString()); }); } + /** * After receiving the GameStarted message from the server, the method is called to set up the view of the players, * to load the images which will be used to set up the game view, to set up the player's data and call the method * setGameView to set the view of the game in the preparation phase. + * @implSpec GUI-NON-CORE */ @Override public void setUpPlayersData() { @@ -768,6 +822,7 @@ public void setUpPlayersData() { * notifications of the game. The hand area contains the common objective cards, secret objective cards and the * hand cards of the player. The chat area lets the player send messages to the other players and view the messages * received. + * @implSpec GUI-NON-CORE */ private void setGameView() { // set the master pane @@ -847,18 +902,22 @@ private void setGameView() { noticeEventPanel.setVisible(false); - masterPane.getChildren().addAll(topLine, board,returnToMyField,playerInfoPanel,noticeArea,noticeEventPanel, deckArea, - deckSize, bottomLine, chatArea.getChatArea(),cardLabels); + masterPane.getChildren().addAll(topLine, board,returnToMyField,playerInfoPanel,noticeArea,noticeEventPanel, + deckArea, deckSize, bottomLine, chatArea.getChatArea(),cardLabels); // update the scene of the application with the master pane masterPane.setMinWidth(1250); app.updateScene(masterPane,1250,750); app.getPrimaryStage().setMinWidth(1250); + app.getPrimaryStage().setMinHeight(750); + app.getPrimaryStage().setMaxWidth(1250); + app.getPrimaryStage().setMaxHeight(750); } /** * Method create VBox to store the player's info area. The player's info area contains the player's nickname, the * player's score, the player's resources and the player's colour. + * @implSpec GUI-NON-CORE * @return the VBox which contains the player's info area. */ private VBox createPlayerInfoPanel() { @@ -918,6 +977,7 @@ private VBox createPlayerInfoPanel() { /** * Create the top line panel of the master pane. The top line panel contains the label indicating the nickname of * thisPlayer, the game ID, the status of the match, the player order, the rules button and the help button. + * @implSpec GUI-NON-CORE * @return the HBox which contains the components needed. */ private HBox createTopLinePanel(){ @@ -946,6 +1006,7 @@ private HBox createTopLinePanel(){ /** * Method create the deck area of the player. The deck area contains the resource deck and the gold deck. The player * can draw a card from the deck by clicking on the card in the deck. + * @implSpec GUI-NON-CORE * @return the VBox which contains the array of the resource deck and the gold deck. */ private VBox createDeckArea() { @@ -960,7 +1021,6 @@ private VBox createDeckArea() { new ImageView(new Image(retrieveResourceURI("placeholder.png"), 120, 80, true, false)) }; - deckArea = new VBox(); deckArea.setSpacing(10); HBox resourceDeck = new HBox(); @@ -980,6 +1040,7 @@ private VBox createDeckArea() { /** * Method create the bottom line panel of the master pane. The bottom line panel contains the common objective cards, * the secret objective cards and the hand cards of the player. + * @implSpec GUI-NON-CORE * @return the HBox which contains the components needed. */ private HBox createBottomLinePanel() { @@ -1002,12 +1063,13 @@ private HBox createBottomLinePanel() { handleHandClicks(); return bottomLine; } + /** * Method create the notification event panel. The notification event panel is used to notify the player that it's * his turn to play. + * @implSpec GUI-NON-CORE * @return the Group which contains the notification panel and the label of the content of the notification. */ - private Group createNoticeEventPanel() { Group root = new Group(); root.setAutoSizeChildren(true); @@ -1029,6 +1091,8 @@ private Group createNoticeEventPanel() { /** * Method to handle the click action of the notification event panel. The player can rotate the notification panel * for 360 degrees. + * @implSpec GUI-NON-CORE + * @param root the group which contains the notification panel. */ private void handleNoticeClicks(Group root) { RotateTransition rotateTransition = new RotateTransition(Duration.seconds(0.5), root); @@ -1036,11 +1100,12 @@ private void handleNoticeClicks(Group root) { rotateTransition.setCycleCount(1); rotateTransition.setAxis(Rotate.Y_AXIS); rotateTransition.play(); - } + /** * Method set the click action of the player's field. The player can zoom in/out the field using the mouse wheel * and move the field using the drag action. + * @implSpec GUI-NON-CORE * @param boardReal the board of the player */ private void handleBoardAction(StackPane boardReal) { @@ -1064,9 +1129,11 @@ private void handleBoardAction(StackPane boardReal) { boardReal.setTranslateY(e.getSceneY() - dragPos[1]); }); // Enable translating of player field when mouse button is held down } + /** * Method set the click action of the player's nickname. The player can see the field of the player that he wants * to see by clicking on the nickname of the player. + * @implSpec GUI-NON-CORE * @param player the nickname of the player that thisPlayer wants to see the field. */ private void handlePlayerNicknameClick(String player) { @@ -1081,7 +1148,7 @@ private void handlePlayerNicknameClick(String player) { /** * Method set the click action of the cards in the deck. The player can draw a card from the deck by clicking on the * card in the deck. - * + * @implSpec GUI-NON-CORE * @param cardView the view of the card in the deck. * @param cardID the ID of the card. * @param cardType the type of the deck where the card is drawn. @@ -1104,6 +1171,7 @@ private void handleDeckCardsClicks(ImageView cardView, int cardID, int cardType) /** * Method to set the click action of the cards in the drawing area. + * @implSpec GUI-NON-CORE */ private void handleDeckClicks() { handleDeckCardsClicks(resourceDeckView[0],-1, 0); @@ -1116,6 +1184,7 @@ private void handleDeckClicks() { /** * Method to set the click action of the cards in the hand. + * @implSpec GUI-NON-CORE */ private void handleHandClicks() { for (int i = 0; i < 3; i++) { // For all cards in the player's hand @@ -1154,6 +1223,7 @@ private void handleHandClicks() { * update the match status of the player, and update the player of the current match status. * If the match status is TERMINATING, the method is called to show the points of all players in the game with * a pop-up window. + * @implSpec GUI-CORE * @param matchStatus the current match status received from the server */ @Override @@ -1169,13 +1239,12 @@ public void updateMatchStatus(int matchStatus) { }); } - // Methods to create the components of the GUI /** * Create a stylized label with the specified text and size. * Used anywhere a stylized label is needed. - * + * @implSpec GUI-NON-CORE * @param text The text contained inside the label * @param size The size of the font * @return The label created @@ -1191,7 +1260,7 @@ private Label createLabel(String text, int size) { /** * Create a stylized label with the specified text, X and Y coordinates. * This version of the method is used in starting page. - * + * @implSpec GUI-NON-CORE * @param text The text contained inside the label * @param X The X coordinate of the label * @param Y The Y coordinate of the label @@ -1209,6 +1278,7 @@ private Label createLabel(String text, int X, int Y) { /** * Create a stylized button with the specified text. + * @implSpec GUI-NON-CORE * @param buttonName the text contained inside the button * @return the button created */ @@ -1222,6 +1292,7 @@ private Button createButton(String buttonName) { /** * Create a stylized button with the specified text, X and Y coordinates. + * @implSpec GUI-NON-CORE * @param buttonName the text contained inside the button * @param X the X coordinate of the button * @param Y the Y coordinate of the button @@ -1239,7 +1310,7 @@ private Button createButton(String buttonName, int X, int Y) { /** * Create a stylized button with the specified text, size and color, and X and Y coordinates. - * + * @implSpec GUI-NON-CORE * @param buttonName the text contained inside the button * @param size the size of the text inside the button * @param color the color of the text inside the button @@ -1258,6 +1329,7 @@ private Button createButton(String buttonName, int size, String color, int X, in /** * Create a text field with the specified prompt text, maximum height, maximum width, X and Y coordinates. + * @implSpec GUI-NON-CORE * @param promptText the prompt text of the text field * @param MaxHeight the maximum height of the text field * @param MaxWidth the maximum width of the text field @@ -1281,6 +1353,7 @@ private TextField createTextField(String promptText, int MaxHeight, int MaxWidth /** * Create a stylized Alert pop-up window with the specified reason. + * @implSpec GUI-NON-CORE * @param reason the reason of the error alert */ private void createAlert(String reason) { @@ -1302,8 +1375,37 @@ private void createAlert(String reason) { }); } + /** + * Create a stylized ComboBox with the specified content, text, size and position. + * @implSpec GUI-NON-CORE + * @param content the content of the ComboBox + * @param text the text of the ComboBox + * @param MaxHeight the maximum height of the ComboBox + * @param MaxWidth the maximum width of the ComboBox + * @param X the X coordinate of the ComboBox + * @param Y the Y coordinate of the ComboBox + * @return The ComboBox created + */ + private ComboBox createComboBox(List content, String text, + int MaxHeight, int MaxWidth, int X, int Y){ + ComboBox newComboBox = new ComboBox<>(); + for(String string : content){ + newComboBox.getItems().add(string); + } + newComboBox.setStyle("-fx-background-color: #E6DEB3;-fx-text-fill: #3A2111;-fx-alignment: center;" + + "-fx-font-size: 20px;-fx-font-family: 'JejuHallasan';-fx-effect: dropshadow( gaussian , " + + "rgba(58,33,17,100,0.2) , 10,0,0,10 );-fx-border-color: #3A2111; -fx-border-width: 2px; " + + "-fx-border-radius: 5px; -fx-background-radius: 5px;"); + newComboBox.setPromptText(text); + newComboBox.setMaxSize(MaxWidth, MaxHeight); + newComboBox.setTranslateX(X); + newComboBox.setTranslateY(Y); + return newComboBox; + } + /** * Method used to show the field of the player whose nickname is passed as a parameter. + * @implSpec GUI-NON-CORE * @param playerNickname the nickname of the player whose field should be shown in the board area. */ @Override @@ -1320,6 +1422,7 @@ public void showPlayersField(String playerNickname) { /** * Method used to make the highlight effect on the player's points and resources when the player's turn is now or * the match status is TERMINATING. + * @implSpec GUI-NON-CORE * @param playerNickname the nickname of the player whose points and resources should be shown. */ @Override @@ -1337,6 +1440,7 @@ public void showPointsAndResource(String playerNickname) { * Once the player receives the PlayerTurnMessage from the server, the method is called by processMessage to update * the currentPlayer in the game and print the message to notify the player whose turn is now, also, the method * notifies players the order of the turn in the game. + * @implSpec GUI-CORE * @param playerNickname the nickname of the player who should be able to place the card and draw card in the field. */ @Override @@ -1371,7 +1475,7 @@ public void updatePlayerTurn(String playerNickname) { /** * This method is called by processMessage to update the all data of the players in the game when the game enters * the playing phase or when the player reconnects to the game. - * + * @implSpec GUI-CORE * @param playerNicknames the nicknames of the players in the game. * @param playerConnected the connection status of the players in the game. * @param playerColours the colours assigned to the players in the game. @@ -1407,6 +1511,8 @@ public void updatePlayerData(ArrayList playerNicknames, ArrayList playersResourcesSummary, ArrayList playerAssignedSecretObjectiveCards, int playerStartingCard) { + // Reset the flag attemptingReconnection to indicate that the player has successfully reconnected + attemptingReconnection = false; // Forcefully overwrite the chatHistory to prevent an unwanted use of Server's class inside the Client // We are now rebuilding the ChatMessage object from the ArrayList of Arrays ArrayList chatHistoryRebuild = new ArrayList<>(); @@ -1443,17 +1549,20 @@ public void updatePlayerData(ArrayList playerNicknames, ArrayList playerNicknames, ArrayList { // the current available spaces in the field. updateAfterPlacedCard(players.get(finalI), card[2], card[0], card[1], @@ -1493,8 +1601,9 @@ public void updatePlayerData(ArrayList playerNicknames, ArrayList playerNicknames, ArrayList secrets, ArrayList comm /** * Method to show the hand of the player in the GUI adding the highlight effect on the cards in the hand. + * @implSpec GUI-NON-CORE */ @Override public void showHand() { @@ -1602,6 +1713,7 @@ public void showHand() { /** * Method to show the image of the card in the GUI with the specified ID and side. + * @implSpec GUI-NON-CORE * @param ID the ID of the card should be shown in the image. * @param isUp the side of the card should be shown in the image. */ @@ -1628,7 +1740,7 @@ public void showCard(int ID, boolean isUp) { /** * Method called by the processMessage to update the player's field after receiving confirmation from the server that the card placement was successful. - * + * @implSpec GUI-CORE * @param playerNickname the nickname of the player * @param placedCard the ID of the card placed in the field * @param placedCardCoordinates the coordinates of the card placed in the field @@ -1673,7 +1785,7 @@ public void updatePlacedCardConfirm(String playerNickname, int placedCard, int[] /** * Used to display the winners of the game and the final points of the players after the game has ended. - * + * @implSpec GUI-CORE * @param players the nicknames of the players * @param points the points of the players * @param secrets the secret objective card of the players @@ -1714,6 +1826,7 @@ public void showMatchWinners(ArrayList players, ArrayList point /** * Method used to update the player's board and public info when the player disconnects from the game after the * placement of the card. + * @implSpec GUI-NON-CORE * @param playerNickname the nickname of the player whose board should be updated with the rollback * @param removedCard the ID of the card that should be removed from the board and the public info of the player * @param playerPoints the points of the player after the rollback @@ -1735,7 +1848,7 @@ public void updateRollback(String playerNickname, int removedCard, int playerPoi /** * Used to print out the entire chat history when the player reconnects to the game. - * + * @implSpec GUI-NON-CORE * @param chatHistory the chat history of the game */ @Override @@ -1747,6 +1860,7 @@ public void showChatHistory(List chatHistory) { /** * Called when a chat message is received from the server. + * @implSpec GUI-NON-CORE * @param recipientString the nickname of the recipient of the message * @param senderNickname the nickname of the sender of the message * @param content the content of the message @@ -1764,7 +1878,7 @@ public void updateChat(String recipientString, String senderNickname, String con /** * Called when the player receives the starting card id from the server. * Saves the received starting card, and calls other methods to display card side selection - * + * @implSpec GUI-NON-CORE * @param cardId the ID of the card */ @Override @@ -1775,7 +1889,7 @@ public void setStarterCard(int cardId) { /** * Support method used to prompt the user to select a starting card side - * + * @implSpec GUI-NON-CORE * @param ID the ID of the starter card */ @Override @@ -1786,7 +1900,7 @@ public void requestSelectStarterCardSide(int ID) { /** * Method called by the processMessage after receiving confirmation from the server that the starter card side was selected. - * + * @implSpec GUI-NON-CORE * @param colour the colour assigned to the player * @param cardID the ID of the starter card * @param isUp the side of the starter card @@ -1796,7 +1910,9 @@ public void requestSelectStarterCardSide(int ID) { @Override public void updateConfirmStarterCard(int colour, int cardID, boolean isUp, ArrayList availablePos, int[] resources) { Platform.runLater(() -> { - masterPane.getChildren().removeLast(); + if(currentEvent.equals(Event.SELECT_STARTER_CARD_SIDE)) { // Remove the previous starter card selection area + masterPane.getChildren().removeLast(); + } String colourReceived = convertToColour(colour); publicInfo.get(thisPlayerNickname).updateColour(colourReceived); playerViews.get(thisPlayerNickname).setColour(imagesMap.get(colourReceived)); @@ -1814,6 +1930,7 @@ public void updateConfirmStarterCard(int colour, int cardID, boolean isUp, Array /** * Method called when place card confirmation is received from server. * Enable drawing from deck + * @implSpec GUI-NON-CORE */ @Override public void requestDrawCard() { @@ -1823,7 +1940,7 @@ public void requestDrawCard() { /** * Method called by the processMessage after receiving confirmation from the server that the card was drawn successfully. - * + * @implSpec GUI-NON-CORE * @param hand the updated hand of the player after the draw */ @Override @@ -1842,7 +1959,7 @@ public void updateAfterDrawCard(ArrayList hand) { /** * Used to update the decks after a player has drawn a card - * + * @implSpec GUI-NON-CORE * @param resourceDeckSize the new size of the resource deck * @param goldDeckSize the new size of the gold deck * @param currentResourceCards the current resource cards in the game that the player can draw @@ -1906,12 +2023,30 @@ public void updateDeck(int resourceDeckSize, int goldDeckSize, int[] currentReso /** * Used to handle the failure cases of the events in the game. - * + * @implSpec GUI-CORE * @param event the event that has failed * @param reason the reason for the failure */ @Override public void handleFailureCase(Event event, String reason) { + if(attemptingReconnection) { + switch (event) { + case RECONNECT_GAME -> { + // If the reconnection fails we just have to try again! + askSelectGameMode(); // This method will in itself consume the attemptingReconnection flag + } + case JOIN_GAME -> { + // If the join game fails we just have to try again! + askJoinGame(); // This method will in itself consume the attemptingReconnection flag + } + case CREATE_GAME -> { + // If the game creation fails we just have to try again! + askCreateGame(); // This method will in itself consume the attemptingReconnection flag + } + } + return; + } + createAlert(reason); // in case of create game failure, join game failure, reconnect game failure just notify the player with the reason of the failure. switch (event){ @@ -1936,6 +2071,7 @@ public void handleFailureCase(Event event, String reason) { /** * Used to active chat area, once big boy message is received from the server. + * @implSpec GUI-NON-CORE */ @Override public void startChatting() { @@ -1947,6 +2083,7 @@ public void startChatting() { /** * Method to handle effect when deck label is clicked + * @implSpec GUI-NON-CORE */ @Override public void showDeck() { @@ -1959,6 +2096,7 @@ public void showDeck() { /** * Used to display help information when help button is clicked during the game + * @implSpec GUI-NON-CORE */ @Override public void showHelpInfo() { @@ -1993,6 +2131,7 @@ public void showHelpInfo() { /** * Method called by the processMessage after receiving confirmation from the server that the secret objective card was selected. + * @implSpec GUI-NON-CORE */ @Override public void requestSelectSecretObjectiveCard() { @@ -2002,14 +2141,16 @@ public void requestSelectSecretObjectiveCard() { /** * Method called by the processMessage after receiving confirmation from the server that the secret objective card was selected. - * + * @implSpec GUI-NON-CORE * @param chosenSecretObjectiveCard the ID of the secret objective card selected by the player */ @Override public void updateConfirmSelectedSecretCard(int chosenSecretObjectiveCard) { secretObjCardSelected = chosenSecretObjectiveCard; Platform.runLater(() -> { - masterPane.getChildren().removeLast(); + if(currentEvent.equals(Event.SELECT_SECRET_OBJ_CARD)) { + masterPane.getChildren().removeLast(); + } String cardIdStr = chosenSecretObjectiveCard > 99 ? String.valueOf(chosenSecretObjectiveCard) : "0" + chosenSecretObjectiveCard; secretObjCardView.setImage(new Image(retrieveResourceURI("cards_front_" + cardIdStr + ".png"), 120, 80, true, true)); }); @@ -2017,6 +2158,7 @@ public void updateConfirmSelectedSecretCard(int chosenSecretObjectiveCard) { /** * Method called by the processMessage after receiving confirmation from the server that the secret objective card was selected. + * @implSpec GUI-NON-CORE */ @Override public void requestPlaceCard() { @@ -2044,7 +2186,7 @@ public void requestPlaceCard() { /** * Method set to handle the click action of the available space in the field. * When a player clicks on the available space, the method notifies the listener to place the card in the field. - * + * @implSpec GUI-NON-CORE * @param availableSpace the image view of the available space the player has clicked on * @param x the x coordinate of the available space (field coordinates) * @param y the y coordinate of the available space (field coordinates) @@ -2059,7 +2201,7 @@ private void handleAvailableSpaceClick(ImageView availableSpace, int x, int y){ /** * Updates the player's data after a card has been placed. - * + * @implSpec GUI-NON-CORE * @param playerNickname the nickname of the player * @param cardID the ID of the card placed in the field * @param x the x coordinate of the card placed in the field @@ -2100,7 +2242,7 @@ public void updateAfterPlacedCard(String playerNickname, int cardID, int x, int /** * Handles changes in the state of the game. - * + * @implSpec GUI-CORE * @param event the event to handle * @param message the message to display */ @@ -2119,6 +2261,10 @@ public void handleEvent(Event event, String message) { } case Event.GAME_START -> Platform.runLater(()-> notice.getChildren().add(new Label("> The game starts now!\n"))); case Event.GAME_JOINED -> { + if(attemptingReconnection) { + resetSelectionPaneContext(); + attemptingReconnection = false; + } selectionPane.getChildren().removeLast(); waitingRoot = new StackPane(); this.players.add(thisPlayerNickname); @@ -2169,7 +2315,7 @@ public void handleEvent(Event event, String message) { /** * Used to convert the integer representation of the colour to the string representation. - * + * @implSpec GUI-NON-CORE * @param colour the integer representation of the colour * @return the string representation of the colour */ @@ -2200,6 +2346,7 @@ public String convertToColour(int colour) { /** * Generates the selection area for the initial card side selection. * The selection area is composed of a prompt label, 2 cards to choose from. + * @implSpec GUI-NON-CORE * @param imageNumber the number of the image to load. * @return a VBox containing the selection area for the initial card side selection. */ @@ -2269,6 +2416,7 @@ public VBox setupInitialCardSideSelectionArea(int imageNumber) { /** * Generates the selection area for the secret objective card selection. * The selection area is composed of a prompt label, 2 cards to choose from. + * @implSpec GUI-NON-CORE * @param card1 the ID of the first card * @param card2 the ID of the second card * @return a VBox containing the selection area for the secret objective card selection @@ -2339,7 +2487,7 @@ public VBox setupSecretObjectiveCardSelectionArea(int card1, int card2) { /** * Used to handle the click action on buttons used to select game size when creating a new game - * + * @implSpec GUI-NON-CORE * @param clickedButton the button that was clicked * @param button1 the first button * @param button3 the third button @@ -2353,17 +2501,187 @@ private void handleButtonClick(Button clickedButton, Button button1, Button butt /** * Getter method. - * + * @implSpec GUI-NON-CORE * @return the nickname of the player */ public String getThisPlayerNickname() { return thisPlayerNickname; } - // TODO implementare metodo - public void nodeDisconnected(){} + // <-- Method and flags needed for automatic reconnection --> + + /** + * DialogPane displayed when the network is down. + * It is used to notify the user that the connection with the server is lost. + */ + private DialogPane networkIsDown; + /** + * Flag used to state if the node is disconnected from the server. + */ + private volatile boolean isDisconnected = false; + /** + * Flag used to state if the node is attempting to reconnect to the server. + */ + private volatile boolean attemptingReconnection = false; + + /** + * Method called when the node disconnects from the game. + * Called from the Network to notify the View that the connection to the server is lost. + */ + public void nodeDisconnected(){ + // Set isDisconnected flag to true + isDisconnected = true; + + // Flush the askListener + askListener.flushMessages(); + + // Configure the dialog pane networkIsDown to let the user know that the connection is down + // Run this in the JavaFX thread to be able to interact with the GUI + Platform.runLater(() -> { + networkIsDown = new DialogPane(); + networkIsDown.setStyle("-fx-pref-height: 180px;-fx-pref-width: 600px;-fx-background-image: " + + "url('" + retrieveResourceURI("NoticeDisplay.png") + "');-fx-background-position: center;-fx-background-size: 600px 180px;"); + Label label1 = new Label("The connection with the server is lost.\nAn attempt to reconnect will be made shortly."); + label1.setStyle("-fx-text-fill: #3A2111;-fx-alignment: center; -fx-font-size: 15px;-fx-font-family: 'JejuHallasan';"); + networkIsDown.setContent(label1); + + networkIsDown.setMinHeight(180); + networkIsDown.setMinWidth(600); + networkIsDown.setMaxHeight(180); + networkIsDown.setMaxWidth(600); + + // Show now the dialogPane networkIsDown + app.updateScene(networkIsDown, 600, 180); + app.getPrimaryStage().setMinWidth(600); + app.getPrimaryStage().setMaxWidth(600); + app.getPrimaryStage().setMinHeight(180); + app.getPrimaryStage().setMaxHeight(180); + app.getPrimaryStage().show(); + }); + } + + /** + * Method called when the node reconnects to the game. + * Called from the Network to notify the View that the connection to the server is restored. + */ + public void nodeReconnected(){ + // Set isDisconnected flag to false + isDisconnected = false; + + // Set attemptingReconnection flag to true + attemptingReconnection = true; + + // Flush the askListener + askListener.flushMessages(); + + // Configure the dialog pane networkIsDown to let the user know that the connection is now restored + // Run this in the JavaFX thread to be able to interact with the GUI + Platform.runLater(() -> { + networkIsDown = new DialogPane(); + networkIsDown.setStyle("-fx-pref-height: 180px;-fx-pref-width: 600px;-fx-background-image: " + + "url('" + retrieveResourceURI("NoticeDisplay.png") + "');-fx-background-position: center;-fx-background-size: 600px 180px;"); + Label label1 = new Label("The connection with the server is restored.\nThe system is going to try to rejoin the match."); + label1.setStyle("-fx-text-fill: #3A2111;-fx-alignment: center; -fx-font-size: 15px;-fx-font-family: 'JejuHallasan';"); + networkIsDown.setContent(label1); + + networkIsDown.setMinHeight(180); + networkIsDown.setMinWidth(600); + networkIsDown.setMaxHeight(180); + networkIsDown.setMaxWidth(600); + + // Show now the dialogPane networkIsDown + app.updateScene(networkIsDown, 600, 180); + app.getPrimaryStage().setMinWidth(600); + app.getPrimaryStage().setMaxWidth(600); + app.getPrimaryStage().setMinHeight(180); + app.getPrimaryStage().setMaxHeight(180); + app.getPrimaryStage().show(); + }); + + // Try to rejoin the match itself (do this in an ephemeral thread to avoid blocking the Network thread) + Thread ephemeralThread = new Thread(() -> { + // Sleep for 1.5s to let the user see the message + try { + Thread.sleep(1500); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + // Attempt the reconnection to the match itself + if(Status.equals(Event.WELCOME)) { + switch (currentEvent) { + case Event.CREATE_GAME -> { + askCreateGame(); + } + case Event.JOIN_GAME -> { + // If we know the gameID we can attempt to reconnect to that game. + if(gameID != 0 && !thisPlayerNickname.isEmpty()) { + currentEvent = Event.JOIN_GAME; + notifyAskListener(new AccessGameMessage(gameID, thisPlayerNickname)); + // When an answer is received, the processMessage will handle the reconnection and the GUI will be updated accordingly. + // The flag attemptingReconnection will be set to false in the processMessage method. + } else { + askJoinGame(); + } + } + case Event.RECONNECT_GAME -> { + // If we know the gameID we can attempt to reconnect to that game. + if(gameID != 0 && !thisPlayerNickname.isEmpty()) { + currentEvent = Event.RECONNECT_GAME; + notifyAskListener(new ReconnectGameMessage(thisPlayerNickname, gameID)); + // When an answer is received, the processMessage will handle the reconnection and the GUI will be updated accordingly. + // The flag attemptingReconnection will be set to false in the processMessage method. + } else { + askReconnectGame(); + } + } + default -> { + askSelectGameMode(); + } + } + } else if (Status.equals(Event.LOBBY)) { + // If we were in the lobby, we can attempt to reconnect to that lobby. + currentEvent = Event.JOIN_GAME; + notifyAskListener(new AccessGameMessage(gameID, thisPlayerNickname)); + // When an answer is received, the processMessage will handle the reconnection and the GUI will be updated accordingly. + // The flag attemptingReconnection will be set to false in the processMessage method. + } else { + // If we were in the game, we can attempt to reconnect to that game. + currentEvent = Event.RECONNECT_GAME; + notifyAskListener(new ReconnectGameMessage(thisPlayerNickname, gameID)); + // When an answer is received, the processMessage will handle the reconnection and the GUI will be updated accordingly. + // The flag attemptingReconnection will be set to false in the processMessage method. + } + }); + + ephemeralThread.start(); + } + + /** + * Method called when needing to reset the selectionPane context. + */ + private void resetSelectionPaneContext() { + // Re-initialize the selectionPane + selectionPane = new StackPane(); + + // Set the background image of the selectionPane + Image backgroundSelectionPage = new Image(retrieveResourceURI("SelectionDisplay.png")); + BackgroundImage backgroundImg = new BackgroundImage(backgroundSelectionPage, BackgroundRepeat.NO_REPEAT, + BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, new BackgroundSize(975, 925, false, false, false, false)); + Background background = new Background(backgroundImg); + selectionPane.setBackground(background); + + // Add a dummy pane as a children of the selectionPane + Pane dummyPane = new Pane(); + selectionPane.getChildren().add(dummyPane); - // TODO implementare metodo - public void nodeReconnected(){} + // Show the selectionPane on the GUI + selectionPane.setMinWidth(975); + app.updateScene(selectionPane,975,750); + app.getPrimaryStage().setMinWidth(975); + app.getPrimaryStage().setMinHeight(750); + app.getPrimaryStage().setMaxWidth(975); + app.getPrimaryStage().setMaxHeight(750); + } } diff --git a/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUIApplication.java b/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUIApplication.java index 814552d5..4bda6347 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUIApplication.java +++ b/src/main/java/it/polimi/ingsw/am32/client/view/gui/GraphicalUIApplication.java @@ -4,9 +4,12 @@ import javafx.application.Platform; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.image.Image; import javafx.stage.Stage; import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Objects; /** * The GraphicalUIApplication class extends the Application class from JavaFX. It interacts with the GraphicalUI @@ -21,6 +24,7 @@ public class GraphicalUIApplication extends Application { * The primary stage of the application */ private Stage primaryStage; + /** * The constructor of the class */ @@ -39,8 +43,19 @@ public GraphicalUIApplication(){ @Override public void start(Stage primaryStage) throws IOException { this.primaryStage = primaryStage; - // set the title, the minimum height and width and the scene + // set the title of the application primaryStage.setTitle("Codex Naturalis"); + // set the icon of the application + String iconPath; + try { + iconPath = Objects.requireNonNull(GraphicalUI.class.getResource("codexNaturalis.png")).toURI().toString(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + Image icon = new Image(iconPath); + primaryStage.getIcons().add(icon); + + // set the minimum height and width and the beginning scene of the application primaryStage.setMinHeight(750); primaryStage.setMinWidth(975); primaryStage.setScene(new Scene(graphicalUI.getWelcomeRoot(), 975, 750)); @@ -70,6 +85,7 @@ public void updateScene(Parent parent,int x,int y) { protected Stage getPrimaryStage() { return primaryStage; } + /** * Launches the application with the given arguments * @param args the arguments to be passed to the application @@ -77,4 +93,4 @@ protected Stage getPrimaryStage() { public static void main(String[] args) { launch(args); } -} \ No newline at end of file +} diff --git a/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java b/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java index 6aaeb4c0..336bc275 100644 --- a/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java +++ b/src/main/java/it/polimi/ingsw/am32/client/view/tui/TextUI.java @@ -1,6 +1,7 @@ package it.polimi.ingsw.am32.client.view.tui; import it.polimi.ingsw.am32.network.exceptions.ConnectionSetupFailedException; +import it.polimi.ingsw.am32.utilities.IPAddressFinder; import it.polimi.ingsw.am32.utilities.IsValid; import it.polimi.ingsw.am32.client.*; import it.polimi.ingsw.am32.message.ClientToServer.*; @@ -164,6 +165,19 @@ public class TextUI extends View{ * The thread used to read the input of the player when it is not the player's turn */ private Thread service; + /** + * An object used as a lock for the shared getInput() method + */ + private final Object lockInput = new Object(); + + /** + * A boolean that represents if the TUI is disconnected from the server. + */ + private volatile boolean isDisconnected = false; + /** + * A boolean that represents if the TUI can be reconnected to the server. + */ + private volatile boolean canAttemptReconnection = false; /** * Constructor of the class TextUI @@ -190,6 +204,13 @@ public void launch() { boolean isEnd = false; while (!isEnd) { // TODO think about a better way to handle the flow of the game + + while(isDisconnected) { + if(canAttemptReconnection) { + askIfWantToReconnect(); + } + } + switch (Status) { case WELCOME -> { switch (currentEvent) { @@ -294,7 +315,11 @@ public void chooseConnection() { port = getInputInt(); // Ask the player to re-enter the port number } + String localIP = askForLocalIPAddress(); // Ask the player to choose the correct IPv4 address + try { + System.setProperty("java.rmi.server.hostname", localIP); // Workaround for RMI + out.println("Set RMI localIP to " + localIP); setRMIClient(serverIP, port); // Set the RMI client isConnected = true; // Set the connection status to true } catch (ConnectionSetupFailedException e) { @@ -317,6 +342,33 @@ public void chooseConnection() { } while (!isConnected); // Keep looping until the connection is established } + /** + * Method used to ask the player the correct IP address associated with the current machine. + * If the list of IPv4 addresses is empty, the method will return "127.0.0.1" aka localhost. + * @return The correct IPv4 address associated with the current machine + */ + private String askForLocalIPAddress() { + // We are going to use IPAddressFinder.getIPv4Addresses() to get the list of IPv4 addresses associated with the current machine + List ipv4Addresses = IPAddressFinder.getIPv4Addresses(); + // If the list is empty, we will return localhost aka "127.0.0.1" + if (ipv4Addresses.isEmpty()) { + return "127.0.0.1"; + } + // If the list is not empty, we will ask the user to choose one of the IPv4 addresses + out.println("Choose the correct IPv4 address associated with the current machine:"); + for (int i = 0; i < ipv4Addresses.size(); i++) { + out.println((i + 1) + ". " + ipv4Addresses.get(i)); + } + int choice = getInputInt(); + // We will keep asking the user to choose a valid number until they do so + while (choice < 1 || choice > ipv4Addresses.size()) { + out.println("Invalid choice, please select a number between 1 and " + ipv4Addresses.size()); + choice = getInputInt(); + } + // We will return the chosen IPv4 address + return ipv4Addresses.get(choice - 1); + } + /** * Method that sets the socket client with the server IP and the server port entered by the player and attempts to * establish the connection between the client and the server. @@ -365,6 +417,7 @@ public void showWelcome() { /** * The method prints the menu of the game mode and asks the player to select the action to perform. The player can * create a new game, join a game with the game ID, or reconnect to a game. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ @Override public void askSelectGameMode() { @@ -397,6 +450,7 @@ public void askSelectGameMode() { /** * Method that asks the player to insert the nickname they want to use in the game. * Nickname limited to 20 characters. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ private void askNickname() { while (true) { @@ -418,6 +472,7 @@ else if (thisPlayerNickname.length() > 20) { /** * Method that asks the player to insert the number of players and the nickname desired to create a new game. * Then notify the listener with the NewGameMessage. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ @Override public void askCreateGame() { @@ -437,12 +492,15 @@ public void askCreateGame() { } // Notify the listener with the new game message - notifyAskListener(new NewGameMessage(thisPlayerNickname, playerNum)); + if(!isDisconnected) { + notifyAskListener(new NewGameMessage(thisPlayerNickname, playerNum)); + } } /** * Method that asks the player to insert the nickname they want to use in the game and the Access ID of the game * they want to join. Then notify the listener with the AccessGameMessage. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ @Override public void askJoinGame() { @@ -454,12 +512,15 @@ public void askJoinGame() { gameID = getInputInt(); // notify the listener with the access game message - notifyAskListener(new AccessGameMessage(gameID, thisPlayerNickname)); + if(!isDisconnected) { + notifyAskListener(new AccessGameMessage(gameID, thisPlayerNickname)); + } } /** * Use this method to ask the player if they want to reconnect to the game. Then notify the listener with the * ReconnectGameMessage. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ @Override public void askReconnectGame() { @@ -468,7 +529,9 @@ public void askReconnectGame() { out.println("Insert the game ID you want to reconnect to:"); gameID = getInputInt(); // notify the listener with the reconnect game message - notifyAskListener(new ReconnectGameMessage(thisPlayerNickname,gameID)); + if(!isDisconnected) { + notifyAskListener(new ReconnectGameMessage(thisPlayerNickname, gameID)); + } } /** @@ -596,6 +659,7 @@ public void updateMatchStatus(int matchStatus) { * Once the player receives the AssignedStarterCardMessage from the server, the method is called by processMessage * to request the player to select the side of the starter card they want to use. The player will be able to see * the front and back side of the card and select the side they want to use. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT * @param ID the ID of the starter card received from the server and assigned to the player. */ @Override @@ -612,7 +676,9 @@ public void requestSelectStarterCardSide(int ID) { side = in.nextLine(); } // If we get to this point, the player has written either FRONT or BACK - notifyAskListener(new SelectedStarterCardSideMessage(thisPlayerNickname, side.equals("FRONT"))); + if(!isDisconnected) { + notifyAskListener(new SelectedStarterCardSideMessage(thisPlayerNickname, side.equals("FRONT"))); + } out.println("Please wait for the other players to select the side of the starter card"); currentEvent = Event.SELECTED_STARTER_CARD_SIDE; } @@ -684,6 +750,7 @@ public void setStarterCard(int cardId) { * When the current event is SELECT_SECRET_OBJ_CARD, the method is called to request the player to select the secret * objective card they want to use. The player will be able to see the two secret objective cards received from the * server and select the card they want to use. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ @Override public void requestSelectSecretObjectiveCard() { @@ -698,7 +765,9 @@ public void requestSelectSecretObjectiveCard() { } // notify the listener with the selected secret objective card message - notifyAskListener(new SelectedSecretObjectiveCardMessage(thisPlayerNickname,cardID.equals("LEFT") ? secretObjCards.get(0) : secretObjCards.get(1))); + if(!isDisconnected) { + notifyAskListener(new SelectedSecretObjectiveCardMessage(thisPlayerNickname,cardID.equals("LEFT") ? secretObjCards.get(0) : secretObjCards.get(1))); + } out.println("Please wait for the other players to select the secret objective card"); currentEvent = Event.SELECTED_SECRET_OBJ_CARD; } @@ -782,13 +851,14 @@ public void updatePlayerData(ArrayList playerNicknames, ArrayList playerNicknames, ArrayList { - while (true) { + while (!Thread.currentThread().isInterrupted()) { synchronized (lock) { while (isMyTurn) { try { @@ -958,6 +1034,7 @@ public void readInputThread() { * Use this method to request the player to place a card in the field. The player will be able to see the board * before and after placing the card. Also, the player will be able to see the cards in the hand and select one * card to place in the field. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ @Override public void requestPlaceCard() { @@ -1016,8 +1093,10 @@ public void requestPlaceCard() { pos = getInput(); } String [] posArray = pos.split(","); - notifyAskListener(new PlaceCardMessage(thisPlayerNickname, hand.get(indexCardPlaced),Integer.parseInt(posArray[0]), - Integer.parseInt(posArray[1]), isUp.equals("FRONT"))); + if(!isDisconnected) { + notifyAskListener(new PlaceCardMessage(thisPlayerNickname, hand.get(indexCardPlaced),Integer.parseInt(posArray[0]), + Integer.parseInt(posArray[1]), isUp.equals("FRONT"))); + } currentEvent = Event.CARD_PLACED; } @@ -1056,6 +1135,7 @@ public void updatePlacedCardConfirm(String playerNickname, int placedCard, int[] * Once the player receives the DrawCardMessage from the server, the method is called by processMessage to request * the player to draw a card from the deck. The player will be able to see the current visible resource cards and * gold cards in the game and select one card to add to the hand. + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ @Override public void requestDrawCard() { @@ -1078,15 +1158,15 @@ public void requestDrawCard() { choice = getInput(); } // based on the choice of the player, edit the message to send to the server. - if (choice.equals("R1") || choice.equals("R2")) { + if ((choice.equals("R1") || choice.equals("R2")) && !isDisconnected) { notifyAskListener(new DrawCardMessage(thisPlayerNickname, 2, choice.equals("R1") ? currentResourceCards.get(0) : currentResourceCards.get(1))); out.println(currentResourceCards.get(0)+currentResourceCards.get(1)); - } else if (choice.equals("G1") || choice.equals("G2")) { + } else if ((choice.equals("G1") || choice.equals("G2")) && !isDisconnected) { notifyAskListener(new DrawCardMessage(thisPlayerNickname, 3, choice.equals("G1") ? currentGoldCards.get(0) : currentGoldCards.get(1))); out.println(currentGoldCards.get(0)+currentGoldCards.get(1)); - } else { + } else if(!isDisconnected){ notifyAskListener(new DrawCardMessage(thisPlayerNickname, choice.equals("R") ? 0 : 1, -1)); } currentEvent = Event.CARD_DRAWN; @@ -1266,7 +1346,7 @@ public void updateDeck(int resourceDeckSize, int goldDeckSize, int[]currentResou * Method called when player opens chat from getInput method. * Enables the user to select a player to chat with, or chat with all players. * The user can also exit the chat. - * @implSpec BLOCKING-BUT-RAN-FROM-RIT + * @implSpec BLOCKING, NON-ALTER-STATUS, FREE-OF-SIDE-EFFECT */ @Override public void startChatting() { @@ -1331,11 +1411,15 @@ else if (messageContent.equals("EXIT")) { // Abort sending message if (recipient.equals("ALL")) { // Send a message in broadcast ChatMessage message = new ChatMessage(thisPlayerNickname, "ALL", true, messageContent); chatHistory.add(message); // FIXME Is this needed? RESOLVED: Yes, it is needed, because in the chat history, the player should be able to see the messages that he sent. - notifyAskListener(new InboundChatMessage(thisPlayerNickname, recipient, true, messageContent)); + if(!isDisconnected) { + notifyAskListener(new InboundChatMessage(thisPlayerNickname, recipient, true, messageContent)); + } } else { // Send a direct message ChatMessage message = new ChatMessage(thisPlayerNickname, recipient, false, messageContent); chatHistory.add(message); // FIXME Is this needed? RESOLVED: Yes, it is needed, because in the chat history, the player should be able to see the messages that he sent. - notifyAskListener(new InboundChatMessage(thisPlayerNickname, recipient, false, messageContent)); + if(!isDisconnected) { + notifyAskListener(new InboundChatMessage(thisPlayerNickname, recipient, false, messageContent)); + } } // Loop back up and ask user to insert another chat message @@ -1950,36 +2034,54 @@ private void updateBoardViewLimits(int posX, int posY, int[] limits) { */ @Override public void handleFailureCase(Event event, String reason){ + // Deals with the failure messages received from the server and asks the user to try again. switch (event){ - case CREATE_GAME-> { // Should never happen! + case CREATE_GAME-> { + // Technically, this should never happen as there are no reasons for the game creation to fail. + // However, if it does, the player should be redirected to the askCreateGame() method. + // Implemented to keep the code consistent. out.println("Please try again! Reason: " + reason); + Status = Event.WELCOME; currentEvent = Event.CREATE_GAME_FAILURE; } case JOIN_GAME-> { + // If the join game fails because the game is already started, the player should be redirected + // to the askReconnect() method instead of the askJoinGame() method. This check is done in the + // ErrorMessage class itself in order to avoid code duplication and to not alter the current method. out.println("Please try again! Reason: " + reason); + Status = Event.WELCOME; currentEvent = Event.JOIN_GAME_FAILURE; } case RECONNECT_GAME -> { + // If the reconnection fails, the player should be redirected to the askReconnect() method. out.println("Please try again! Reason: " + reason); + Status = Event.WELCOME; currentEvent = Event.RECONNECT_GAME_FAILURE; } case PLACE_CARD_FAILURE -> { + // If the card placement fails, the player should be redirected to the askPlaceCard() method. out.println("Please try again! Reason: " + reason); currentEvent = Event.PLACE_CARD; } case DRAW_CARD_FAILURE -> { + // If the card drawing fails, the player should be redirected to the askDrawCard() method. out.println("Please try again! Reason: " + reason); currentEvent = Event.DRAW_CARD; } case SELECT_SECRET_OBJ_CARD_FAILURE -> { + // If the selection of the secret objective card fails, the player should be redirected to the + // askSelectSecretObjCard() method. out.println("Please try again! Reason: " + reason); currentEvent = Event.SELECTED_SECRET_OBJ_CARD; } case SELECT_STARTER_CARD_SIDE_FAILURE -> { + // If the selection of the side of the starter card fails, the player should be redirected to the + // askSelectStarterCardSide() method. out.println("Please try again! Reason: " + reason); currentEvent = Event.SELECT_STARTER_CARD_SIDE; } case CHAT_ERROR -> { + // If the last message was not sent, add a notice to the chat history and print the reason. out.println("The last message was not sent! Reason: " + reason); ChatMessage error = new ChatMessage("NOTICE", thisPlayerNickname, false,"The last message was not sent! " + reason); chatHistory.add(error); @@ -2024,13 +2126,15 @@ public void handleEvent(Event event,String nickname) { /** * The Method used to get the input from the user and handle the commands that the user can use to interact with the * game in the service mode. + * @implSpec BLOCKING, NON-ALTER-STATUS, NO-SIDE-EFFECT * @return the input from the user. */ - private synchronized String getInput() { - String input = ""; - if (!Status.equals(Event.TERMINATED)) { - input= in.nextLine(); - } + private String getInput() { + synchronized (lockInput) { + String input = ""; + if (!Status.equals(Event.TERMINATED)) { + input= in.nextLine(); + } switch (input) { case "HELP" -> showHelpInfo(); case "QUIT" -> System.exit(0); @@ -2055,13 +2159,14 @@ private synchronized String getInput() { case "SID" -> out.println("The game ID is: " + gameID); case "SCD" -> showDeck(); } - return input; + return input; + } } /** * Loops until the user enters a valid single integer. * Inputs such as “string 5,” “4 string,” “string” are all invalid. - * + * @implSpec BLOCKING, NON-ALTER-STATUS, NO-SIDE-EFFECT * @return Integer input from the user */ private int getInputInt() { @@ -2085,9 +2190,87 @@ private int getInputInt() { } } - // TODO implementare metodo - public void nodeDisconnected(){} + /** + * Method called by the Network to notify that the Client has lost connection with the Server. + * @implSpec NON-BLOCKING, NO-SIDE-EFFECT, NON-ALTER-STATUS + */ + public void nodeDisconnected(){ + if(service != null) { service.interrupt(); } + + out.println("The connection with the server is lost, an attempt to reconnect will be made shortly."); + askListener.flushMessages(); + isDisconnected = true; + canAttemptReconnection = false; + } + + /** + * Method called by the Network to notify that the Client has reconnected with the Server. + * @implSpec NON-BLOCKING, NO-SIDE-EFFECT, NON-ALTER-STATUS + */ + public void nodeReconnected(){ + if(service != null) { service.interrupt(); } + + canAttemptReconnection = true; + isDisconnected = true; + askListener.flushMessages(); + out.println("The connection with the server is restored. Please perform the last action (it will have no effect) to continue."); + } + + /** + * Method to use to return the TUI in a state where the user can attempt to reconnect to the match. + * @implSpec NON-BLOCKING, NO-SIDE-EFFECT, NON-ALTER-STATUS + */ + private void askIfWantToReconnect() { + // If the readInputThread is running stop it to avoid conflicts. + if(service != null) { service.interrupt(); } + + // Reset the flags and the status of the TUI + canAttemptReconnection = false; + isDisconnected = false; + + out.println("The system is attempting to reconnect to the match itself."); - // TODO implementare metodo - public void nodeReconnected(){} -} + // Based on the current status of the TUI we need to decide what to do next. + if(Status.equals(Event.WELCOME)) { + switch(currentEvent) { + case Event.CREATE_GAME -> { + currentEvent = Event.CREATE_GAME_FAILURE; + // If we are here we don't even know which game to join/reconnect. + // It will handled by the launch() loop. + } + case Event.JOIN_GAME -> { + // If we know the gameID we can attempt to reconnect to that lobby. + if(gameID != 0 && !thisPlayerNickname.isEmpty()) { + currentEvent = Event.JOIN_GAME; + notifyAskListener(new AccessGameMessage(gameID, thisPlayerNickname)); + } else { + currentEvent = Event.JOIN_GAME_FAILURE; + // If we don't know the gameID we can't reconnect to the lobby. + // It will handled by the launch() loop. + } + } + case Event.RECONNECT_GAME -> { + // If we know the gameID we can attempt to reconnect to that game. + if(gameID != 0 && !thisPlayerNickname.isEmpty()) { + currentEvent = Event.RECONNECT_GAME; + notifyAskListener(new ReconnectGameMessage(thisPlayerNickname, gameID)); + } else { + currentEvent = Event.RECONNECT_GAME_FAILURE; + // If we don't know the gameID we can't reconnect to the game. + // It will handled by the launch() loop. + } + } + } + } else if (Status.equals(Event.LOBBY)) { + // If we were in the lobby, we can attempt to reconnect to that lobby. + currentEvent = Event.JOIN_GAME; + notifyAskListener(new AccessGameMessage(gameID, thisPlayerNickname)); + // If this fails the TUI will be put again in askJoinGame() where the user can try again. + } else { + // If we were in the game, we can attempt to reconnect to that game. + currentEvent = Event.RECONNECT_GAME; + notifyAskListener(new ReconnectGameMessage(thisPlayerNickname,gameID)); + // If this fails the TUI will be put again in askReconnectGame() where the user can try again. + } + } + } diff --git a/src/main/java/it/polimi/ingsw/am32/controller/GameControllerStatus.java b/src/main/java/it/polimi/ingsw/am32/controller/GameControllerStatus.java index 5d1412e1..bb30cc1b 100644 --- a/src/main/java/it/polimi/ingsw/am32/controller/GameControllerStatus.java +++ b/src/main/java/it/polimi/ingsw/am32/controller/GameControllerStatus.java @@ -6,17 +6,29 @@ * @author Anto */ public enum GameControllerStatus { - // The game controller is in the lobby state, waiting for players to join. + /** + * The game controller is in the lobby state, waiting for players to join. + */ LOBBY(0), - // The game controller is waiting for all cards to make a selection for the starter card side. + /** + * The game controller is waiting for all cards to make a selection for the starter card side. + */ WAITING_STARTER_CARD_CHOICE(1), - // The game controller is waiting for all players to make a selection for the secret objective card. + /** + * The game controller is waiting for all players to make a selection for the secret objective card. + */ WAITING_SECRET_OBJECTIVE_CARD_CHOICE(2), - // The game controller is waiting for the current player to place a card on the board. + /** + * The game controller is waiting for the current player to place a card on the board. + */ WAITING_CARD_PLACEMENT(3), - // The game controller is waiting for the current player to draw a card from the deck. + /** + * The game controller is waiting for the current player to draw a card from the deck. + */ WAITING_CARD_DRAW(4), - // The game controller is in the ended state, meaning that the game has ended. + /** + * The game controller is in the ended state, meaning that the game has ended. + */ GAME_ENDED(5); /** diff --git a/src/main/java/it/polimi/ingsw/am32/controller/exceptions/abstraction/LobbyMessageExceptionEnumeration.java b/src/main/java/it/polimi/ingsw/am32/controller/exceptions/abstraction/LobbyMessageExceptionEnumeration.java index 06ab0e79..fdf003ab 100644 --- a/src/main/java/it/polimi/ingsw/am32/controller/exceptions/abstraction/LobbyMessageExceptionEnumeration.java +++ b/src/main/java/it/polimi/ingsw/am32/controller/exceptions/abstraction/LobbyMessageExceptionEnumeration.java @@ -7,14 +7,41 @@ * @value The integer value associated with each exception. */ public enum LobbyMessageExceptionEnumeration { + /** + * This exception type indicates that the number of players in a game is invalid. + */ INVALID_PLAYER_NUMBER_EXCEPTION(0), + /** + * This exception type indicates that a game is already started and a player tries to join it. + */ GAME_ALREADY_STARTED_EXCEPTION(1), + /** + * This exception type indicates that a player tries to join a full lobby. + */ FULL_LOBBY_EXCEPTION(2), + /** + * This exception type indicates that a player tries to join a lobby with a nickname that is already in use. + */ DUPLICATE_NICKNAME_EXCEPTION(3), + /** + * This exception type indicates that the game was not found. + */ GAME_NOT_FOUND_EXCEPTION(4), + /** + * This exception type indicates that a game is already ended and a player tries to join it. + */ GAME_ALREADY_ENDED_EXCEPTION(5), + /** + * This exception type indicates that a player tries to join a lobby with a nickname that is already in use. + */ PLAYER_NOT_FOUND_EXCEPTION(6), + /** + * This exception type indicates that a player is already connected but tries to connect again somehow. + */ PLAYER_ALREADY_CONNECTED_EXCEPTION(7), + /** + * This exception type indicates that a player tries to connect to a game that has not yet started. + */ GAME_NOT_YET_STARTED_EXCEPTION(8); /** diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/AccessGameMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/AccessGameMessage.java index d9e3a076..ade09ac5 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/AccessGameMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/AccessGameMessage.java @@ -20,7 +20,11 @@ public class AccessGameMessage implements CtoSLobbyMessage { * The nickname of the player who wants to join the game */ private final String senderNickname; - + /** + * Constructor: a message containing the id of the game and the nickname of the player who wants to join the game + * @param matchId the id of the game the player wants to join + * @param senderNickname the nickname of the player who requests to join the game + */ public AccessGameMessage(int matchId, String senderNickname) { this.matchId = matchId; this.senderNickname = senderNickname; @@ -42,6 +46,13 @@ public GameController elaborateMessage(NodeInterface nodeInterface) throws GameA return GamesManager.getInstance().accessGame(senderNickname, matchId, nodeInterface); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the AccessGameMessage object. The string includes the message type, + * the matchId and the senderNickname properties of the object. + */ @Override public String toString() { return "AccessGameMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/CtoSLobbyMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/CtoSLobbyMessage.java index 5bbef5d3..57ddc636 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/CtoSLobbyMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/CtoSLobbyMessage.java @@ -11,6 +11,19 @@ * It contains a single method to elaborate the message */ public interface CtoSLobbyMessage extends Serializable { + /** + * Elaborates the message associated with the specified nodeInterface. + * @param nodeInterface the serverNode of the player + * @return The game controller that will manage the game + * @throws LobbyMessageException represents an exception that can be thrown during the elaboration of a generic + * Lobby-Message. + */ GameController elaborateMessage(NodeInterface nodeInterface) throws LobbyMessageException; + /** + * This method provides a string representation of a message object, which can be useful for debugging purposes. + * It will be overridden by the classes that implement the StoCMessage interface. + * + * @return A string representation of the CtoSLobbyMessage object. + */ String toString(); // Used for debugging purposes } diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/CtoSMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/CtoSMessage.java index dab4e356..02e04ecd 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/CtoSMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/CtoSMessage.java @@ -15,5 +15,11 @@ public interface CtoSMessage extends Serializable { * @param gameController The game controller with which the message should be elaborated */ void elaborateMessage(GameController gameController); + /** + * This method provides a string representation of a message object, which can be useful for debugging purposes. + * It will be overridden by the classes that implement the StoCMessage interface. + * + * @return A string representation of the CtoSMessage object. + */ String toString(); // Used for debugging purposes } diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/DrawCardMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/DrawCardMessage.java index 3d9fbd52..98265338 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/DrawCardMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/DrawCardMessage.java @@ -19,6 +19,14 @@ public class DrawCardMessage implements CtoSMessage { */ private final int cardId; + /** + * Constructor: a message used to request to draw a card during the player's turn + * @param senderNickname the nickname of the player who drawn the card + * @param deckType the type of deck drawn by player: 0 for resource deck, 1 for gold deck, + * 2 for resource card visible, 3 for gold card visible + * + * @param cardId the id of the card drawn by the player + */ public DrawCardMessage(String senderNickname, int deckType, int cardId) { this.senderNickname = senderNickname; this.deckType = deckType; @@ -35,6 +43,13 @@ public void elaborateMessage(GameController gameController) { gameController.drawCard(senderNickname, deckType, cardId); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the DrawCardMessage object. + * The string includes the message type, the senderNickname, the deckType and the cardId properties of the object. + */ @Override public String toString() { return "DrawCardMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/InboundChatMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/InboundChatMessage.java index b2edb383..be42f111 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/InboundChatMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/InboundChatMessage.java @@ -24,6 +24,17 @@ public class InboundChatMessage implements CtoSMessage { */ private final String content; + /** + * Constructor: a message representing a chat message sent by a player to another player or to all the players in + * the game. + * + * @param senderNickname the nickname of the player who wants to send the message + * @param recipientNickname the nickname of the player who will receive the message + * @param multicastFlag the flag that indicates if the message is for all the players in the game or for a single + * player: true if the message is for all the players, false if the message is for a single + * player + * @param content the content of the message + */ public InboundChatMessage(String senderNickname, String recipientNickname, boolean multicastFlag, String content) { this.senderNickname = senderNickname; this.recipientNickname = recipientNickname; @@ -41,6 +52,14 @@ public void elaborateMessage(GameController gameController) { gameController.submitChatMessage(new ChatMessage(senderNickname, recipientNickname, multicastFlag, content)); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the InboundChatMessage object. + * The string includes the message type, the senderNickname, the recipientNickname, the multicastFlag and the + * content properties of the object. + */ @Override public String toString() { return "InboundChatMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/NewGameMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/NewGameMessage.java index b50c1523..aaeb6543 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/NewGameMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/NewGameMessage.java @@ -42,6 +42,14 @@ public GameController elaborateMessage(NodeInterface nodeInterface) throws Inval return GamesManager.getInstance().createGame(senderNickname, playerNum, nodeInterface); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the NewGameMessage object. + * The string includes the message type, the senderNickname and the playerNum properties of the object. + + */ @Override public String toString() { return "NewGameMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/PingMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/PingMessage.java index 0c33056a..5f9caafd 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/PingMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/PingMessage.java @@ -11,16 +11,30 @@ public class PingMessage implements CtoSMessage { */ private final String senderNickname; + /** + * Constructor: a message representing a ping message sent by a player to the server. + * @param senderNickname the nickname of the player who wants to ping the server + */ public PingMessage(String senderNickname) { this.senderNickname = senderNickname; } - // TODO Need javadoc + /** + * This method is called when a player wants to ping the server. + * @param gameController The game controller with which the message should be elaborated + */ @Override public void elaborateMessage(GameController gameController) { gameController.pongPlayer(senderNickname); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PingMessage object. + * The string includes the message type and the senderNickname properties of the object. + */ @Override public String toString() { return "PingMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/PlaceCardMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/PlaceCardMessage.java index 202939ff..2964ce93 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/PlaceCardMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/PlaceCardMessage.java @@ -27,6 +27,18 @@ public class PlaceCardMessage implements CtoSMessage { */ private final boolean isUp; + /** + * Constructor: a message containing the nickname of the player who wants to place the card, the id of the card the + * player wants to place, the x and y coordinates of the position in the field where the player wants to place the + * card and a flag that indicates if the card is placed face up or face down. + * @param senderNickname the nickname of the player who wants to place the card + * @param cardId the id of the card the player wants to place + * @param row the row of the field where the player wants to place the card + * @param column the colum of the field where the player wants to place the card + * @param isUp indicates if the card is placed face up or face down: + * true if the card is placed face up, false otherwise + */ + public PlaceCardMessage(String senderNickname, int cardId, int row, int column, boolean isUp) { this.senderNickname = senderNickname; this.cardId = cardId; @@ -44,7 +56,14 @@ public PlaceCardMessage(String senderNickname, int cardId, int row, int column, public void elaborateMessage(GameController gameController) { gameController.placeCard(senderNickname, cardId, row, column, isUp); } - + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlaceCardMessage object. + * The string includes the message type, the senderNickname, the cardId, the row, the column and the isUp properties + * of the object. + */ @Override public String toString() { return "PlaceCardMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/ReconnectGameMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/ReconnectGameMessage.java index 1621709d..7896cec3 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/ReconnectGameMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/ReconnectGameMessage.java @@ -4,22 +4,54 @@ import it.polimi.ingsw.am32.controller.GamesManager; import it.polimi.ingsw.am32.controller.exceptions.*; import it.polimi.ingsw.am32.network.ServerNode.NodeInterface; - +/** + * This class is used to manage the message sent by the client when he wants to reconnect to a game. + */ public class ReconnectGameMessage implements CtoSLobbyMessage { + /** + * The nickname of the player who wants to reconnect to the game + */ private final String senderNickname; + /** + * The id of the game the player left before and wants to reconnect to + */ private final int matchId; + /** + * Constructor: a message containing the nickname of the player who wants to reconnect to the game and the id of + * the game the player requests to reconnect to. + * @param senderNickname the nickname of the player who wants to reconnect to the game + * @param matchId the id of the game the player wants to reconnect to + */ public ReconnectGameMessage(String senderNickname, int matchId) { this.senderNickname = senderNickname; this.matchId = matchId; } - + /** + * This method is called when a player wants to reconnect to a game. + * Creates a new GameController and adds the player and updates the data of the player and the game. + * @param nodeInterface the serverNode of the player + * @return the game controller of the game the player wants to join + * @throws GameAlreadyEndedException if the game has already ended + * @throws GameNotFoundException if the game was not found with given id + * @throws PlayerAlreadyConnectedException if the player is already connected to the game + * @throws GameNotYetStartedException if the game has not yet started, in lobby phase + * @throws CTRPlayerNotFoundException if the player was not found with given nickname + * + */ @Override public GameController elaborateMessage(NodeInterface nodeInterface) throws GameAlreadyEndedException, GameNotFoundException, PlayerAlreadyConnectedException, GameNotYetStartedException, CTRPlayerNotFoundException { return GamesManager.getInstance().reconnectToGame(senderNickname, matchId, nodeInterface); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the ReconnectGameMessage object. + * The string includes the message type, the matchId and the senderNickname properties of the object. + */ @Override public String toString() { return "ReconnectGameMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/RequestGameStatusMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/RequestGameStatusMessage.java index b9a620fb..e0d7f11d 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/RequestGameStatusMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/RequestGameStatusMessage.java @@ -11,6 +11,11 @@ public class RequestGameStatusMessage implements CtoSMessage { */ private final String senderNickname; + /** + * Constructor: a message representing a request for the status of the game sent by a player. + * @param senderNickname the nickname of the player who wants to know the status of the game + * + */ public RequestGameStatusMessage(String senderNickname) { this.senderNickname = senderNickname; } @@ -25,6 +30,13 @@ public void elaborateMessage(GameController gameController) { gameController.sendGameStatus(senderNickname); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the RequestGameStatusMessage object. + * The string includes the message type and the senderNickname properties of the object. + */ @Override public String toString() { return "RequestGameStatusMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/RequestPlayerFieldMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/RequestPlayerFieldMessage.java index b35d0de4..7b48aeab 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/RequestPlayerFieldMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/RequestPlayerFieldMessage.java @@ -15,6 +15,12 @@ public class RequestPlayerFieldMessage implements CtoSMessage { */ private final String playerNickname; + /** + * Constructor: a message representing a request for the field of another player sent by a player. + * @param senderNickname the nickname of the player who wants to see the field of another player + * @param playerNickname the nickname of the player whose field the player requests to see + */ + public RequestPlayerFieldMessage(String senderNickname, String playerNickname) { this.senderNickname = senderNickname; this.playerNickname = playerNickname; @@ -30,6 +36,14 @@ public void elaborateMessage(GameController gameController) { gameController.sendPlayerField(senderNickname, playerNickname); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the RequestPlayerFieldMessage object. + * The string includes the message type, the senderNickname and the playerNickname properties of the object. + + */ @Override public String toString() { return "RequestPlayerFieldMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/SelectedSecretObjectiveCardMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/SelectedSecretObjectiveCardMessage.java index 04631d1c..77d80b9a 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/SelectedSecretObjectiveCardMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/SelectedSecretObjectiveCardMessage.java @@ -15,6 +15,12 @@ public class SelectedSecretObjectiveCardMessage implements CtoSMessage { */ private final int cardId; + /** + * Constructor: a message containing the nickname of the player who selected the secret objective card and the id + * of the card selected. + * @param senderNickname the nickname of the player who selected the secret objective card + * @param cardId the id of the secret objective card selected by the player + */ public SelectedSecretObjectiveCardMessage(String senderNickname, int cardId) { this.senderNickname = senderNickname; this.cardId = cardId; @@ -29,6 +35,13 @@ public void elaborateMessage(GameController gameController) { gameController.chooseSecretObjectiveCard(senderNickname, cardId); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the SelectedSecretObjectiveCardMessage object. + * The string includes the message type, the senderNickname and the cardId properties of the object. + */ @Override public String toString() { return "SelectedSecretObjectiveCardMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/SelectedStarterCardSideMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/SelectedStarterCardSideMessage.java index 791669d9..117f4c70 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/SelectedStarterCardSideMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ClientToServer/SelectedStarterCardSideMessage.java @@ -15,6 +15,12 @@ public class SelectedStarterCardSideMessage implements CtoSMessage { */ private final boolean isUp; + /** + * Constructor: a message containing the nickname of the player who selected the side of the starter card and + * the side selected. + * @param senderNickname the nickname of the player who selected the side of the starter card + * @param isUp the side of the starter card selected by the player + */ public SelectedStarterCardSideMessage(String senderNickname, boolean isUp) { this.senderNickname = senderNickname; this.isUp = isUp; @@ -29,6 +35,13 @@ public void elaborateMessage(GameController gameController) { gameController.chooseStarterCardSide(senderNickname, isUp); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the SelectedStarterCardSideMessage object. + * The string includes the message type, the senderNickname and the isUp properties of the object. + */ @Override public String toString() { return "SelectedStarterCardSideMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/AccessGameConfirmMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/AccessGameConfirmMessage.java index 8174ef81..1c7de9a2 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/AccessGameConfirmMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/AccessGameConfirmMessage.java @@ -2,25 +2,52 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; - +/** + * This class is used to manage the message sent by the server to the client to confirm the access to the game. + */ public class AccessGameConfirmMessage implements StoCMessage { + /** + * The nickname of the recipient who requested to access the game before. + */ private final String recipientNickname; + /** + * The constructor of the class: it creates a new AccessGameConfirmMessage with the nickname of the recipient who + * requested to access the game before. + * @param recipientNickname the nickname of the player who will receive the confirmation message for his request + * to access the game and should be updated. + **/ public AccessGameConfirmMessage(String recipientNickname) { this.recipientNickname = recipientNickname; } + /** + * This method is used to process the message to the client when the access to the game is confirmed, + * updating the current event of the game and notifying the player that he joined the game successfully. + * @param view the view of the player who will receive the message. + */ @Override public void processMessage(View view) { view.updateCurrentEvent(Event.GAME_JOINED); view.handleEvent(Event.GAME_JOINED,null); // notify the player that he joined the game successfully. } + /** + * This method is used to get the nickname of the recipient who requested to access the game before. + * @return the nickname of the player who will receive the confirmation message for his request to access the game. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the AccessGameConfirmMessage object. + * It contains the nickname of the recipient who requested to access the game before. + */ @Override public String toString() { return "AccessGameConfirmMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/AssignedSecretObjectiveCardMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/AssignedSecretObjectiveCardMessage.java index c7d45766..304e5f60 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/AssignedSecretObjectiveCardMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/AssignedSecretObjectiveCardMessage.java @@ -5,12 +5,38 @@ import java.util.ArrayList; +/** + * This class is used to manage the message sent by the server to the client to assign the secret objective cards which + * should be chosen by the player, the common objective cards and the cards to the player's hand. + */ public class AssignedSecretObjectiveCardMessage implements StoCMessage { + /** + * The nickname of the recipient who will receive the assignment of the cards. + */ private final String recipientNickname; + /** + * The list of the secret objective cards assigned to the player so that he can choose one of them. + */ private final ArrayList assignedSecretObjectiveCards; + /** + * The list of the common objective cards assigned to the player for this game. + */ private final ArrayList chosenCommonObjectiveCards; + /** + * The list of the cards assigned to the player's hand at the beginning of the game: three cards (two resource cards + * and one god card). + */ private final ArrayList playerHand; + /** + * The constructor of the class: it creates a new AssignedSecretObjectiveCardMessage with the nickname of the + * recipient who will receive the assignment of the cards. + * @param recipientNickname the nickname of the player who will receive the message. + * @param assignedSecretObjectiveCards the list of the secret objective cards assigned to the player so that he can + * choose one of them. + * @param chosenCommonObjectiveCards the list of the common objective cards assigned to the player for this game. + * @param playerHand the list of the cards assigned to the player's hand at the beginning of the game. + */ public AssignedSecretObjectiveCardMessage(String recipientNickname, ArrayList assignedSecretObjectiveCards, ArrayList chosenCommonObjectiveCards, ArrayList playerHand) { this.recipientNickname = recipientNickname; @@ -19,17 +45,32 @@ public AssignedSecretObjectiveCardMessage(String recipientNickname, ArrayList availableSpaces; + /** + * The resources of the player in the field after the placement of the starter card. + */ private final int[] playerResources; + /** + * The color identifier of the player in this game. + */ private final int playerColour; + /** + * The constructor of the class: it creates a new confirmStarterCardSideSelectionMessage with the nickname of the + * recipient who will receive the confirmation message for the selection of the starter card side, the id of the + * starter card, the side of the starter card, the available spaces and the resources of the player in the field + * after the placement of the starter card and the color identifier of the player in this game. + * @param recipientNickname who will receive the confirmation message for the selection of the starter card side. + * @param startingCardId the id of the starter card assigned to the player. + * @param side the side of the starter card selected by the player. + * @param availableSpaces the available spaces after the placement of the starter card. + * @param playerResources the resources of the player in the field after the placement of the starter card. + * @param playerColour the color identifier of the player in this game. + */ public ConfirmStarterCardSideSelectionMessage(String recipientNickname, int startingCardId, boolean side, ArrayList availableSpaces, int[] playerResources, int playerColour) { @@ -25,15 +60,33 @@ public ConfirmStarterCardSideSelectionMessage(String recipientNickname, int star this.playerColour = playerColour; } + /** + * This method is used to get the nickname of the recipient who will receive the confirmation message for the + * selection of the starter card side. + * @return the nickname of the player who will receive the message. + */ public String getRecipientNickname() { return recipientNickname; } + /** + * This method is used to process the message to the client when the selection of the starter card side is + * confirmed, + * updating the view with the selected side of the starter card, the available spaces and resources + * of the player in the field after the placement of the starter card. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.updateConfirmStarterCard(playerColour,startingCardId,side, availableSpaces, playerResources); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the ConfirmStarterCardSideSelectionMessage object. + */ @Override public String toString() { return "ConfirmStarterCardSideSelectionMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DeckSizeUpdateMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DeckSizeUpdateMessage.java index 45b33572..6a104e87 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DeckSizeUpdateMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DeckSizeUpdateMessage.java @@ -4,15 +4,51 @@ import java.util.Arrays; +/** + * This class is used to manage the message sent by the server to the client to update the deck after one player + * draws a card. + */ public class DeckSizeUpdateMessage implements StoCMessage { + /** + * The nickname of the recipient who will receive the message to update the deck size after the draw card action. + */ private final String recipientNickname; + /** + * The size of the resource card deck after the draw card action. + */ private final int resourceCardDeckSize; + /** + * The resource card deck facing kingdom after the draw card action. + */ private final int resourceCardDeckFacingKingdom; + /** + * The size of the gold card deck after the draw card action. + */ private final int goldCardDeckSize; + /** + * The gold card deck facing kingdom after the draw card action. + */ private final int goldCardDeckFacingKingdom; + /** + * The current resource cards in the deck after the draw card action. + */ private final int[] currentResourceCards; + /** + * The current gold cards in the deck after the draw card action. + */ private final int[] currentGoldCards; + /** + * The constructor of the class: it creates a new DeckSizeUpdateMessage with the nickname of the recipient who will + * receive the message to update the deck after the draw card action. + * @param recipientNickname the nickname of the player who will receive the message. + * @param resourceCardDeckSize the size of the resource card deck after the draw card action. + * @param goldCardDeckSize the size of the gold card deck after the draw card action. + * @param currentResourceCards the current resource card visible after the draw card action. + * @param currentGoldCards the current gold card visible after the draw card action. + * @param resourceCardDeckFacingKingdom the resource card deck facing kingdom after the draw card action. + * @param goldCardDeckFacingKingdom the gold card deck facing kingdom after the draw card action. + */ public DeckSizeUpdateMessage(String recipientNickname, int resourceCardDeckSize, int goldCardDeckSize, int[] currentResourceCards, int[] currentGoldCards, int resourceCardDeckFacingKingdom, int goldCardDeckFacingKingdom) { @@ -25,16 +61,31 @@ public DeckSizeUpdateMessage(String recipientNickname, int resourceCardDeckSize, this.goldCardDeckFacingKingdom = goldCardDeckFacingKingdom; } + /** + * This method is used to process the message to the client when the deck is updated after the draw card action. + * It updates the view with the new deck size and the current cards in the deck. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.updateDeck(resourceCardDeckSize, goldCardDeckSize, currentResourceCards, currentGoldCards,resourceCardDeckFacingKingdom ,goldCardDeckFacingKingdom ); } + /** + * This method is used to get the nickname of the recipient who will receive the message to update the deck. + * @return the nickname of the player who will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the DeckSizeUpdateMessage object. + */ @Override public String toString() { return "DeckSizeUpdateMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DrawCardConfirmationMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DrawCardConfirmationMessage.java index b9f2a0bb..93241a61 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DrawCardConfirmationMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DrawCardConfirmationMessage.java @@ -4,25 +4,56 @@ import java.util.ArrayList; +/** + * This class is used to manage the message sent by the server to the client to confirm the draw card action. + */ public class DrawCardConfirmationMessage implements StoCMessage { + /** + * The nickname of the recipient who will receive the confirmation after he draws a card. + */ private final String recipientNickname; + /** + * The cards in the player's hand after the draw card action. + */ private final ArrayList playerHand; + /** + * The constructor of the class: it creates a new DrawCardConfirmationMessage with the nickname of the recipient who + * will receive the confirmation and the cards in the player's hand after his draw card action. + * @param recipientNickname the nickname of the player who will receive the confirmation message. + * @param playerHand the cards in the player's hand after the draw card action. + */ public DrawCardConfirmationMessage(String recipientNickname, ArrayList playerHand) { this.recipientNickname = recipientNickname; this.playerHand = playerHand; } + /** + * This method is used to process the message to the client when the draw card action is confirmed, updating the + * view with the cards in the player's hand. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.updateAfterDrawCard(playerHand); } + /** + * This method is used to get the nickname of the recipient who will receive the confirmation after he draws a card. + * @return the nickname of the player who will receive the confirmation message. + */ + @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the DrawCardConfirmationMessage object. + */ @Override public String toString() { return "DrawCardConfirmationMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DrawCardFailedMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DrawCardFailedMessage.java index 3134bf6c..84e68aeb 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DrawCardFailedMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/DrawCardFailedMessage.java @@ -3,25 +3,56 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent by the server to the client when his draw card action fails. + */ public class DrawCardFailedMessage implements StoCMessage { + /** + * The nickname of the recipient who will receive the message when his draw card action fails. + */ private final String recipientNickname; + /** + * The reason why the draw card action failed. + */ private final String reason; + /** + * The constructor of the class: it creates a new DrawCardFailedMessage with the nickname of the recipient who will + * receive the message when his draw card action fails and the reason why the draw card action failed. + * @param recipientNickname the nickname of the player who tried to draw a card but failed. + * @param reason the reason why the draw card action failed. + */ public DrawCardFailedMessage(String recipientNickname, String reason) { this.recipientNickname = recipientNickname; this.reason = reason; } + /** + * This method is used to process the message to the client when the draw card action fails, updating the view with + * the reason why the draw card action failed. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.handleFailureCase(Event.DRAW_CARD_FAILURE, reason); } + /** + * This method is used to get the nickname of the recipient who will receive the message when his draw card action + * fails. + * @return the nickname of the player who tried to draw a card but failed. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the DrawCardFailedMessage object. + */ @Override public String toString() { return "DrawCardFailedMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ErrorMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ErrorMessage.java index 2f46f289..0a7729e7 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ErrorMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ErrorMessage.java @@ -1,28 +1,74 @@ package it.polimi.ingsw.am32.message.ServerToClient; +import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; - +import it.polimi.ingsw.am32.controller.exceptions.abstraction.LobbyMessageExceptionEnumeration; +/** + * This class is used to manage the message sent by the server to the client when client's request to access the game, + * to create a new game or to reconnect to a game is not successful. + */ public class ErrorMessage implements StoCMessage{ + /** + * The message that the server sends to the client to notify the failure reason of the request. + */ private final String message; + /** + * The nickname of the recipient who requested to create a new game, to access the game or to reconnect to a game + * before and received the error message. + */ private final String recipientNickname; + /** + * The type of the error message. + */ private final int errorType; + /** + * The constructor of the class. + * @param message the message that the server sends to the client to notify the failure reason of the request. + * @param recipientNickname the nickname of the player who will receive the error message. + * @param errorType the code associated with the error type. + */ public ErrorMessage(String message, String recipientNickname, int errorType) { this.message = message; this.recipientNickname = recipientNickname; this.errorType = errorType; } + /** + * This method is used to process the message to the client when the request to access the game, + * to create a new game or to reconnect to a game is not successful, + * updating the current event of the game and notifying the player + * that the request is not successful. + * @param view the view of the player who will receive the message about the failure of his request and + * should be updated. + */ @Override public void processMessage(View view) { + // If the View is in the LOBBY state (or WELCOME state with JOIN_GAME as currentEvent) and the error is a + // GAME_ALREADY_STARTED_EXCEPTION, we are going to put the View, again, in the WELCOME state with + // RECONNECT_GAME as currentEvent to let the user choose if he wants to reconnect to the game. + if(errorType == LobbyMessageExceptionEnumeration.GAME_ALREADY_STARTED_EXCEPTION.getValue() && + view.getEvent() == Event.JOIN_GAME) { + view.updateCurrentEvent(Event.RECONNECT_GAME); + } view.handleFailureCase(view.getEvent(), message); } + /** + * This method is used to get the recipient's nickname of the error message. + * @return the nickname of the player who will receive the error message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the ErrorMessage object. + */ @Override public String toString() { return "ErrorMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/GameStartedMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/GameStartedMessage.java index a0357b86..cc252168 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/GameStartedMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/GameStartedMessage.java @@ -3,13 +3,33 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent by the server to the client to notify the player that the game is + * started, entering the preparation phase. + */ + public class GameStartedMessage implements StoCMessage { + /** + * The nickname of the recipient who will receive the message when the game enters the preparation phase. + */ private final String recipientNickname; + /** + * The constructor of the class: it creates a new GameStartedMessage with the nickname of the recipient who will + * receive the message when the game enters the preparation phase. + * @param recipientNickname the nickname of the player who will receive the message. + */ + public GameStartedMessage(String recipientNickname) { this.recipientNickname = recipientNickname; } + /** + * This method is used to process the message to the client when the game is started, updating the view with the + * setup of players' data and notifying the player that the game entered the preparation phase. + * @param view the view of the player who will receive the message and should be updated. + */ + @Override public void processMessage(View view) { view.setUpPlayersData(); @@ -17,11 +37,22 @@ public void processMessage(View view) { view.handleEvent(Event.GAME_START,null); // notify the player that the game is started } + /** + * This method is used to get the nickname of the recipient who will receive the message when the game enters the + * preparation phase. + * @return the nickname of the player who will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the GameStartedMessage object. + */ @Override public String toString() { return "GameStartedMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidInboundChatMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidInboundChatMessage.java index e01ae854..239b4ca0 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidInboundChatMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidInboundChatMessage.java @@ -3,25 +3,53 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent from the server to the player notifying them of an invalid chat message. + */ public class InvalidInboundChatMessage implements StoCMessage { + /** + * The nickname of the sender of the invalid chat message. + */ private final String recipientNickname; + /** + * The reason why the chat message is invalid. + */ private final String reason; + /** + * The constructor of the class. + * @param recipientNickname The nickname of the sender of the invalid chat message. + * @param reason The reason why the chat message is invalid. + */ public InvalidInboundChatMessage(String recipientNickname, String reason) { this.recipientNickname = recipientNickname; this.reason = reason; } + /** + * This method is used to get the nickname of the sender of the invalid chat message. + * @return The nickname of the sender of the invalid chat message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method is used to notify the recipient of the invalid chat message. + * @param view The view of the recipient. + */ @Override public void processMessage(View view) { view.handleFailureCase(Event.CHAT_ERROR,reason); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the InvalidInboundChatMessage object. + */ @Override public String toString() { return "InvalidInboundChatMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidSelectedSecretObjectiveCardMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidSelectedSecretObjectiveCardMessage.java index 3ef66a64..e0aecffa 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidSelectedSecretObjectiveCardMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidSelectedSecretObjectiveCardMessage.java @@ -3,28 +3,60 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent to the client when the selected secret objective card is invalid. + */ public class InvalidSelectedSecretObjectiveCardMessage implements StoCMessage { + /** + * The nickname of the recipient. + */ private final String recipientNickname; + /** + * The reason why the selected secret objective card is invalid. + */ private final String reason; + /** + * The constructor of the class. + * @param recipientNickname the nickname of the recipient. + * @param reason the reason why the selected secret objective card is invalid. + */ public InvalidSelectedSecretObjectiveCardMessage(String recipientNickname, String reason) { this.recipientNickname = recipientNickname; this.reason = reason; } + /** + * Getter method. + * @return the nickname of the recipient. + */ public String getRecipientNickname() { return recipientNickname; } + /** + * Getter method. + * @return the reason why the selected secret objective card is invalid. + */ public String getReason() { return reason; } + /** + * This method is used to manage the message sent to the client when the selected secret objective card is invalid. + * @param view the view that will manage the message. + */ @Override public void processMessage(View view) { view.handleFailureCase(Event.SELECT_SECRET_OBJ_CARD_FAILURE,reason); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the InvalidSelectedSecretObjectiveCardMessage object. + */ @Override public String toString() { return "InvalidSelectedSecretObjectiveCardMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidStarterCardSideSelectionMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidStarterCardSideSelectionMessage.java index 9b6a5cab..02aee87f 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidStarterCardSideSelectionMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/InvalidStarterCardSideSelectionMessage.java @@ -3,28 +3,61 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent to the client notifying them that the side of the starter card they have selected is invalid. + */ public class InvalidStarterCardSideSelectionMessage implements StoCMessage { + /** + * The nickname of the player who has selected the invalid side of the starter card. + */ private final String recipientNickname; + /** + * The reason why the side of the starter card selected is invalid. + */ private final String reason; + /** + * The constructor of the class. + * @param recipientNickname The nickname of the player who has selected the invalid side of the starter card. + * @param reason The reason why the side of the starter card selected is invalid. + */ public InvalidStarterCardSideSelectionMessage(String recipientNickname, String reason) { this.recipientNickname = recipientNickname; this.reason = reason; } + /** + * Getter method. + * @return The nickname of the player who has selected the invalid side of the starter card. + */ public String getRecipientNickname() { return recipientNickname; } + /** + * Getter method. + * @return The reason why the side of the starter card selected is invalid. + */ public String getReason() { return reason; } + /** + * This method is used to manage the message sent to the client notifying them that the side of the starter card they have selected is invalid. + * @param view The view of the client. + */ @Override public void processMessage(View view) { view.handleFailureCase(Event.SELECT_STARTER_CARD_SIDE_FAILURE,reason); } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the InvalidStarterCardSideSelectionMessage object. + + */ @Override public String toString() { return "InvalidStarterCardSideSelectionMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/LobbyPlayerListMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/LobbyPlayerListMessage.java index a037dd72..900a3ae6 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/LobbyPlayerListMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/LobbyPlayerListMessage.java @@ -4,26 +4,53 @@ import java.util.ArrayList; +/** + * This class is used to manage the message send to the players to notify them of the updated list of players in the lobby. + */ public class LobbyPlayerListMessage implements StoCMessage { + /** + * The nickname of the recipient. + */ private final String recipientNickname; + /** + * The list of players in the lobby. + */ private final ArrayList playerList; + /** + * The constructor of the class. + * @param recipientNickname the nickname of the recipient. + * @param playerList the list of players in the lobby. + */ public LobbyPlayerListMessage(String recipientNickname, ArrayList playerList) { this.recipientNickname = recipientNickname; this.playerList = playerList; } + /** + * This method is used to update the player list in the view. + * @param view the view of the player. + */ @Override public void processMessage(View view) { - view.updatePlayerList(playerList); // update the player list in the view } + /** + * This method is used to get the list of players in the lobby. + * @return the list of players in the lobby. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the LobbyPlayerListMessage object. + */ @Override public String toString() { return "LobbyPlayerListMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/MatchStatusMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/MatchStatusMessage.java index 96da50ce..c39efdbd 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/MatchStatusMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/MatchStatusMessage.java @@ -2,25 +2,53 @@ import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message send to the players notifying them of the game status. + */ public class MatchStatusMessage implements StoCMessage { + /** + * The nickname of the player that will receive the message. + */ private final String recipientNickname; + /** + * The status of the match. + */ private final int matchStatus; + /** + * The constructor of the class. + * @param recipientNickname the nickname of the player that will receive the message. + * @param matchStatus the status of the match. + */ public MatchStatusMessage(String recipientNickname, int matchStatus) { this.recipientNickname = recipientNickname; this.matchStatus = matchStatus; } + /** + * This method is used to update the view of the player that will receive the message. + * @param view the view of the player that will receive the message. + */ @Override public void processMessage(View view) { view.updateMatchStatus(matchStatus); } + /** + * This method is used to get the nickname of the player that will receive the message. + * @return the nickname of the player that will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the MatchStatusMessage object. + */ @Override public String toString() { return "MatchStatusMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/MatchWinnersMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/MatchWinnersMessage.java index 84988804..767aa3b4 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/MatchWinnersMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/MatchWinnersMessage.java @@ -4,14 +4,44 @@ import java.util.ArrayList; +/** + * This class is used to manage the message send by the server to the players notifying them the winners of the match. + */ public class MatchWinnersMessage implements StoCMessage { + /** + * The nickname of the player who will receive the message. + */ private final String recipientNickname; + /** + * The list of the players who played the match. + */ private final ArrayList players; + /** + * The list of the points gained by the players. + */ private final ArrayList points; + /** + * The list of the secrets gained by the players. + */ private final ArrayList secrets; + /** + * The list of the points gained by the players from the secrets. + */ private final ArrayList pointsGainedFromSecrets; + /** + * The list of the winners of the match. + */ private final ArrayList winners; + /** + * The constructor of the class. + * @param recipientNickname the nickname of the player who will receive the message. + * @param players the list of the players who played the match. + * @param points the list of the points gained by the players. + * @param secrets the list of the secrets gained by the players. + * @param pointsGainedFromSecrets the list of the points gained by the players from the secrets. + * @param winners the list of the winners of the match. + */ public MatchWinnersMessage(String recipientNickname, ArrayList players, ArrayList points, ArrayList secrets, ArrayList pointsGainedFromSecrets, ArrayList winners) { @@ -23,16 +53,30 @@ public MatchWinnersMessage(String recipientNickname, ArrayList players, this.winners = winners; } + /** + * This method is used to show the message to the player. + * @param view the view of the player. + */ @Override public void processMessage(View view) { view.showMatchWinners(players, points, secrets, pointsGainedFromSecrets, winners); } + /** + * This method is used to get the nickname of the player who will receive the message. + * @return the nickname of the player who will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the MatchWinnersMessage object. + */ @Override public String toString() { return "MatchWinnersMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/NegativeResponsePlayerFieldMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/NegativeResponsePlayerFieldMessage.java index bbd89bba..a2d1ffd0 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/NegativeResponsePlayerFieldMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/NegativeResponsePlayerFieldMessage.java @@ -2,25 +2,53 @@ import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent to the player who requested the field of another player to notify him that the field could not be fetched (used for testing only). + */ public class NegativeResponsePlayerFieldMessage implements StoCMessage{ + /** + * The nickname of the recipient. + */ private final String recipientNickname; + /** + * The nickname of the player whose field has been requested. + */ private final String playerNickname; + /** + * The constructor of the class. + * @param recipientNickname The nickname of the recipient. + * @param playerNickname The nickname of the player whose field has been requested. + */ public NegativeResponsePlayerFieldMessage(String recipientNickname, String playerNickname) { this.recipientNickname = recipientNickname; this.playerNickname = playerNickname; } + /** + * This method is never called by Client, the NegativeResponsePlayerFieldMessage is kept for easier debugging and testing + * @param view The view of the player who receives the message. + */ @Override public void processMessage(View view) { // This method is never called by Client, the NegativeResponsePlayerFieldMessage is kept for easier debugging and testing } + /** + * This method is never called by Client, the NegativeResponsePlayerFieldMessage is kept for easier debugging and testing + * @return The nickname of the recipient. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the NegativeResponsePlayerFieldMessage object. + */ @Override public String toString() { return "NegativeResponsePlayerFieldMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/NewGameConfirmationMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/NewGameConfirmationMessage.java index 8be04a59..be93434f 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/NewGameConfirmationMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/NewGameConfirmationMessage.java @@ -2,16 +2,38 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; - +/** + * This class is used to manage the message sent by the server to the client to confirm the creation of a new game. + */ public class NewGameConfirmationMessage implements StoCMessage { + /** + * The nickname of the recipient who requested to create a new game and received the confirmation message. + */ private final String recipientNickname; + /** + * The id of the match created. + */ private final int matchId; + /** + * The constructor of the class: it creates a new NewGameConfirmationMessage with the nickname of the recipient who + * requested to create a new game and the id of the match returned by the server. + * @param recipientNickname the nickname of the player who will receive the confirmation message for his request to + * create a new game. + * @param matchId the id of the match created and returned by the server. + */ public NewGameConfirmationMessage(String recipientNickname, int matchId) { this.recipientNickname = recipientNickname; this.matchId = matchId; } + /** + * This method is used to process the message to the client when the creation of a new game is confirmed, + * updating view with data related to the new game created and the current event of the game, notifying the player + * that the game is created correctly. + * @param view the view of the player who will receive the message and should be updated. + */ + @Override public void processMessage(View view){ view.updateNewGameConfirm(matchId, recipientNickname); @@ -19,11 +41,21 @@ public void processMessage(View view){ view.updateCurrentEvent(Event.WAITING_FOR_START); // enter the waiting for start event } + /** + * This method is used to get the nickname of the player that will receive the message. + * @return the nickname of the player that will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the NewGameConfirmationMessage object. + */ @Override public String toString() { return "NewGameConfirmationMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/OutboundChatMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/OutboundChatMessage.java index 3159a2ea..bc475842 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/OutboundChatMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/OutboundChatMessage.java @@ -2,27 +2,59 @@ import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent from the server to the players notifying them of a new chat message. + */ public class OutboundChatMessage implements StoCMessage { + /** + * The nickname of the recipient of the chat message. + */ private final String recipientString; + /** + * The nickname of the sender of the chat message. + */ private final String senderNickname; + /** + * The content of the chat message. + */ private final String content; + /** + * The constructor of the class. + * @param recipientString The nickname of the recipient of the chat message. + * @param senderNickname The nickname of the sender of the chat message. + * @param content The content of the chat message. + */ public OutboundChatMessage(String recipientString, String senderNickname, String content) { this.recipientString = recipientString; this.senderNickname = senderNickname; this.content = content; } + /** + * This method is used to update the chat of the recipient. + * @param view The view of the recipient. + */ @Override public void processMessage(View view) { view.updateChat(recipientString,senderNickname,content); } + /** + * This method is used to get the nickname of the sender of the chat message. + * @return The nickname of the sender of the chat message. + */ @Override public String getRecipientNickname() { return recipientString; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the OutboundChatMessage object. + */ @Override public String toString() { return "OutboundChatMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardConfirmationMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardConfirmationMessage.java index 5c9a5c42..7e96caa7 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardConfirmationMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardConfirmationMessage.java @@ -6,17 +6,54 @@ import java.util.Arrays; import java.util.stream.Collectors; +/** + * This class is used to manage the message sent from the server to the players notifying them that a player has placed a card. + */ public class PlaceCardConfirmationMessage implements StoCMessage { + /** + * The nickname of the recipient. + */ private final String recipientNickname; - + /** + * The nickname of the player who placed the card successfully. + */ private final String playerNickname; + /** + * The card placed by the player. + */ private final int placedCard; + /** + * The coordinates where the card has been placed. + */ private final int[] placedCardCoordinates; + /** + * The side where the card has been placed. + */ private final boolean placedSide; + /** + * The points of the player who placed the card. + */ private final int playerPoints; + /** + * The resources of the player who placed the card. + */ private final int[] playerResources; + /** + * The new available field spaces. + */ private final ArrayList newAvailableFieldSpaces; + /** + * The constructor of the class. + * @param recipientNickname The nickname of the recipient. + * @param playerNickname The nickname of the player who placed the card successfully. + * @param placedCard The card placed by the player. + * @param placedCardCoordinates The coordinates where the card has been placed. + * @param placedSide The side where the card has been placed. + * @param playerPoints The points of the player who placed the card. + * @param playerResources The resources of the player who placed the card. + * @param newAvailableFieldSpaces The new available field spaces. + */ public PlaceCardConfirmationMessage(String recipientNickname, String playerNickname, int placedCard, int[] placedCardCoordinates, boolean placedSide, int playerPoints, @@ -31,16 +68,30 @@ public PlaceCardConfirmationMessage(String recipientNickname, String playerNickn this.newAvailableFieldSpaces = newAvailableFieldSpaces; } + /** + * This method is used to update the view of the player who placed the card. + * @param view The view of the player who placed the card. + */ @Override public void processMessage(View view) { view.updatePlacedCardConfirm(playerNickname, placedCard, placedCardCoordinates, placedSide, playerPoints, playerResources, newAvailableFieldSpaces); } + /** + * This method is used to get the nickname of the recipient. + * @return The nickname of the recipient. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlaceCardConfirmationMessage object. + */ @Override public String toString(){ return "PlaceCardConfirmationMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardFailedMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardFailedMessage.java index 5b9b4c56..a5b47443 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardFailedMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardFailedMessage.java @@ -3,26 +3,56 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent a player notifying them that a card placement has failed. + */ public class PlaceCardFailedMessage implements StoCMessage { + /** + * The nickname of the recipient who will receive the message. + */ private final String recipientNickname; + /** + * The reason why the card placement has failed. + */ private final String reason; + /** + * The constructor of the class: it creates a new PlaceCardFailedMessage with the nickname of the recipient who will receive the message + * and the reason why the card placement has failed. + * @param recipientNickname the nickname of the player who will receive the message. + * @param reason the reason why the card placement has failed. + */ public PlaceCardFailedMessage(String recipientNickname, String reason) { this.recipientNickname = recipientNickname; this.reason = reason; } + /** + * This method is used to process the message to the client when a card placement has failed, + * updating the view of the player who will receive the message. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.updateCurrentEvent(Event.PLACE_CARD_FAILURE); view.handleFailureCase(Event.PLACE_CARD_FAILURE,reason); } + /** + * This method is used to get the nickname of the recipient who will receive the message. + * @return the nickname of the recipient who will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlaceCardFailedMessage object. + */ @Override public String toString() { return "PlaceCardFailedMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardRollbackMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardRollbackMessage.java index c50ae6c5..2975baec 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardRollbackMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlaceCardRollbackMessage.java @@ -4,13 +4,41 @@ import java.util.Arrays; +/** + * This class is used to manage the message sent to all the players, notifying them that a player has placed a card and disconnected. + */ public class PlaceCardRollbackMessage implements StoCMessage{ + /** + * The nickname of the recipient who will receive the message. + */ private final String recipientNickname; + /** + * The nickname of the player who disconnected after placing + */ private final String playerNickname; + /** + * The card that has been placed by the player and should be removed. + */ private final int removedCard; + /** + * The old points of the player before the card placement who disconnected. + */ private final int playerPoints; + /** + * The old resources of the player before the card placement who disconnected. + */ private final int[] playerResources; + /** + * The constructor of the class: it creates a new PlaceCardRollbackMessage with the nickname of the recipient who will receive the message, + * the nickname of the player who disconnected after placing a card, the card that has been placed by the player and should be removed, + * the old points of the player before the card placement who disconnected and the old resources of the player before the card placement who disconnected. + * @param recipientNickname the nickname of the player who will receive the message. + * @param playerNickname the nickname of the player who disconnected after placing a card. + * @param removedCard the card that has been placed by the player and should be removed. + * @param playerPoints the old points of the player before the card placement who disconnected. + * @param playerResources the old resources of the player before the card placement who disconnected. + */ public PlaceCardRollbackMessage(String recipientNickname, String playerNickname, int removedCard, int playerPoints, int[] playerResources) { this.recipientNickname = recipientNickname; this.playerNickname = playerNickname; @@ -19,16 +47,31 @@ public PlaceCardRollbackMessage(String recipientNickname, String playerNickname, this.playerResources = playerResources; } + /** + * This method is used to process the message to the client when a player has placed a card and disconnected, + * updating the view of the player who will receive the message. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.updateRollback(playerNickname, removedCard, playerPoints, playerResources); } + /** + * This method is used to get the nickname of the recipient who will receive the message. + * @return the nickname of the player who will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlaceCardRollbackMessage object. + */ @Override public String toString() { return "PlaceCardRollbackMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerConnectedMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerConnectedMessage.java index c26469c1..7b0c72d3 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerConnectedMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerConnectedMessage.java @@ -3,25 +3,53 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent to notify players that a new player has joined the game during the lobby phase. + */ public class PlayerConnectedMessage implements StoCMessage { + /** + * The nickname of the player that will receive the message. + */ private final String recipientNickname; + /** + * The nickname of the player that has joined the game. + */ private final String connectedNickname; + /** + * Constructor. + * @param recipientNickname The nickname of the player that will receive the message. + * @param connectedNickname The nickname of the player that has joined the game. + */ public PlayerConnectedMessage(String recipientNickname, String connectedNickname) { this.recipientNickname = recipientNickname; this.connectedNickname = connectedNickname; } + /** + * This method is used to process the message to the client when a new player joins the game. + * @param view the view of the player who will receive the message. + */ @Override public void processMessage(View view) { view.handleEvent(Event.NEW_PLAYER_JOIN, connectedNickname); } + /** + * This method is used to get the nickname of the player that will receive the message. + * @return the nickname of the player that will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlayerConnectedMessage object. + */ @Override public String toString() { return "PlayerConnectedMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerDisconnectMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerDisconnectMessage.java index 351f57e0..b12c7a56 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerDisconnectMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerDisconnectMessage.java @@ -3,25 +3,55 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent to notify players when another player disconnects from the game during any stage. + */ public class PlayerDisconnectMessage implements StoCMessage { + /** + * The nickname of the recipient of the message + */ private final String recipientNickname; + /** + * The nickname of the player who disconnected + */ private final String disconnectedNickname; + /** + * The constructor of the class: it creates a new PlayerDisconnectMessage with the nickname of the recipient of the message + * and the nickname of the player who disconnected. + * @param recipientNickname the nickname of the player who will receive the message. + * @param disconnectedNickname the nickname of the player who disconnected from the game. + */ public PlayerDisconnectMessage(String recipientNickname, String disconnectedNickname) { this.recipientNickname = recipientNickname; this.disconnectedNickname = disconnectedNickname; } + /** + * This method is used to process the message to the client when a player disconnects from the game, + * updating the view based on the PLAYER_DISCONNECTED event. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.handleEvent(Event.PLAYER_DISCONNECTED, disconnectedNickname); } + /** + * This method is used to get the nickname of the recipient of the message. + * @return the nickname of the player who will receive the message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlayerDisconnectMessage object. + */ @Override public String toString() { return "PlayerDisconnectMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerGameStatusMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerGameStatusMessage.java index 1b2dbca8..cfc80cce 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerGameStatusMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerGameStatusMessage.java @@ -6,6 +6,9 @@ import java.util.Arrays; import java.util.stream.Collectors; +/** + * This class is used to manage the message sent to notify the player of the game status + */ public class PlayerGameStatusMessage implements StoCMessage { /** * Nickname of the recipient of the message @@ -100,6 +103,33 @@ public class PlayerGameStatusMessage implements StoCMessage { */ private final ArrayList newAvailableFieldSpaces; + /** + * Constructor: a message containing all the data necessary to update the view when the game enters a playing phase + * or when the player reconnects to the game. + * @param recipientNickname the nickname of the player who will receive the message and his view should be updated. + * @param playerNicknames the nicknames of the players in the game. + * @param playerConnected the connection status of the players in the game. + * @param playerColours the colours of the players in the game. + * @param playerHand the cards in the hand of the player. + * @param playerAssignedSecretObjectiveCards the secret objective cards assigned to the player. + * @param playerStartingCard the starting card assigned to the player. + * @param playerSecretObjective the secret objective chosen by the player. + * @param playerPoints the points of the players in the game. + * @param playersResourcesSummary the resources of the players in the game. + * @param playerFields the fields data of the players in the game. + * @param playerResources the resources of the player who will receive the message. + * @param gameCommonObjectives the common objectives of the game. + * @param gameCurrentResourceCards the resource cards visible in the game. + * @param gameCurrentGoldCards the gold cards visible in the game. + * @param gameResourcesDeckSize the size of the resource deck. + * @param gameGoldDeckSize the size of the gold deck. + * @param matchStatus the status of the match. + * @param chatHistory the chat history of players in the game. + * @param currentPlayer the nickname of the current player. + * @param newAvailableFieldSpaces the available field spaces for the player to place a card. + * @param resourceCardDeckFacingKingdom the kingdom type of the card facing up in the resource deck. + * @param goldCardDeckFacingKingdom the kingdom type of the card facing up in the gold deck. + */ public PlayerGameStatusMessage(String recipientNickname, ArrayList playerNicknames, ArrayList playerConnected, ArrayList playerColours, ArrayList playerHand, ArrayList playerAssignedSecretObjectiveCards, @@ -137,6 +167,11 @@ public PlayerGameStatusMessage(String recipientNickname, ArrayList playe this.goldCardDeckFacingKingdom = goldCardDeckFacingKingdom; } + /** + * This method is used to process the message to the client when the game status is updated, + * updating the view of the player with the new game status. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.updatePlayerData(playerNicknames, playerConnected,playerColours, playerHand, playerSecretObjective, @@ -146,11 +181,21 @@ public void processMessage(View view) { playersResourcesSummary,playerAssignedSecretObjectiveCards,playerStartingCard ); } + /** + * This method is used to get the nickname of the recipient of the message + * @return the nickname of the player who will receive the message + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlayerGameStatusMessage object. + */ @Override public String toString(){ String playerFieldsAsString = playerFields.stream() diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerReconnectedMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerReconnectedMessage.java index 92559e04..1ffe42a6 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerReconnectedMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerReconnectedMessage.java @@ -3,25 +3,56 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent to notify players that a player has reconnected to the game. + **/ public class PlayerReconnectedMessage implements StoCMessage { + /** + * The nickname of the recipient who requested to reconnect to the game before. + */ private final String recipientNickname; + /** + * The nickname of the player who reconnected to the game. + */ private final String disconnectedNickname; + /** + * The constructor of the class: it creates a new PlayerReconnectedMessage with the nickname of the recipient who + * requested to reconnect to the game before and the nickname of the player who reconnected to the game. + * @param recipientNickname the nickname of the player who will receive the message. + * @param disconnectedNickname the nickname of the player who reconnected to the game. + */ public PlayerReconnectedMessage(String recipientNickname, String disconnectedNickname) { this.recipientNickname = recipientNickname; this.disconnectedNickname = disconnectedNickname; } + /** + * This method is used to process the message to the client when a player reconnects to the game, + * updating the view based on the PLAYER_RECONNECTED event. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.handleEvent(Event.PLAYER_RECONNECTED, disconnectedNickname); } + /** + * This method is used to get the nickname of the recipient who requested to reconnect to the game before. + * @return the nickname of the player who received the confirmation message for his request to reconnect to the game. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlayerReconnectedMessage object. + + */ @Override public String toString() { return "PlayerReconnectedMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerTurnMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerTurnMessage.java index 059ea941..2354783b 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerTurnMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PlayerTurnMessage.java @@ -2,26 +2,56 @@ import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent to notify players of whose turn it is + */ public class PlayerTurnMessage implements StoCMessage { + /** + * The nickname of the recipient who requested to access the game before. + */ private final String recipientNickname; + /** + * The nickname of the player whose turn it is + */ private final String playerNickname; + /** + * The constructor of the class: it creates a new PlayerTurnMessage with the nickname of the recipient who + * requested to access the game before and the nickname of the player whose turn it is + * @param recipientNickname the nickname of the player who will receive the message. + * @param playerNickname the nickname of the player whose turn it is + */ public PlayerTurnMessage(String recipientNickname, String playerNickname) { this.recipientNickname = recipientNickname; this.playerNickname = playerNickname; } + /** + * This method is used to process the message to the client when the player turn is notified, + * updating the current event of the game and notifying the player that it is his turn. + * @param view the view of the player who will receive the message. + */ @Override public void processMessage(View view) { view.updatePlayerTurn(playerNickname); } + /** + * This method is used to get the nickname of the recipient who requested to access the game before. + * @return the nickname of the player who will receive the confirmation message for his request to access the game. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PlayerTurnMessage object. + */ @Override public String toString() { return "PlayerTurnMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PongMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PongMessage.java index 5e5edffe..039c2240 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PongMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/PongMessage.java @@ -2,23 +2,47 @@ import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent to notify the client that a ping has been received. + */ public class PongMessage implements StoCMessage { + /** + * The nickname of the recipient who sent the ping. + */ private final String recipientNickname; + /** + * The constructor of the class: it creates a new PongMessage with the nickname of the recipient who sent the ping. + * @param recipientNickname the nickname of the player who will receive the pong message. + */ public PongMessage(String recipientNickname) { this.recipientNickname = recipientNickname; } + /** + * This method is used to process the message to the client when a pong is received. + * @param view the view of the player who will receive the message. + */ @Override public void processMessage(View view) { // TODO } + /** + * This method is used to get the nickname of the recipient who sent the ping. + * @return the nickname of the player who will receive the pong message. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the PongMessage object. + */ @Override public String toString() { return "PongMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ReconnectGameConfirmMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ReconnectGameConfirmMessage.java index 54369ddc..2ef186a4 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ReconnectGameConfirmMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ReconnectGameConfirmMessage.java @@ -3,23 +3,51 @@ import it.polimi.ingsw.am32.client.Event; import it.polimi.ingsw.am32.client.View; +/** + * This class is used to manage the message sent by the server to the client to confirm the reconnection to the game. + * + **/ public class ReconnectGameConfirmMessage implements StoCMessage { + /** + * The nickname of the recipient who requested to reconnect to the game before. + */ private final String recipientNickname; + /** + * The constructor of the class: it creates a new ReconnectGameConfirmMessage with the nickname of the recipient who + * requested to reconnect to the game before. + * @param recipientNickname the nickname of the player who will receive the confirmation message for his request + * to reconnect to the game. + */ public ReconnectGameConfirmMessage(String recipientNickname) { this.recipientNickname = recipientNickname; } + /** + * This method is used to process the message to the client when the reconnection to the game is confirmed, + * modifying the view based on the GAME_RECONNECTED event. + * @param view the view of the player who will receive the message and should be updated. + */ @Override public void processMessage(View view) { view.handleEvent(Event.GAME_RECONNECTED,null); } + /** + * This method is used to get the nickname of the recipient who requested to reconnect to the game before. + * @return the nickname of the player who received the confirmation message for his request to reconnect to the game. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the ReconnectGameConfirmMessage object. + */ @Override public String toString() { return "ReconnectGameConfirmMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ResponsePlayerFieldMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ResponsePlayerFieldMessage.java index 34afab20..559f4ed4 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ResponsePlayerFieldMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/ResponsePlayerFieldMessage.java @@ -5,12 +5,34 @@ import java.util.Arrays; import java.util.stream.Collectors; +/** + * This class is used to manage the message sent to the player who requested the field of another player (used for testing only). + */ public class ResponsePlayerFieldMessage implements StoCMessage { + /** + * The nickname of the recipient. + */ private final String recipientNickname; + /** + * The nickname of the player whose field has been requested. + */ private final String playerNickname; + /** + * The field of the player whose field has been requested. + */ private final ArrayList playerField; + /** + * The resources of the player whose field has been requested. + */ private final int[] playerResources; + /** + * The constructor of the class. + * @param recipientNickname The nickname of the recipient. + * @param playerNickname The nickname of the player whose field has been requested. + * @param playerField The field of the player whose field has been requested. + * @param playerResources The resources of the player whose field has been requested. + */ public ResponsePlayerFieldMessage(String recipientNickname, String playerNickname, ArrayList playerField, int[] playerResources) { this.recipientNickname = recipientNickname; @@ -19,16 +41,30 @@ public ResponsePlayerFieldMessage(String recipientNickname, String playerNicknam this.playerResources = playerResources; } + /** + * This method is never called by Client, the ResponsePlayerFieldMessage is kept for easier debugging and testing + * @param view The view of the player who receives the message. + */ @Override public void processMessage(View view) { // This method is never called by Client, the ResponsePlayerFieldMessage is kept for easier debugging and testing } + /** + * This method is never called by Client, the ResponsePlayerFieldMessage is kept for easier debugging and testing + * @return The nickname of the recipient. + */ @Override public String getRecipientNickname() { return recipientNickname; } + /** + * This method overrides the default toString method. + * It provides a string representation of a message object, which can be useful for debugging purposes. + * + * @return A string representation of the ResponsePlayerFieldMessage object. + */ @Override public String toString() { return "ResponsePlayerFieldMessage:{" + diff --git a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/StoCMessage.java b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/StoCMessage.java index 42bed70d..b3e11d37 100644 --- a/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/StoCMessage.java +++ b/src/main/java/it/polimi/ingsw/am32/message/ServerToClient/StoCMessage.java @@ -11,8 +11,22 @@ public interface StoCMessage extends Serializable { /** * Delivers the message to the specified virtual view. + * @param view the view that should be updated with the data contained in the message. */ void processMessage(View view); - String getRecipientNickname(); // Method needed for submitVirtualViewMessage method in Gamecontroller; GameController needs to know who to send message to. - String toString(); // Used for debugging purposes + + /** + * Gets the recipient's nickname of the message. + * Method needed for submitVirtualViewMessage method in Game controller. + * GameController needs to know who to send a message to. + * @return the recipient's nickname of the message. + */ + String getRecipientNickname(); + /** + * This method provides a string representation of a message object, which can be useful for debugging purposes. + * It will be overridden by the classes that implement the StoCMessage interface. + * + * @return A string representation of the StoCMessage object. + */ + String toString(); } diff --git a/src/main/java/it/polimi/ingsw/am32/model/card/CornerType.java b/src/main/java/it/polimi/ingsw/am32/model/card/CornerType.java index f3737d09..79d03c89 100644 --- a/src/main/java/it/polimi/ingsw/am32/model/card/CornerType.java +++ b/src/main/java/it/polimi/ingsw/am32/model/card/CornerType.java @@ -7,18 +7,53 @@ * @author Antony */ public enum CornerType { + /** + * Plant corner type indicates that the corner of the card has a plant resource. + */ PLANT(0), + /** + * Fungi corner type indicates that the corner of the card has a fungi resource. + */ FUNGI(1), + /** + * Animal corner type indicates that the corner of the card has an animal resource. + */ ANIMAL(2), + /** + * Insect corner type indicates that the corner of the card has an insect resource. + */ INSECT(3), + /** + * Quill corner type indicates that the corner of the card has a quill object. + */ QUILL(4), + /** + * Inkwell corner type indicates that the corner of the card has an inkwell object. + */ INKWELL(5), + /** + * Manuscript corner type indicates that the corner of the card has a manuscript object. + */ MANUSCRIPT(6), + /** + * Empty corner type indicates that the corner of the card is empty. + */ EMPTY(7), + /** + * Non-coverable corner type indicates that the corner of the card is not coverable. + */ NON_COVERABLE(8); + /** + * The integer value associated with the corner type. + */ private final int value; + /** + * Constructor for the CornerType enum. + * + * @param value The integer value associated with the corner type. + */ CornerType(int value) { this.value = value; } diff --git a/src/main/java/it/polimi/ingsw/am32/model/card/pointstrategy/ObjectType.java b/src/main/java/it/polimi/ingsw/am32/model/card/pointstrategy/ObjectType.java index 4a1059af..719f12db 100644 --- a/src/main/java/it/polimi/ingsw/am32/model/card/pointstrategy/ObjectType.java +++ b/src/main/java/it/polimi/ingsw/am32/model/card/pointstrategy/ObjectType.java @@ -9,16 +9,44 @@ * @author Antony */ public enum ObjectType { + /** + * Plant object type indicates that the object is a plant resource. + */ PLANT(0), + /** + * Fungi object type indicates that the object is a fungi resource. + */ FUNGI(1), + /** + * Animal object type indicates that the object is an animal resource. + */ ANIMAL(2), + /** + * Insect object type indicates that the object is an insect resource. + */ INSECT(3), + /** + * Quill object type indicates that the object is a quill object. + */ QUILL(4), + /** + * Inkwell object type indicates that the object is an inkwell object. + */ INKWELL(5), + /** + * Manuscript object type indicates that the object is a manuscript object. + */ MANUSCRIPT(6); + /** + * The integer value associated with the object type. + */ private final int value; + /** + * Constructor for the ObjectType enum. + * @param value The integer value associated with the object type. + */ ObjectType(int value) { this.value = value; } diff --git a/src/main/java/it/polimi/ingsw/am32/model/deck/utils/DeckType.java b/src/main/java/it/polimi/ingsw/am32/model/deck/utils/DeckType.java index f84bbf9d..25826afd 100644 --- a/src/main/java/it/polimi/ingsw/am32/model/deck/utils/DeckType.java +++ b/src/main/java/it/polimi/ingsw/am32/model/deck/utils/DeckType.java @@ -8,9 +8,21 @@ * @author Lorenzo */ public enum DeckType { + /** + * The deck that contains the resource cards. + */ RESOURCE("/it/polimi/ingsw/am32/model/deck/ResourceCards.json"), + /** + * The deck that contains the gold cards. + */ GOLD("/it/polimi/ingsw/am32/model/deck/GoldCards.json"), + /** + * The deck that contains the starting cards. + */ STARTING("/it/polimi/ingsw/am32/model/deck/StartingCards.json"), + /** + * The deck that contains the objective cards. + */ OBJECTIVE("/it/polimi/ingsw/am32/model/deck/ObjectiveCards.json"); /** @@ -18,6 +30,11 @@ public enum DeckType { */ private final String JSONPath; + /** + * Constructor for the DeckType enum. + * + * @param JSONPath The path to the JSON file that contains the card data for the deck. + */ DeckType(String JSONPath) { this.JSONPath = JSONPath; } diff --git a/src/main/java/it/polimi/ingsw/am32/model/field/CardPlaced.java b/src/main/java/it/polimi/ingsw/am32/model/field/CardPlaced.java index d1bbeac0..ec9a0b8b 100644 --- a/src/main/java/it/polimi/ingsw/am32/model/field/CardPlaced.java +++ b/src/main/java/it/polimi/ingsw/am32/model/field/CardPlaced.java @@ -15,9 +15,21 @@ public class CardPlaced { //--------------------------------------------------------------------------------------------- // Variables and Constants + /** + * The card that player decided to place. + */ private final NonObjectiveCard placedCard; + /** + * The x coordinate of the placed card. + */ private final int x; + /** + * The y coordinate of the placed card. + */ private final int y; + /** + * A boolean representing the face of the card that player want to use. + */ private final boolean isUp; //--------------------------------------------------------------------------------------------- diff --git a/src/main/java/it/polimi/ingsw/am32/model/field/Field.java b/src/main/java/it/polimi/ingsw/am32/model/field/Field.java index 324cfbf9..f83b38d4 100644 --- a/src/main/java/it/polimi/ingsw/am32/model/field/Field.java +++ b/src/main/java/it/polimi/ingsw/am32/model/field/Field.java @@ -18,10 +18,21 @@ public class Field { //--------------------------------------------------------------------------------------------- // Variables and Constants + /** + * The list of cards placed in the field. + */ private final ArrayList fieldCards; + /** + * The resources currently owned by the player + */ private final int[] activeRes; + /** + * The number of resources in the game + */ private static final int resourcesSize = 7; - + /** + * The resources owned by the player before the last card was placed; used for rollback + */ private final int[] oldActiveRes; //--------------------------------------------------------------------------------------------- diff --git a/src/main/java/it/polimi/ingsw/am32/model/match/MatchStatus.java b/src/main/java/it/polimi/ingsw/am32/model/match/MatchStatus.java index c7bbc9f1..d82e92d8 100644 --- a/src/main/java/it/polimi/ingsw/am32/model/match/MatchStatus.java +++ b/src/main/java/it/polimi/ingsw/am32/model/match/MatchStatus.java @@ -6,20 +6,34 @@ * @author Lorenzo */ public enum MatchStatus { - // The match is in the lobby state, waiting for players to join. + /** + * The match is in the lobby state, waiting for players to join. + */ LOBBY(0), - // The match is in the preparation state, players are setting up their game. + /** + * The match is in the preparation state, players are setting up their game. + */ PREPARATION(1), - // The match is in the playing state, the game is in progress. + /** + * The match is in the playing state, the game is in progress. + */ PLAYING(2), - // The match is in the terminating state, the game is about to end. + /** + * The match is in the terminating state, the game is about to end. + */ TERMINATING(3), - // The match is in the last turn state, the last turn of the game is in progress. + /** + * The match is in the last turn state, the last turn of the game is in progress. + */ LAST_TURN(4), - // The match is in the terminated state, the game has ended. + /** + * The match is in the terminated state, the game has ended. + */ TERMINATED(5); - // The integer value associated with each state. + /** + * The integer value associated with the state. + */ private final int value; /** diff --git a/src/main/java/it/polimi/ingsw/am32/model/player/Colour.java b/src/main/java/it/polimi/ingsw/am32/model/player/Colour.java index 4134836c..28933c63 100644 --- a/src/main/java/it/polimi/ingsw/am32/model/player/Colour.java +++ b/src/main/java/it/polimi/ingsw/am32/model/player/Colour.java @@ -6,13 +6,31 @@ * @author Matteo */ public enum Colour { - RED(0), // Represents the colour red, associated with the value 0 - GREEN(1), // Represents the colour green, associated with the value 1 - BLUE(2), // Represents the colour blue, associated with the value 2 - YELLOW(3), // Represents the colour yellow, associated with the value 3 - BLACK(4); // Represents the colour black, associated with the value 4 + /** + * Represents the red color that a player can identify with and is associated with value 0. + */ + RED(0), + /** + * Represents the green color that a player can identify with and is associated with value 1. + */ + GREEN(1), + /** + * Represents the blue color that a player can identify with and is associated with value 2. + */ + BLUE(2), + /** + * Represents the yellow color that a player can identify with and is associated with value 3. + */ + YELLOW(3), + /** + * Represents the black color that a player can identify with and is associated with value 4. + */ + BLACK(4); - private final int value; // The unique integer value associated with the colour + /** + * The unique integer value associated with the color. + */ + private final int value; /** * Constructor for the Colour enum. diff --git a/src/main/java/it/polimi/ingsw/am32/model/player/Player.java b/src/main/java/it/polimi/ingsw/am32/model/player/Player.java index 55a5997b..7d96ba3c 100644 --- a/src/main/java/it/polimi/ingsw/am32/model/player/Player.java +++ b/src/main/java/it/polimi/ingsw/am32/model/player/Player.java @@ -18,18 +18,49 @@ public class Player { //--------------------------------------------------------------------------------------------- // Variables and Constants + /** + * The nickname of the player + */ private final String nickname; + /** + * The field of the player + */ private Field gameField; + /** + * The secret objective of the player + */ private Card secretObjective; + /** + * The colour assigned of the player + */ private Colour colour; + /** + * The points owned of the player + */ private int points; + /** + * The hand of the player + */ private ArrayList hand; + /** + * The two cards that the player can choose as secret objective + */ private final Card[] tmpSecretObj; + /** + * The points gained from the objectives + */ private int pointsGainedFromObjectives = 0; + /** + * The state of the points gained from the objectives + */ private final boolean[] objectivePointsState = new boolean[]{false, false}; - + /** + * The number of cards that the player can choose as secret objective + */ private final static int secObjOptions = 2; - + /** + * The old points of the player; used for rollback + */ private int oldPoints; //--------------------------------------------------------------------------------------------- diff --git a/src/main/java/it/polimi/ingsw/am32/network/ClientAcceptor/RMIClientAcceptor.java b/src/main/java/it/polimi/ingsw/am32/network/ClientAcceptor/RMIClientAcceptor.java index ae16147b..69da7d79 100644 --- a/src/main/java/it/polimi/ingsw/am32/network/ClientAcceptor/RMIClientAcceptor.java +++ b/src/main/java/it/polimi/ingsw/am32/network/ClientAcceptor/RMIClientAcceptor.java @@ -3,9 +3,12 @@ import it.polimi.ingsw.am32.controller.GameController; import it.polimi.ingsw.am32.controller.exceptions.abstraction.LobbyMessageException; import it.polimi.ingsw.am32.message.ClientToServer.CtoSLobbyMessage; +import it.polimi.ingsw.am32.message.ServerToClient.ErrorMessage; import it.polimi.ingsw.am32.network.ClientNode.RMIClientNodeInt; import it.polimi.ingsw.am32.network.GameTuple; import it.polimi.ingsw.am32.network.ServerNode.RMIServerNode; +import it.polimi.ingsw.am32.network.exceptions.UploadFailureException; +import it.polimi.ingsw.am32.utilities.Configuration; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -32,14 +35,24 @@ public GameTuple uploadToServer(RMIClientNodeInt node, CtoSLobbyMessage message) try { gameController = message.elaborateMessage(rmiServerNode); } catch (LobbyMessageException e) { - // TODO: Handle the exception, send ErrorMessage to the client instead - rmiServerNode.destroy(); + + Configuration.getInstance().getExecutorService().submit(() -> { + try { + rmiServerNode.uploadToClient(new ErrorMessage(e.getMessage(), "PLAYER", e.getExceptionType().getValue())); + } catch (UploadFailureException ignore) {} + rmiServerNode.destroy(); + }); + logger.error("GameController access failed: {}", e.getMessage()); throw e; + } catch (Exception e) { // We can't lose the visibility of the RuntimeExceptions that are thrown by the elaboration of the message. // The Server will not crash because how the thread is managed, but we need to know what happened to fix it in the future. // Do not remove this catch block. Remove the throws clause if needed but keep the logger. + + // TODO mandiamo ErrorMessage anche qui? + rmiServerNode.destroy(); logger.fatal("GameController access failed due to a critical exception: {}", e.getMessage()); throw e; @@ -50,4 +63,8 @@ public GameTuple uploadToServer(RMIClientNodeInt node, CtoSLobbyMessage message) logger.info("RMIServerNode successfully created and added to the GameController ID {}", gameController.getId()); return new GameTuple(rmiServerNode, gameController.getId()); } + + public void extraPing(){ + logger.trace("extraPing"); + } } diff --git a/src/main/java/it/polimi/ingsw/am32/network/ClientAcceptor/RMIClientAcceptorInt.java b/src/main/java/it/polimi/ingsw/am32/network/ClientAcceptor/RMIClientAcceptorInt.java index bff7a719..e3878d62 100644 --- a/src/main/java/it/polimi/ingsw/am32/network/ClientAcceptor/RMIClientAcceptorInt.java +++ b/src/main/java/it/polimi/ingsw/am32/network/ClientAcceptor/RMIClientAcceptorInt.java @@ -11,4 +11,6 @@ public interface RMIClientAcceptorInt extends Remote { GameTuple uploadToServer(RMIClientNodeInt node, CtoSLobbyMessage message) throws RemoteException, LobbyMessageException; + + void extraPing() throws RemoteException; } diff --git a/src/main/java/it/polimi/ingsw/am32/network/ClientNode/RMIClientNode.java b/src/main/java/it/polimi/ingsw/am32/network/ClientNode/RMIClientNode.java index 90054b57..c0a3d1b9 100644 --- a/src/main/java/it/polimi/ingsw/am32/network/ClientNode/RMIClientNode.java +++ b/src/main/java/it/polimi/ingsw/am32/network/ClientNode/RMIClientNode.java @@ -8,7 +8,8 @@ import it.polimi.ingsw.am32.message.ServerToClient.PongMessage; import it.polimi.ingsw.am32.message.ServerToClient.StoCMessage; import it.polimi.ingsw.am32.network.ClientAcceptor.RMIClientAcceptorInt; -import it.polimi.ingsw.am32.network.GameTuple; +import it.polimi.ingsw.am32.network.ServerNode.RMIServerNodeInt; +import it.polimi.ingsw.am32.network.exceptions.ConnectionSetupFailedException; import it.polimi.ingsw.am32.network.exceptions.NodeClosedException; import it.polimi.ingsw.am32.network.exceptions.UploadFailureException; import org.apache.logging.log4j.LogManager; @@ -28,13 +29,17 @@ public class RMIClientNode extends UnicastRemoteObject implements ClientNodeInte private static final int PONGMAXCOUNT = 3; + private static final int THREADSLEEPINTERVAL = 1000; + private static final int PINGINTERVAL = 5000; + private static final String REMOTEOBJECTNAME = "Server-CodexNaturalis"; + private final ExecutorService executorService; private final Logger logger; - private GameTuple gameTuple; + private RMIServerNodeInt serverNode; private final View view; - private final String serverURL; + private final String ip; private final int port; private int pongCount; private String nickname; @@ -44,47 +49,92 @@ public class RMIClientNode extends UnicastRemoteObject implements ClientNodeInte private final Timer timer; private ClientPingTask clientPingTask; + private ClientPingTask prePingTask; private boolean statusIsAlive; + private boolean nodePreState; + private boolean reconnectCalled; private final Object aliveLock; private final Object cToSProcessingLock; private final Object sToCProcessingLock; - public RMIClientNode(View view, String serverURL, int port) throws RemoteException { + public RMIClientNode(View view, String ip, int port) throws RemoteException, ConnectionSetupFailedException { this.view = view; - this.serverURL = serverURL; + this.ip = ip; this.port = port; + pongCount = PONGMAXCOUNT; + nickname = "Unknown"; + reconnectCalled = false; + logger = LogManager.getLogger(RMIClientNode.class); + + try { + + logger.info("Attempting to connect to the server at {}:{}", ip, port); + + registry = LocateRegistry.getRegistry(ip, port); + + rmiClientAcceptor = (RMIClientAcceptorInt) registry.lookup(REMOTEOBJECTNAME); + logger.info("RMI-Client-Acceptor found on the server. Connection established"); + + } catch (RemoteException | NotBoundException e) { + + logger.info("Connection failed do to wrong parameters or inaccessible server"); + + throw new ConnectionSetupFailedException(); + } + + statusIsAlive = true; + nodePreState = true; + timer = new Timer(); aliveLock = new Object(); cToSProcessingLock = new Object(); sToCProcessingLock = new Object(); - pongCount = PONGMAXCOUNT; executorService = Executors.newCachedThreadPool(); clientPingTask = new ClientPingTask(this); + prePingTask = new ClientPingTask(this); + timer.schedule(prePingTask, 0, PINGINTERVAL); } @Override public void uploadToServer(CtoSMessage message) throws UploadFailureException { - synchronized (aliveLock) { - if(gameTuple == null) { + synchronized (cToSProcessingLock) { - // TODO aggiungere di dire errore alla view - throw new UploadFailureException(); - } - } + synchronized (aliveLock) { - synchronized (cToSProcessingLock) { + if(serverNode == null) { + + logger.error("Attempt to send CtoSMessage before CtoSLobbyMessage. Upload rejected. Message: {}", message); + // TODO aggiungere di dire errore alla view + throw new UploadFailureException(); + } + + if(!statusIsAlive) + throw new UploadFailureException(); + } try { - gameTuple.getNode().uploadCtoS(message); // TODO il numero di partita in realtà non server + serverNode.uploadCtoS(message); // TODO il numero di partita in realtà non server logger.info("Message sent. Type: CtoSMessage: {}", message); - } catch (NodeClosedException e) { // TODO gestire eccezioni - throw new RuntimeException(e); + + } catch (NodeClosedException e) { + + logger.info("Failed to process CtoSMessage because server node is closed"); + + requestReconnection(); + + throw new UploadFailureException(); + } catch (RemoteException e) { - throw new RuntimeException(e); + + logger.info("Failed to send CtoSMessage to server. RemoteException: {}", e.getMessage()); + + requestReconnection(); + + throw new UploadFailureException(); } } } @@ -92,110 +142,198 @@ public void uploadToServer(CtoSMessage message) throws UploadFailureException { @Override public void uploadToServer(CtoSLobbyMessage message) throws UploadFailureException { - synchronized (aliveLock) { - if(gameTuple != null) { + synchronized (cToSProcessingLock) { - // TODO aggiungere di dire errore alla view - throw new UploadFailureException(); - } - } + synchronized (aliveLock) { + if(serverNode != null) { - synchronized (cToSProcessingLock) { + logger.error("Attempt to send second CtoSLobbyMessage while RMIServerNode still valid. Upload rejected. Message: {}", message); + // TODO aggiungere di dire errore alla view + throw new UploadFailureException(); + } + + if(!statusIsAlive) + throw new UploadFailureException(); + } try { // TODO ritorniamo solo l'interfaccia RMI e non il num di partita perchè non serve?? - gameTuple = rmiClientAcceptor.uploadToServer((RMIClientNodeInt) this, message); + serverNode = rmiClientAcceptor.uploadToServer((RMIClientNodeInt) this, message).getNode(); + + synchronized (aliveLock){ + nodePreState = false; + prePingTask.cancel(); + } + logger.info("Message sent. Type: CtoSLobbyMessage. Content: {}", message); + timer.scheduleAtFixedRate(clientPingTask, 0, PINGINTERVAL); - timer.scheduleAtFixedRate(clientPingTask, 0, 5000); + } catch (RemoteException e) { - } catch (RemoteException e) { // TODO come gestisco queste exception?? - throw new RuntimeException(e); - } catch (LobbyMessageException e) { - // TODO: Handle exception correctly - // view.failureCtoSLobby + logger.info("Failed to send CtoSLobbyMessage to server. RemoteException: {}", e.getMessage()); + + requestReconnection(); + + throw new UploadFailureException(); + + } catch (LobbyMessageException ignore) { + + // TODO come faccio la parte in cui il node è ancora connesso } } } @Override - public void uploadStoC(StoCMessage message) { + public void uploadStoC(StoCMessage message) throws NodeClosedException { - resetTimeCounter(); + synchronized (sToCProcessingLock) { - if(message == null) { - logger.error("Null message received"); - return; - } + synchronized (aliveLock) { + if(!statusIsAlive) + throw new NodeClosedException(); - if(message instanceof PongMessage) { - logger.debug("PongMessage received"); - return; + resetTimeCounter(); + } + + if (message == null) { + logger.error("Null message received"); + return; + } + + if (message instanceof PongMessage) { + logger.debug("PongMessage received"); + return; + } + + try { + logger.info("Message received. Type: StoCMessage. Processing: {}", message); + message.processMessage(view); + + } catch (Exception e) { + logger.fatal("Critical Runtime Exception:\nException Type: {}\nLocal Message: {}\nStackTrace: {}", + e.getClass(), e.getLocalizedMessage(), Arrays.toString(e.getStackTrace())); + } } + } - try { - logger.info("Message received. Type: StoCMessage. Processing: {}", message); - message.processMessage(view); - } catch (Exception e) { - logger.fatal("Critical Runtime Exception:\nException Type: {}\nLocal Message: {}\nStackTrace: {}", - e.getClass(), e.getLocalizedMessage(), Arrays.toString(e.getStackTrace())); + private void requestReconnection() { + + synchronized (aliveLock) { + + if(!statusIsAlive && reconnectCalled) { + return; + } + + reconnectCalled = true; + statusIsAlive = false; + nodePreState = false; + serverNode = null; + clientPingTask.cancel(); + prePingTask.cancel(); + timer.purge(); + clientPingTask = new ClientPingTask(this); + prePingTask = new ClientPingTask(this); + view.nodeDisconnected(); + + executorService.execute(this::resetConnection); } } private void resetConnection () { - gameTuple = null; - clientPingTask.cancel(); - timer.purge(); - clientPingTask = new ClientPingTask(this); - // TODO aggiungere alla view - //TODO view.disconnected(); + while(true){ + + try { + rmiClientAcceptor = (RMIClientAcceptorInt) registry.lookup(REMOTEOBJECTNAME); + logger.debug("RMI-Client-Acceptor found on the server. Connection established"); + break; + } catch (RemoteException | NotBoundException e) { + + logger.debug("RMI-Client-Acceptor not found on the server. searching for registry"); + + while (true) { + try { + registry = LocateRegistry.getRegistry(ip, port); + logger.debug("Registry found on the server. Searching for RMIClientAcceptor"); + break; + } catch (RemoteException ignored) {} + logger.debug("Registry not found. Trying again later"); + + try { + Thread.sleep(THREADSLEEPINTERVAL); + } catch (InterruptedException ignore) {} + } + } + } + + synchronized (aliveLock) { + reconnectCalled = false; + nodePreState = true; + statusIsAlive = true; + pongCount = PONGMAXCOUNT; + timer.schedule(prePingTask, 0, PINGINTERVAL); + logger.info("Connection established"); + view.nodeReconnected(); + } } public void startConnection() { - try { - registry = LocateRegistry.getRegistry(serverURL, port); - String remoteObjectName = "Server-CodexNaturalis"; - rmiClientAcceptor = (RMIClientAcceptorInt) registry.lookup(remoteObjectName); - logger.info("RMI-Client-Acceptor found on the server. Connection established"); - } catch (RemoteException | NotBoundException e) { - //TODO handle exception - } + logger.debug("RMIClientNode started"); } @Override public void pongTimeOverdue() { boolean toReset = false; + boolean preState = false; synchronized (aliveLock){ + if(!statusIsAlive) return; - pongCount--; + if(nodePreState){ + preState = true; + logger.debug("Pong time overdue node pre-game"); + + } else { + pongCount--; - logger.debug("Pong time overdue. Pong count: {}", pongCount); + logger.debug("Pong time overdue. Pong count: {}", pongCount); - if(pongCount <= 0) { - logger.info("Pong count reached minimum. Trying to check connection"); - toReset = true; + if (pongCount <= 0) { + logger.info("Pong count reached minimum. Trying to check connection"); + toReset = true; + } } } if(toReset){ - // resetConnection(); // TODO risolvere + requestReconnection(); return; } - executorService.submit(() -> { - try { - uploadToServer(new PingMessage(nickname)); - } catch (UploadFailureException ignore) {} - }); + if(preState){ + executorService.submit(() -> { + try { + rmiClientAcceptor.extraPing(); + logger.debug("Calling extraPing method on RMIClientAcceptor"); + } catch (RemoteException e) { + requestReconnection(); + } + }); + + } else { + executorService.submit(() -> { + try { + uploadToServer(new PingMessage(nickname)); + } catch (UploadFailureException ignore) {} + }); + } } public void resetTimeCounter() { diff --git a/src/main/java/it/polimi/ingsw/am32/network/ClientNode/RMIClientNodeInt.java b/src/main/java/it/polimi/ingsw/am32/network/ClientNode/RMIClientNodeInt.java index b5efec5c..c476a7d1 100644 --- a/src/main/java/it/polimi/ingsw/am32/network/ClientNode/RMIClientNodeInt.java +++ b/src/main/java/it/polimi/ingsw/am32/network/ClientNode/RMIClientNodeInt.java @@ -1,10 +1,11 @@ package it.polimi.ingsw.am32.network.ClientNode; import it.polimi.ingsw.am32.message.ServerToClient.StoCMessage; +import it.polimi.ingsw.am32.network.exceptions.NodeClosedException; import java.rmi.Remote; import java.rmi.RemoteException; public interface RMIClientNodeInt extends Remote { - void uploadStoC(StoCMessage message) throws RemoteException; + void uploadStoC(StoCMessage message) throws RemoteException, NodeClosedException; } diff --git a/src/main/java/it/polimi/ingsw/am32/network/ClientNode/SKClientNode.java b/src/main/java/it/polimi/ingsw/am32/network/ClientNode/SKClientNode.java index dcad5649..3df1e4ff 100644 --- a/src/main/java/it/polimi/ingsw/am32/network/ClientNode/SKClientNode.java +++ b/src/main/java/it/polimi/ingsw/am32/network/ClientNode/SKClientNode.java @@ -6,6 +6,7 @@ import it.polimi.ingsw.am32.message.ClientToServer.PingMessage; import it.polimi.ingsw.am32.message.ServerToClient.PongMessage; import it.polimi.ingsw.am32.message.ServerToClient.StoCMessage; +import it.polimi.ingsw.am32.network.exceptions.ConnectionSetupFailedException; import it.polimi.ingsw.am32.network.exceptions.NodeClosedException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -21,6 +22,7 @@ public class SKClientNode implements ClientNodeInterface, Runnable { private static final int PONGMAXCOUNT = 3; + private static final int SOCKETTIMEOUT = 100; private final Logger logger; private final ExecutorService executorService; @@ -44,20 +46,62 @@ public class SKClientNode implements ClientNodeInterface, Runnable { private final Object cToSProcessingLock; private final Object sToCProcessingLock; - public SKClientNode(View view, String ip, int port) { + public SKClientNode(View view, String ip, int port) throws ConnectionSetupFailedException { this.view = view; - executorService = Executors.newCachedThreadPool(); this.ip = ip; this.port = port; + statusIsAlive = true; + reconnectCalled = false; + pongCount = PONGMAXCOUNT; // todo fare un config?? + nickname = "Unknown"; + + logger = LogManager.getLogger(SKClientNode.class); + + try { + + logger.info("Attempting to connect to the server at {}:{}", ip, port); + + socket = new Socket(ip, port); + outputObtStr = new ObjectOutputStream(socket.getOutputStream()); + outputObtStr.flush(); + inputObtStr = new ObjectInputStream(socket.getInputStream()); + socket.setSoTimeout(SOCKETTIMEOUT); + + logger.info("Connection established. Personal connection data: {}", socket.getLocalSocketAddress()); + + } catch (IOException e) { + + if (inputObtStr != null) { + try { + inputObtStr.close(); + } catch (IOException ignore) {} + } + + if (outputObtStr != null) { + try { + outputObtStr.close(); + } catch (IOException ignore) {} + } + + if (socket != null) { + try { + socket.close(); + } catch (IOException ignore) {} + } + + //System.out.println("Connection failed do to wrong parameters or inaccessible server"); + logger.info("Connection failed do to wrong parameters or inaccessible server"); + + throw new ConnectionSetupFailedException(); + } + + executorService = Executors.newCachedThreadPool(); clientPingTask = new ClientPingTask(this); timer = new Timer(); aliveLock = new Object(); cToSProcessingLock = new Object(); sToCProcessingLock = new Object(); - statusIsAlive = false; - pongCount = PONGMAXCOUNT; // todo fare un config?? - logger = LogManager.getLogger(SKClientNode.class); - reconnectCalled = false; + timer.scheduleAtFixedRate(clientPingTask, 0, 5000); } public void run() { @@ -120,7 +164,7 @@ public void listenForIncomingMessages() throws IOException, ClassNotFoundExcepti @Override public void uploadToServer(CtoSLobbyMessage message) { - while (true) { + while (true) { //TODO cambiare il while try { synchronized (cToSProcessingLock) { outputObtStr.writeObject(message); @@ -140,7 +184,7 @@ public void uploadToServer(CtoSLobbyMessage message) { @Override public void uploadToServer(CtoSMessage message) { - while (true) { + while (true) { //TODO cambiare il while try { synchronized (cToSProcessingLock) { outputObtStr.writeObject(message); @@ -199,7 +243,8 @@ private boolean manageReconnectionRequests() { try { aliveLock.wait(); - } catch (InterruptedException ignore) {} + } catch (InterruptedException | IllegalMonitorStateException ignore) { + } return false; @@ -208,6 +253,7 @@ private boolean manageReconnectionRequests() { clientPingTask.cancel(); timer.purge(); clientPingTask = new ClientPingTask(this); + view.nodeDisconnected(); return true; } } @@ -244,12 +290,12 @@ private void connect() { outputObtStr = new ObjectOutputStream(socket.getOutputStream()); outputObtStr.flush(); inputObtStr = new ObjectInputStream(socket.getInputStream()); - socket.setSoTimeout(100); + socket.setSoTimeout(SOCKETTIMEOUT); logger.info("Connection established. Personal connection data: {}", socket.getLocalSocketAddress()); } catch (IOException ignore) { - logger.error("Failed to connect to {}:{}", ip, port); + logger.debug("Failed to connect to {}:{}", ip, port); try { Thread.sleep(100); // TODO parametrizzazione con config? } catch (InterruptedException ignore2) {} @@ -269,6 +315,7 @@ private void connect() { pongCount = PONGMAXCOUNT; aliveLock.notifyAll(); timer.scheduleAtFixedRate(clientPingTask, 0, 5000); + view.nodeReconnected(); } } diff --git a/src/main/java/it/polimi/ingsw/am32/network/ServerNode/RMIServerNode.java b/src/main/java/it/polimi/ingsw/am32/network/ServerNode/RMIServerNode.java index 512f5767..9d10a84e 100644 --- a/src/main/java/it/polimi/ingsw/am32/network/ServerNode/RMIServerNode.java +++ b/src/main/java/it/polimi/ingsw/am32/network/ServerNode/RMIServerNode.java @@ -86,8 +86,22 @@ public void uploadToClient(StoCMessage message) throws UploadFailureException { clientNode.uploadStoC(message); logger.info("StoCMessage sent to client: {}", message.toString()); - } catch (RemoteException e) { // TODO gestire errore RMI interfaccia client?? + } catch (RemoteException e) { + + synchronized (aliveLock) { + statusIsAlive = false; + } logger.error("Failed to send StoCMessage to client: {}", e.getMessage()); + config.getExecutorService().submit(this::destroy); + throw new UploadFailureException(); + + } catch (NodeClosedException e) { + + synchronized (aliveLock) { + statusIsAlive = false; + } + logger.info("Failed to send StoCMessage to client because client node is closed"); + config.getExecutorService().submit(this::destroy); throw new UploadFailureException(); } } @@ -101,9 +115,11 @@ public void pingTimeOverdue() { pingCount--; + logger.debug("Ping time overdue. Ping count: {}", pingCount); + if(pingCount <= 0){ statusIsAlive = false; - logger.debug("Ping time overdue, set statusIsAlive to false"); + logger.debug("Ping count reached minimum, starting destruction process"); } } @@ -135,8 +151,6 @@ public void destroy() { serverPingTask.cancel(); } - - synchronized (ctoSProcessingLock) { synchronized (stoCProcessingLock) { @@ -159,7 +173,7 @@ public void destroy() { public void setGameController(GameController gameController) { this.gameController = gameController; - // TODO controllare se il timer può fallire a runtime (controllare con gamecontroller) + gameController.getTimer().scheduleAtFixedRate(serverPingTask, 0, Configuration.getInstance().getPingTimeInterval()); } diff --git a/src/main/java/it/polimi/ingsw/am32/network/ServerNode/SKServerNode.java b/src/main/java/it/polimi/ingsw/am32/network/ServerNode/SKServerNode.java index 55fd3ea7..05083f80 100644 --- a/src/main/java/it/polimi/ingsw/am32/network/ServerNode/SKServerNode.java +++ b/src/main/java/it/polimi/ingsw/am32/network/ServerNode/SKServerNode.java @@ -22,6 +22,7 @@ import java.net.Socket; import java.net.SocketException; import java.net.SocketTimeoutException; +import java.util.Arrays; public class SKServerNode implements Runnable, NodeInterface { @@ -125,10 +126,15 @@ public void run() { } } catch (IOException | ClassNotFoundException e) { + logger.error("Critical ObjectInputStream error while reading.\n" + + "Exception message: {}\n" + + "Exception local message: {}\n" + + "Stack Trace: {}\n", + e.getMessage(), e.getLocalizedMessage(), Arrays.toString(e.getStackTrace())); + + //TODO risolvere meglio gli errori destroy(); - logger.error("Critical ObjectInputStream error while reading: {}" + - " . Socket Closed", e.getMessage()); //TODO risolvere meglio gli errori } catch (NodeClosedException e) { return; } @@ -259,6 +265,7 @@ public void uploadToClient(StoCMessage msg) throws UploadFailureException { logger.info("StoCMessage sent to client: {}", msg.toString()); } catch (IOException e) { + logger.error("Failed to send StoCMessage to client: {}", e.getMessage()); destroy(); @@ -348,7 +355,7 @@ public void destroy(){ serverPingTask = null; notLinkedPingTask = null; - logger.info("SKServerNode destroyed"); + logger.info("SKServerNode destroyed: Stack Trace" + Arrays.toString(Thread.currentThread().getStackTrace())); config.purgeTimer(); } } diff --git a/src/main/java/it/polimi/ingsw/am32/utilities/IPAddressFinder.java b/src/main/java/it/polimi/ingsw/am32/utilities/IPAddressFinder.java new file mode 100644 index 00000000..19025f3c --- /dev/null +++ b/src/main/java/it/polimi/ingsw/am32/utilities/IPAddressFinder.java @@ -0,0 +1,43 @@ +package it.polimi.ingsw.am32.utilities; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This class is used to find all IPv4 addresses of the current machine. + */ +public class IPAddressFinder { + + /** + * This method returns a list of all IPv4 addresses of the current machine. + * It iterates over all network interfaces and their associated addresses. + * If an address is an instance of Inet4Address, it is added to the list. + * + * @return A list of strings representing the IPv4 addresses. + */ + public static List getIPv4Addresses() { + // Create an empty list of strings to store the IPv4 addresses. + List ipv4Addresses = new ArrayList<>(); + try { + // Iterate over all network interfaces. + for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) { + // Iterate over all addresses associated with the current network interface. + for (InetAddress inetAddress : Collections.list(networkInterface.getInetAddresses())) { + // If the address is an instance of Inet4Address, add it to the list. + if (inetAddress instanceof Inet4Address) { + ipv4Addresses.add(inetAddress.getHostAddress()); + } + } + } + } catch (SocketException ignored) { + // If an exception occurs, the list of addresses will be empty. + } + return ipv4Addresses; + } + +} diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 11e8d793..abd8e489 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,3 +1,6 @@ +/** + * This module is the main module of the project. + */ module it.polimi.ingsw.am32 { requires javafx.controls; requires javafx.fxml; diff --git a/src/main/resources/it/polimi/ingsw/am32/client/view/gui/codexNaturalis.png b/src/main/resources/it/polimi/ingsw/am32/client/view/gui/codexNaturalis.png new file mode 100644 index 00000000..65aafc68 Binary files /dev/null and b/src/main/resources/it/polimi/ingsw/am32/client/view/gui/codexNaturalis.png differ