diff --git a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java index 70cc100..8e39e4a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java +++ b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java @@ -26,6 +26,9 @@ public class ClientController { /** Network client (either TCP or RMI) */ private IClient client; + /** + * The username of the client associated with this event. + */ public String myUsername; @@ -65,6 +68,11 @@ public class ClientController { view.setModel(miniModel); } + /** + * Sets the username of the client associated with this event. + * + * @param username the username to set. + */ public void setMyUsername (String username) { this.myUsername=username; } @@ -170,7 +178,16 @@ public class ClientController { } } - //TODO + /** + * Handles the selection of a totem by the specified player. + * + *
If the player is not the current one, an error message is shown.
+ * Otherwise, the selected totem is retrieved from the available totems
+ * and the choice is forwarded to the client.
+ *
+ * @param playerUsername the username of the player making the choice.
+ * @param pos the position of the selected totem in the available totems list.
+ */
public void totemChoice(String playerUsername,int pos) {
if(!Objects.equals(playerUsername, miniModel.currentState.getCurrentPlayer().getUserName()))
view.showError("It's not your turn!");
diff --git a/src/main/java/it/polimi/ingsw/gc14/Controller/GameController.java b/src/main/java/it/polimi/ingsw/gc14/Controller/GameController.java
index 0a5ade5..382b2f6 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Controller/GameController.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Controller/GameController.java
@@ -30,7 +30,14 @@ public class GameController {
*/
public GameController() {
}
- //TODO
+
+ /**
+ * Marks the player associated with the specified username as disconnected.
+ *
+ * @param username the username of the player who disconnected.
+ * @return {@code true} if the disconnection is handled successfully,
+ * {@code false} if no player with the specified username exists.
+ */
public boolean DisconnectedPlayer(String username)
{
Player player= model.getPlayerByUsername(username);
@@ -38,7 +45,14 @@ public class GameController {
return false;
return model.DisconnectedPlayer(player);
}
- //TODO
+
+ /**
+ * Marks the player associated with the specified username as reconnected.
+ *
+ * @param username the username of the player who reconnected.
+ * @return {@code true} if the reconnection is handled successfully,
+ * {@code false} if no player with the specified username exists.
+ */
public boolean ReconnectPlayer(String username)
{
Player player= model.getPlayerByUsername(username);
@@ -46,6 +60,7 @@ public class GameController {
return false;
return model.ReconnectPlayer(player);
}
+
/**
* Returns the game model managed by this controller.
*
@@ -166,7 +181,14 @@ public class GameController {
return model.SlotChoiceByIndex(model.getPlayerByUsername(playerUsername),pos);
}
- //TODO
+ /**
+ * Applies the totem choice made by the player associated with the specified username.
+ *
+ * @param playerUsername the username of the player making the choice.
+ * @param totem the name of the selected totem.
+ * @return {@code true} if the choice is handled successfully,
+ * {@code false} if no player with the specified username exists.
+ */
public boolean TotemChoice(String playerUsername,String totem) {
Player player= model.getPlayerByUsername(playerUsername);
if(player==null)
diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/EffectType.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/EffectType.java
index ed7ba06..6377ae2 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/EffectType.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/Building/EffectType.java
@@ -4,5 +4,34 @@ package it.polimi.ingsw.gc14.Model.Cards.Building;
* Represents the possible effect types of building cards.
*/
public enum EffectType {
- FINAL, CARD_SET, INVENTOR_PAIR, ON_EVENT, ON_END_TURN, ON_ROUND_END
-}
+
+ /**
+ * Effect applied during the final scoring phase.
+ */
+ FINAL,
+
+ /**
+ * Effect based on collecting a specific set of cards.
+ */
+ CARD_SET,
+
+ /**
+ * Effect based on pairs of Inventor cards.
+ */
+ INVENTOR_PAIR,
+
+ /**
+ * Effect triggered when an event card is resolved.
+ */
+ ON_EVENT,
+
+ /**
+ * Effect triggered at the end of a player's turn.
+ */
+ ON_END_TURN,
+
+ /**
+ * Effect triggered at the end of a round.
+ */
+ ON_ROUND_END
+ }
diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/CharacterType.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/CharacterType.java
index 68f3962..f86db05 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/CharacterType.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/CharacterType.java
@@ -4,5 +4,34 @@ package it.polimi.ingsw.gc14.Model.Cards.TribeCards;
* Represents the different types of character cards available in the game.
*/
public enum CharacterType {
- INVENTOR, BUILDER, GATHERER, ARTIST, SHAMAN, HUNTER
+
+ /**
+ * Character card representing an Inventor.
+ */
+ INVENTOR,
+
+ /**
+ * Character card representing a Builder.
+ */
+ BUILDER,
+
+ /**
+ * Character card representing a Gatherer.
+ */
+ GATHERER,
+
+ /**
+ * Character card representing an Artist.
+ */
+ ARTIST,
+
+ /**
+ * Character card representing a Shaman.
+ */
+ SHAMAN,
+
+ /**
+ * Character card representing a Hunter.
+ */
+ HUNTER
}
diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventType.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventType.java
index 1b6720a..9752352 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventType.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventType.java
@@ -4,5 +4,24 @@ package it.polimi.ingsw.gc14.Model.Cards.TribeCards;
* Represents the different types of event cards available in the game.
*/
public enum EventType {
- SUSTENANCE, SHAMANIC_RITUAL, CAVE_PAINTINGS, HUNT
-}
+
+ /**
+ * Event card representing Sustenance.
+ */
+ SUSTENANCE,
+
+ /**
+ * Event card representing the Shamanic Ritual.
+ */
+ SHAMANIC_RITUAL,
+
+ /**
+ * Event card representing Cave Paintings.
+ */
+ CAVE_PAINTINGS,
+
+ /**
+ * Event card representing the Hunt.
+ */
+ HUNT
+ }
\ No newline at end of file
diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java
index 7a56903..47ba0c1 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java
@@ -29,11 +29,20 @@ import java.util.stream.Stream;
*/
public class Game implements Serializable {
-
+ /**
+ * The final ranking of players at the end of the game.
+ */
private ArrayList The choice is accepted only if the game is currently in the
+ * {@link GameStages#TOTEM_CHOICE} stage, the player is the current one,
+ * and the selected totem is still available.
+ *
+ * After a valid choice, the method advances to the next player in the queue.
+ * If all players have completed the selection, the game moves to the slot choice phase.
+ * Disconnected players are automatically assigned a random available totem.
+ *
+ * @param player the player making the totem choice.
+ * @param totem the selected totem.
+ * @return {@code true} if the choice is applied successfully, {@code false} otherwise.
+ */
public boolean TotemChoice(Player player,Totems totem) {
if(!currentState.getGameStage().equals(GameStages.TOTEM_CHOICE))
return false;
@@ -87,9 +118,23 @@ public class Game implements Serializable {
return true;
}
- //TODO
+ /**
+ * Map tracking the players who are currently disconnected.
+ */
public Map If the player disconnects during the waiting phase, they are removed from
+ * the player list and from the totem choice queue. If the disconnected player is
+ * the current one, the game advances to the next suitable player or, during the
+ * totem choice phase, handles the remaining selection flow automatically.
+ *
+ * @param player the player who disconnected.
+ * @return {@code true} if the disconnection is handled successfully,
+ * {@code false} if the player was already marked as disconnected.
+ */
public boolean DisconnectedPlayer(Player player)
{
if(disconnetedPlayers.containsKey(player) && disconnetedPlayers.get(player))
@@ -121,7 +166,17 @@ public class Game implements Serializable {
return true;
}
- //TODO
+ /**
+ * Marks the specified player as reconnected.
+ *
+ * If the player reconnects during the slot choice phase, they are removed
+ * from the disconnected players map and reinserted into the order logic card
+ * when necessary.
+ *
+ * @param player the player who reconnected.
+ * @return {@code true} if the reconnection is handled successfully,
+ * {@code false} if the player was not previously marked as disconnected.
+ */
public boolean ReconnectPlayer(Player player)
{
if(!disconnetedPlayers.containsKey(player))
@@ -140,12 +195,14 @@ public class Game implements Serializable {
return true;
}
- //Totem
- //TODO
+ /**
+ * Clears the collection of disconnected players.
+ */
public void ClearDisconnected()
{
disconnetedPlayers.clear();
}
+
/**
* Returns the current number of players participating in the game.
* @return the current number of players.
@@ -195,7 +252,12 @@ public class Game implements Serializable {
* The board associated with this game.
*/
private Board board;
- //TODO
+
+ /**
+ * Returns the game board.
+ *
+ * @return the board associated with the game.
+ */
public Board getBoard() {return board;}
/**
@@ -925,6 +987,13 @@ public class Game implements Serializable {
return true;
}
+ /**
+ * Ends the game by forfeit and determines the final player standing.
+ *
+ * The player who is still connected is declared the winner and placed
+ * in the first position of the final ranking. The remaining players are
+ * ordered by prestige value and, in case of a tie, by food value.
+ */
public void EndGameForFeit() {
Player winner=playersList.stream().filter(x->!disconnetedPlayers.containsValue(x)||!disconnetedPlayers.get(x)).toList().get(0);
currentState.GameStageUpdate(GameStages.ENDED);
diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/GameStages.java b/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/GameStages.java
index c0ba67e..fad51b1 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/GameStages.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/GameStages.java
@@ -4,5 +4,43 @@ package it.polimi.ingsw.gc14.Model.GamePackage;
* Represents the possible stages of a game.
*/
public enum GameStages {
- WAITING,TOTEM_CHOICE, SLOT_CHOICE, RES_ACTIONS, OPT_CARD_E, RES_EVENT, ENDING, ENDED
-}
+ /**
+ * Stage in which the game is waiting for players to join.
+ */
+ WAITING,
+
+ /**
+ * Stage in which players choose their totems.
+ */
+ TOTEM_CHOICE,
+
+ /**
+ * Stage in which players select their action slots.
+ */
+ SLOT_CHOICE,
+
+ /**
+ * Stage in which the mandatory actions associated with the chosen slots are resolved.
+ */
+ RES_ACTIONS,
+
+ /**
+ * Stage in which an optional card effect can be resolved.
+ */
+ OPT_CARD_E,
+
+ /**
+ * Stage in which an event card is being resolved.
+ */
+ RES_EVENT,
+
+ /**
+ * Stage in which end-of-round or end-of-game operations are processed.
+ */
+ ENDING,
+
+ /**
+ * Stage indicating that the game has ended.
+ */
+ ENDED
+ }
diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Totems.java b/src/main/java/it/polimi/ingsw/gc14/Model/Totems.java
index ea459e1..c15fbd1 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Model/Totems.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Model/Totems.java
@@ -1,5 +1,32 @@
package it.polimi.ingsw.gc14.Model;
+/**
+ * Represents the different totem colors available in the game.
+ */
public enum Totems {
- YELLOW, BLUE, ORANGE, WHITE, PURPLE
+
+ /**
+ * Yellow totem.
+ */
+ YELLOW,
+
+ /**
+ * Blue totem.
+ */
+ BLUE,
+
+ /**
+ * Orange totem.
+ */
+ ORANGE,
+
+ /**
+ * White totem.
+ */
+ WHITE,
+
+ /**
+ * Purple totem.
+ */
+ PURPLE
}
\ No newline at end of file
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/EventType.java b/src/main/java/it/polimi/ingsw/gc14/Network/EventType.java
index a1f8fe4..535e400 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/EventType.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/EventType.java
@@ -5,16 +5,64 @@ package it.polimi.ingsw.gc14.Network;
* client and server.
*/
public enum EventType {
- ADD_PLAYER,
+
+ /**
+ * Event used to add a player to the game.
+ */
+ ADD_PLAYER,
+
+ /**
+ * Event used to submit a player's totem choice.
+ */
TOTEM_CHOICE,
- SLOT_CHOICE,
- DRAW_UPPER_TRIBE,
- DRAW_LOWER_TRIBE,
- DRAW_UPPER_BUILD,
- DRAW_LOWER_BUILD,
+
+ /**
+ * Event used to submit a player's slot choice.
+ */
+ SLOT_CHOICE,
+
+ /**
+ * Event used to draw a tribe card from the upper card list.
+ */
+ DRAW_UPPER_TRIBE,
+
+ /**
+ * Event used to draw a tribe card from the lower card list.
+ */
+ DRAW_LOWER_TRIBE,
+
+ /**
+ * Event used to draw a building card from the upper card list.
+ */
+ DRAW_UPPER_BUILD,
+
+ /**
+ * Event used to draw a building card from the lower card list.
+ */
+ DRAW_LOWER_BUILD,
+
+ /**
+ * Event used to skip the current turn or optional action.
+ */
SKIP_TURN,
- DISCONNECTED_PLAYER,
- RECONNECT_PLAYER,
+
+ /**
+ * Event used to notify that a player has disconnected.
+ */
+ DISCONNECTED_PLAYER,
+
+ /**
+ * Event used to notify that a player has reconnected.
+ */
+ RECONNECT_PLAYER,
+
+ /**
+ * Event used to apply the transition to the next round.
+ */
NEXT_ROUND,
+
+ /**
+ * Event used to notify that the game has ended.
+ */
ENDED_GAME
-}
+ }
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java
index c633910..43704e2 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java
@@ -1,25 +1,73 @@
package it.polimi.ingsw.gc14.Network;
-import it.polimi.ingsw.gc14.Network.NetworkEvents.*;
-
-import java.rmi.RemoteException;
-import java.util.Objects;
-
+/**
+ * Defines the operations that a client can request during the game.
+ */
public interface IClient {
- public boolean connect(String username,int preferredInt);
- public void drawUpperTribeCard(String playerUsername, int pos) ;
+ /**
+ * Connects the client to the server using the specified username
+ * and preferred connection type.
+ *
+ * @param username the username chosen by the player.
+ * @param preferredInt the preferred connection type selected by the client.
+ * @return {@code true} if the connection is established successfully,
+ * {@code false} otherwise.
+ */
+ boolean connect(String username, int preferredInt);
- public void drawLowerTribeCard(String playerUsername,int pos) ;
+ /**
+ * Requests to draw a tribe card from the upper tribe card list.
+ *
+ * @param playerUsername the username of the player performing the action.
+ * @param pos the position of the selected card in the upper tribe card list.
+ */
+ void drawUpperTribeCard(String playerUsername, int pos);
- public void drawUpperBuildingCard(String playerUsername,int pos) ;
+ /**
+ * Requests to draw a tribe card from the lower tribe card list.
+ *
+ * @param playerUsername the username of the player performing the action.
+ * @param pos the position of the selected card in the lower tribe card list.
+ */
+ void drawLowerTribeCard(String playerUsername, int pos);
+ /**
+ * Requests to draw a building card from the upper building card list.
+ *
+ * @param playerUsername the username of the player performing the action.
+ * @param pos the position of the selected card in the upper building card list.
+ */
+ void drawUpperBuildingCard(String playerUsername, int pos);
- public void drawLowerBuildingCard(String playerUsername,int pos) ;
+ /**
+ * Requests to draw a building card from the lower building card list.
+ *
+ * @param playerUsername the username of the player performing the action.
+ * @param pos the position of the selected card in the lower building card list.
+ */
+ void drawLowerBuildingCard(String playerUsername, int pos);
- public void skipTurn(String playerUsername);
-
+ /**
+ * Requests to skip the current player's optional action.
+ *
+ * @param playerUsername the username of the player skipping the action.
+ */
+ void skipTurn(String playerUsername);
- public void slotChoice(String playerUsername,int pos) ;
- public void totemChoice(String playerUsername,String totem) ;
+ /**
+ * Requests to assign the specified player to a slot.
+ *
+ * @param playerUsername the username of the player making the slot choice.
+ * @param pos the position of the selected slot.
+ */
+ void slotChoice(String playerUsername, int pos);
+
+ /**
+ * Requests to assign the selected totem to the specified player.
+ *
+ * @param playerUsername the username of the player making the totem choice.
+ * @param totem the name of the selected totem.
+ */
+ void totemChoice(String playerUsername, String totem);
}
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvent.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvent.java
index aeacecd..d5eecad 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvent.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvent.java
@@ -11,59 +11,113 @@ import java.io.Serializable;
import java.util.Map;
/**
- * Represents an event sent over the network
+ * Represents an event sent over the network.
+ *
+ * A network event contains the information required to identify
+ * the requested action, determine whether it produced an error,
+ * and apply it either to the server-side {@link GameController}
+ * or to the client-side {@link MiniModel}.
*/
public abstract class NetworkEvent implements Serializable {
- /** Username of the player requesting the event */
+
+ /**
+ * Username of the player requesting the event.
+ */
protected String username;
/**
- * @return the username of the player requesting the event
+ * Returns the username of the player requesting the event.
+ *
+ * @return the username associated with the event.
*/
public String getUsername() {
return username;
}
- /** EventType of the event */
+ /**
+ * Type of the network event.
+ */
protected EventType eventType;
+ /**
+ * Map associating each occupied slot with the corresponding player.
+ */
protected Map If the event does not represent an error, the player data,
+ * turn order, current game state, and slot assignments are updated.
+ *
+ * @param miniModel the mini model on which to apply the event.
+ * @return {@code true} if the update is applied successfully,
+ * {@code false} if the event represents an error.
+ */
@Override
- public boolean apply(MiniModel miniModel){
- if(isError)
+ public boolean apply(MiniModel miniModel) {
+ if (isError)
return false;
- if(miniModel!=null) {
+
+ if (miniModel != null) {
miniModel.setPlayer(player);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
}
+
return true;
}
-
}
\ No newline at end of file
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/TotemChoice.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/TotemChoice.java
index e911423..04ace18 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/TotemChoice.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/TotemChoice.java
@@ -5,49 +5,78 @@ import it.polimi.ingsw.gc14.Model.MiniModel;
import it.polimi.ingsw.gc14.Model.Totems;
import it.polimi.ingsw.gc14.Network.EventType;
import it.polimi.ingsw.gc14.Network.NetworkEvent;
-import it.polimi.ingsw.gc14.View.IView;
import java.io.Serializable;
import java.util.List;
/**
- * NetworkEvent to select a slot where to place the player totem.
+ * Network event used to handle a player's totem choice.
*/
-public class TotemChoice extends NetworkEvent implements Serializable {
+public class TotemChoice extends NetworkEvent implements Serializable {
- /** Index of the card to draw */
+ /**
+ * Name of the totem selected by the player.
+ */
private String totem;
- private List If the event does not represent an error, the player data,
+ * turn order, current game state, slot assignments, and available
+ * totems are updated.
+ *
+ * @param miniModel the mini model on which to apply the event.
+ * @return {@code true} if the update is applied successfully,
+ * {@code false} if the event represents an error.
+ */
@Override
- public boolean apply(MiniModel miniModel){
- if(isError)
+ public boolean apply(MiniModel miniModel) {
+ if (isError)
return false;
+
miniModel.setPlayer(player);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
miniModel.setAvailableTotems(availableTotems);
return true;
-
}
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java
index 313e605..44f425a 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java
@@ -1,18 +1,13 @@
package it.polimi.ingsw.gc14.Network.RMI.Client;
-import java.net.InetAddress;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
-import java.util.Objects;
import java.util.concurrent.*;
import it.polimi.ingsw.gc14.Controller.ClientController;
import it.polimi.ingsw.gc14.Network.IClient;
-import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.Network.NetworkEvents.*;
-import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback;
import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer;
-import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer;
/**
* Client RMI. Uses the methods exposed by the server RMI.
@@ -34,7 +29,14 @@ public class RMIClient implements IClient {
/** Scheduler that fires ping() every PING_INTERVAL_S seconds. */
private ScheduledExecutorService pingSender;
-
+ /**
+ * Constructs an RMI client and initializes its connection parameters.
+ *
+ * @param controller the client controller associated with this RMI client.
+ * @param host the hostname or IP address of the RMI server.
+ * @param port the port used to connect to the RMI registry.
+ * @param myIP the IP address of the client.
+ */
public RMIClient(ClientController controller, String host, int port, String myIP) {
this.controller = controller;
this.host = host;
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java
index c68c5b9..e09a065 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IClientCallback.java
@@ -21,7 +21,7 @@ public interface IClientCallback extends Remote, Serializable {
/**
* Notifies the client that the game model has been initialized or updated.
*
- * @param model the current game model.
+ * @param miniModel the current mini model of the game.
* @throws RemoteException if an RMI communication error occurs.
*/
void onGameInit(MiniModel miniModel) throws RemoteException;
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java
index 64177ab..aef508d 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Common/IGameServer.java
@@ -1,7 +1,5 @@
package it.polimi.ingsw.gc14.Network.RMI.Common;
-import it.polimi.ingsw.gc14.Network.NetworkEvent;
-
import java.rmi.*;
/**
@@ -9,22 +7,89 @@ import java.rmi.*;
*/
public interface IGameServer extends Remote {
+ /**
+ * Adds a player to the game and registers the callback used by the server
+ * to notify the corresponding RMI client.
+ *
+ * @param username the username chosen by the player.
+ * @param preferredInt the preferred number of players for the game.
+ * @param callback the remote callback associated with the client.
+ * @return {@code true} if the player joins the game successfully,
+ * {@code false} otherwise.
+ * @throws RemoteException if an RMI communication error occurs.
+ */
boolean joinGame(String username, int preferredInt, IClientCallback callback) throws RemoteException;
- boolean doEvent(NetworkEvent event) throws RemoteException;
-
- void drawUpperTribeCard(String playerUsername, int pos) throws RemoteException;
- void drawLowerTribeCard(String playerUsername, int pos) throws RemoteException;
- void drawUpperBuildingCard(String playerUsername, int pos) throws RemoteException;
- void drawLowerBuildingCard(String playerUsername, int pos) throws RemoteException;
- void skipTurn(String playerUsername) throws RemoteException;
- void slotChoice(String playerUsername, int pos) throws RemoteException;
- void totemChoice(String playerUsername, String totems) throws RemoteException;
/**
- * Heartbeat: called periodically by the client to signal it is still alive.
- * Mirrors the PING/PONG mechanism used in the TCP heartbeat channel.
+ * Requests to draw a tribe card from the upper tribe card list.
*
- * @param username the username of the client sending the ping.
+ * @param playerUsername the username of the player performing the action.
+ * @param pos the position of the selected card.
+ * @throws RemoteException if an RMI communication error occurs.
+ */
+ void drawUpperTribeCard(String playerUsername, int pos) throws RemoteException;
+
+ /**
+ * Requests to draw a tribe card from the lower tribe card list.
+ *
+ * @param playerUsername the username of the player performing the action.
+ * @param pos the position of the selected card.
+ * @throws RemoteException if an RMI communication error occurs.
+ */
+ void drawLowerTribeCard(String playerUsername, int pos) throws RemoteException;
+
+ /**
+ * Requests to draw a building card from the upper building card list.
+ *
+ * @param playerUsername the username of the player performing the action.
+ * @param pos the position of the selected card.
+ * @throws RemoteException if an RMI communication error occurs.
+ */
+ void drawUpperBuildingCard(String playerUsername, int pos) throws RemoteException;
+
+ /**
+ * Requests to draw a building card from the lower building card list.
+ *
+ * @param playerUsername the username of the player performing the action.
+ * @param pos the position of the selected card.
+ * @throws RemoteException if an RMI communication error occurs.
+ */
+ void drawLowerBuildingCard(String playerUsername, int pos) throws RemoteException;
+
+ /**
+ * Requests to skip the current player's optional action.
+ *
+ * @param playerUsername the username of the player skipping the action.
+ * @throws RemoteException if an RMI communication error occurs.
+ */
+ void skipTurn(String playerUsername) throws RemoteException;
+
+ /**
+ * Requests to assign the specified player to a slot.
+ *
+ * @param playerUsername the username of the player making the slot choice.
+ * @param pos the position of the selected slot.
+ * @throws RemoteException if an RMI communication error occurs.
+ */
+ void slotChoice(String playerUsername, int pos) throws RemoteException;
+
+ /**
+ * Requests to assign the selected totem to the specified player.
+ *
+ * @param playerUsername the username of the player making the totem choice.
+ * @param totems the name of the selected totem.
+ * @throws RemoteException if an RMI communication error occurs.
+ */
+ void totemChoice(String playerUsername, String totems) throws RemoteException;
+
+ /**
+ * Heartbeat method called periodically by the client to signal
+ * that it is still connected.
+ *
+ * This method mirrors the PING/PONG mechanism used in the TCP
+ * heartbeat channel.
+ *
+ * @param username the username of the client sending the heartbeat ping.
* @throws RemoteException if an RMI communication error occurs.
*/
void ping(String username) throws RemoteException;
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIHeartbeat.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIHeartbeat.java
index e9ee1f0..f164565 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIHeartbeat.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIHeartbeat.java
@@ -1,7 +1,6 @@
package it.polimi.ingsw.gc14.Network.RMI.Server;
import it.polimi.ingsw.gc14.LimitedMap;
-import it.polimi.ingsw.gc14.Model.Game;
import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.Network.NetworkEvents.DisconnectedPlayer;
@@ -15,14 +14,13 @@ import java.util.concurrent.*;
* instead of reading raw bytes from a dedicated socket, it relies on {@link #receivePing()}
* being called by {@link RMIServer#ping(String)} every time the client sends a ping.
*
- * If no ping is received within {@value SILENCE_THRESHOLD_MS} ms the player is
+ * If no ping is received within {@value SILENCE_THRESHOLD_MS} ms, the player is
* considered disconnected and {@link #disconnect()} is invoked, which:
* The heartbeat handler is stopped, the player is marked as offline,
+ * the associated RMI callback is removed, and a disconnection event is
+ * added to the action queue for server-side processing.
*/
- public void setGame(Game game) {
- this.game = game;
- }
-
- // -------------------------------------------------------------------------
-
private void disconnect() {
if (!running) return;
running = false;
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java
index 1f8110b..5c10a9a 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java
@@ -21,7 +21,12 @@ import java.rmi.*;
/**
- * Server RMI. Exposes a method to join the game and one to execute an event.
+ * RMI server responsible for handling remote client connections,
+ * receiving player actions, and propagating game updates.
+ *
+ * The server manages player registration, reconnection handling,
+ * heartbeat monitoring, and the forwarding of client requests to the
+ * shared network event queue.
*/
public class RMIServer extends UnicastRemoteObject implements IGameServer {
private String host;
@@ -43,10 +48,26 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
private LimitedMap If the event does not represent an error, it is sent to all registered clients.
+ * If it represents an error, it is sent only to the client that requested the action.
+ * Communication errors are logged without interrupting the notification process.
+ *
+ * @param action the network event to send to the clients.
*/
public void notifyAll(NetworkEvent action){
for (Map.Entry The updated mini model is sent to each registered client callback.
+ * If a communication error occurs for a client, the exception is logged
+ * without interrupting the notification of the remaining clients.
+ *
+ * @param model the updated mini model to send to the connected clients.
*/
public void notifyAll(MiniModel model) {
- // Keep every watchdog's game reference up to date
- synchronized (controller){
- watchdogs.values().forEach(wd -> wd.setGame(controller.getModel()));
- }
for (IClientCallback cb : clients.values()) {
try{
cb.onGameInit(model);
@@ -188,17 +213,6 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
}
}
-
-
- /**
- * Push an action in actionQueue.
- * @param action The desired actio
- * @return true if the action was successfully added, false otherwise
- */
- public boolean doEvent(NetworkEvent action) {
- return actionQueue.offer(action);
- }
-
/**
* Requests to draw a tribe card from the upper list.
* Creates a NetworkEvent and sends it through the network client.
@@ -269,10 +283,17 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
}
- // Metodi per avviare server RMI
/**
- * Starts the RMI server.
- * @return true if the server starts successfully, false otherwise
+ * Starts the RMI server and binds it to the configured registry.
+ *
+ * The method configures the server hostname, creates the RMI registry
+ * on the specified port, and registers this server instance under the
+ * {@code RMIGameServer} name.
+ *
+ * @param serverCrashed {@code true} if the server is being restarted after a crash,
+ * {@code false} otherwise.
+ * @return {@code true} if the server starts successfully,
+ * {@code false} otherwise.
*/
public boolean start(boolean serverCrashed) {
this.serverCrashed = serverCrashed;
@@ -288,12 +309,21 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
}
}
+ /**
+ * Stops the RMI server and removes its binding from the registry.
+ *
+ * The remote server object is unexported, the registry entry associated
+ * with {@code RMIGameServer} is removed, and the server shutdown is logged.
+ *
+ * @return {@code true} if the server is stopped successfully,
+ * {@code false} otherwise.
+ */
public boolean stop() {
try {
registry.unbind("RMIGameServer");
UnicastRemoteObject.unexportObject(this, true);
watchdogs.values().forEach(wd -> { /* watchdogs shut themselves down */ });
- System.out.println("RMI Server fermato");
+ System.out.println("RMI Server stopped");
return true;
} catch (RemoteException | NotBoundException e) {
e.printStackTrace();
@@ -303,17 +333,13 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
/**
- * Creates and starts a {@link RMIHeartbeat} for {@code username}.
- * Also seeds the watchdog with the current model if one already exists
- * (reconnection case).
+ * Creates and starts an {@link RMIHeartbeat} for the specified player.
+ *
+ * @param username the username of the player monitored by the heartbeat watchdog.
*/
private void startWatchdog(String username) {
RMIHeartbeat wd = new RMIHeartbeat(
username, playerList, clients, actionQueue);
- synchronized (controller)
- {
- if (controller.getModel() != null) wd.setGame(controller.getModel());
- }
watchdogs.put(username, wd);
wd.start();
}
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java
index efd91db..28598d4 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java
@@ -46,10 +46,12 @@ public class TCPClient implements IClient {
/**
- * Class constructor that initializes the attributes.
- * @param controller The game controller
- * @param hostname The IP address of the server
- * @param port The TCP port of the server
+ * Constructs a TCP client and initializes its connection parameters.
+ *
+ * @param controller the client controller.
+ * @param hostname the IP address or hostname of the server.
+ * @param mainPort the main TCP port of the server.
+ * @param heartbeatPort the TCP port used for heartbeat communication.
*/
public TCPClient(ClientController controller, String hostname, int mainPort,int heartbeatPort ) {
this.controller = controller;
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java
index 15773f7..8e36e01 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java
@@ -58,12 +58,13 @@ public class ClientHandler implements Runnable {
/**
* Class constructor that initializes the attributes.
*
- * @param username the username associated with the client.
- * @param clientSocket the socket representing the client's TCP connection.
- * @param out the output stream used to send data to the client.
- * @param in the input stream used to receive data from the client.
+ * @param username the username associated with the client.
+ * @param clientSocket the socket representing the client's TCP connection.
+ * @param out the output stream used to send data to the client.
+ * @param in the input stream used to receive data from the client.
* @param clientHandlers the shared list of all active client handlers.
- * @param actionQueue the queue containing incoming events.
+ * @param playersMap the shared map containing the connected players.
+ * @param actionQueue the queue containing incoming events.
*/
public ClientHandler(String username, Socket clientSocket, ObjectOutputStream out, ObjectInputStream in, List The client handler is stopped and removed from the list of active handlers.
+ * The player is marked as disconnected, a {@link DisconnectedPlayer} event is
+ * added to the action queue, and the associated socket is closed.
+ */
public void disconnect() {
running = false;
clientHandlers.remove(this);
diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/HeartbeatHandler.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/HeartbeatHandler.java
index a0dde68..fdf9f8e 100644
--- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/HeartbeatHandler.java
+++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/HeartbeatHandler.java
@@ -4,12 +4,26 @@ import java.io.*;
import java.net.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
+/**
+ * Handles the heartbeat communication associated with a TCP client.
+ *
+ * This component listens for heartbeat {@code PING} messages from the client,
+ * replies with {@code PONG} messages, and periodically checks whether the client
+ * has remained silent for too long. If a timeout or communication error occurs,
+ * both the heartbeat connection and the main client connection are disconnected.
+ */
public class HeartbeatHandler implements Runnable {
+ /**
+ * Maximum allowed time without receiving heartbeat messages before disconnecting the client.
+ */
private static final long SILENCE_THRESHOLD_MS = 5_000;
+
+ /**
+ * Expected interval between heartbeat messages.
+ */
private static final long KEEPALIVE_INTERVAL_MS = 3_000;
private final String username;
@@ -17,18 +31,46 @@ public class HeartbeatHandler implements Runnable {
private final InputStream in;
private final OutputStream out;
+ /**
+ * Byte value representing a heartbeat ping message.
+ */
private static final int PING = 1;
+
+ /**
+ * Byte value representing a heartbeat pong response.
+ */
private static final int PONG = 2;
- // riferimento al ClientHandler principale per disconnetterlo insieme
+ /**
+ * Main client handler associated with this heartbeat connection.
+ */
private final ClientHandler mainHandler;
+ /**
+ * Timestamp of the last received heartbeat message.
+ */
private volatile long lastReceivedTime = System.currentTimeMillis();
+
+ /**
+ * Indicates whether the heartbeat handler is still active.
+ */
private volatile boolean running = true;
+
+ /**
+ * Executor used to periodically check heartbeat timeouts.
+ */
private final ScheduledExecutorService watchdog =
Executors.newSingleThreadScheduledExecutor();
+ /**
+ * Constructs a heartbeat handler for the specified client.
+ *
+ * @param username the username of the connected client.
+ * @param socket the socket dedicated to heartbeat communication.
+ * @param mainHandler the main client handler associated with the same player.
+ * @throws IOException if the input or output stream cannot be obtained from the socket.
+ */
public HeartbeatHandler(String username, Socket socket, ClientHandler mainHandler)
throws IOException {
this.username = username;
@@ -38,6 +80,14 @@ public class HeartbeatHandler implements Runnable {
this.out = socket.getOutputStream();
}
+ /**
+ * Starts the heartbeat listening loop.
+ *
+ * The method activates the watchdog task, then waits for incoming heartbeat
+ * messages. When a {@code PING} is received, the last-received timestamp is
+ * updated and a {@code PONG} response is sent back to the client.
+ * If the stream is closed or an I/O error occurs, the client is disconnected.
+ */
@Override
public void run() {
startWatchdog();
@@ -56,6 +106,12 @@ public class HeartbeatHandler implements Runnable {
}
}
+ /**
+ * Starts the periodic watchdog task that detects heartbeat timeouts.
+ *
+ * If no heartbeat message is received within the configured silence threshold,
+ * the associated client is disconnected.
+ */
private void startWatchdog() {
watchdog.scheduleAtFixedRate(() -> {
if (System.currentTimeMillis() - lastReceivedTime > SILENCE_THRESHOLD_MS) {
@@ -65,7 +121,12 @@ public class HeartbeatHandler implements Runnable {
}, 1, 1, TimeUnit.SECONDS);
}
-
+ /**
+ * Disconnects the heartbeat channel and the associated main client connection.
+ *
+ * The handler is stopped, the watchdog task is terminated, the main
+ * {@link ClientHandler} is disconnected, and the heartbeat socket is closed.
+ */
private void disconnect() {
running = false;
watchdog.shutdownNow();
diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java
index 64fd1e6..25b1f5e 100644
--- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java
+++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java
@@ -192,15 +192,26 @@ public class ServerLauncher {
/**
- * The first method executed when the server program is launched.
- * It creates all the objects needed: playerList, actionQueue, gameController, serverRMI, serverTCP, launcher.
- * Then sets the playerList's action to execute launcher.run() and starts the TCP/RMI servers.
- * Note: the model is initialized and set in the controller in TCP/RMI servers when the first user decides the number of players.
+ * Entry point of the server application.
*
- * @throws InterruptedException if this exception is issued by run method
- * @throws RemoteException if this exception is issued by run method
+ * The method initializes the shared player list, the network event queue,
+ * the game controller, the RMI server, the TCP server, and the server launcher.
+ * It also selects the network interface to expose, configures the server crash
+ * recovery state, and defines the action to execute once the required number
+ * of players has joined the game.
+ *
+ * When the player list reaches its limit, the current game model is converted
+ * into a {@link MiniModel}, sent to all connected clients through both RMI and TCP,
+ * and rendered on the server-side TUI. Finally, the event-processing launcher
+ * and both network servers are started.
+ *
+ * The game model itself is initialized by the TCP or RMI server when the first
+ * player joins and selects the total number of players.
+ *
+ * @param args the command-line arguments passed to the server application.
+ * @throws RemoteException if the RMI server cannot be created.
*/
- public static void main(String[] args) throws InterruptedException, RemoteException {
+ public static void main(String[] args) throws RemoteException {
playerList = new LimitedMap The method repeatedly processes the first event in the action queue
+ * and, when a view is available, updates the rendered game state.
+ *
+ * If the thread is interrupted while waiting for an event,
+ * the interruption status is restored and the loop terminates.
*/
public void run() {
while (true) {
@@ -282,6 +296,18 @@ public class ServerLauncher {
}
}
+ /**
+ * Lets the user choose the network interface to be used by the server.
+ *
+ * The method scans all active, non-loopback, and non-virtual network
+ * interfaces, collecting their IPv4 addresses. If only one valid address is
+ * found, it is selected automatically. Otherwise, the available addresses are
+ * printed and the user is asked to choose one by index.
+ *
+ * @param scanner the scanner used to read the user's selection.
+ * @return the IPv4 address of the selected network interface.
+ * @throws Exception if no valid network interface is available.
+ */
public static String chooseNetworkInterface(Scanner scanner) throws Exception {
List The save file is stored in the {@code GameSaves/save.dat} path relative
+ * to the server executable location. If the directory does not exist, it is
+ * created before writing the serialized game model.
+ *
+ * @return {@code true} if the game is saved successfully,
+ * {@code false} otherwise.
+ */
private boolean gameSave(){
try{
Path jarPath = Paths.get(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParent();
@@ -340,6 +376,16 @@ public class ServerLauncher {
}
}
+ /**
+ * Loads a previously saved game model from the local save file.
+ *
+ * The method attempts to deserialize the game stored in
+ * {@code GameSaves/save.dat}. If no save file exists or an I/O error occurs,
+ * {@code null} is returned.
+ *
+ * @return the loaded {@link Game} instance, or {@code null} if no valid save
+ * can be loaded.
+ */
private Game loadSave(){
try {
Path jarPath = Paths.get(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParent();
@@ -363,6 +409,12 @@ public class ServerLauncher {
}
}
+ /**
+ * Deletes the current local game save file.
+ *
+ * @return {@code true} if the save file is deleted successfully,
+ * {@code false} otherwise.
+ */
private boolean deleteSave(){
try{
Path jarPath = Paths.get(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParent();
diff --git a/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java b/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java
index 1241146..c9bd7b9 100644
--- a/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java
+++ b/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java
@@ -16,7 +16,6 @@ import javafx.stage.Screen;
import javafx.util.Duration;
import java.util.Locale;
-import java.util.Objects;
public class TotemFXMLController {
diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java
index 6914e40..504ee6e 100644
--- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java
+++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java
@@ -185,6 +185,13 @@ public class TUI implements IView {
System.out.println(AsciiTable.sideBySide(lines, lines2, 3));
}
+ /**
+ * Renders the available totems in the terminal interface.
+ *
+ * The method clears the terminal, builds a table containing the currently
+ * available totems together with their selection positions, and displays the
+ * instructions required to choose one.
+ */
public void renderTotems() {
clearTerminal();
var table = new AsciiTable(BorderStyle.ROUNDED, model.availableTotems.size());
*
*/
public class RMIHeartbeat {
@@ -38,9 +36,6 @@ public class RMIHeartbeat {
private volatile long lastPingTime = System.currentTimeMillis();
private volatile boolean running = true;
- /** Reference to the current game model — needed to check whose turn it is. */
- private volatile Game game;
-
private final ScheduledExecutorService watchdog =
Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r, "rmi-watchdog-" + username);
@@ -48,6 +43,14 @@ public class RMIHeartbeat {
return t;
});
+ /**
+ * Constructs an RMI heartbeat handler for the specified client.
+ *
+ * @param username the username of the client monitored by the heartbeat.
+ * @param playerList the map storing the connection status of the players.
+ * @param clients the collection of currently registered RMI clients.
+ * @param actionQueue the queue containing network events to be processed.
+ */
public RMIHeartbeat(
String username,
LimitedMap