Add: JavaDOC in ServerLauncher

Fix: Action error handling in the entire network stack
Modified: TCP's broadcast methods name
This commit is contained in:
2026-04-25 17:34:28 +02:00
parent 59dd27f123
commit 3a8706603c
8 changed files with 100 additions and 52 deletions
@@ -12,34 +12,58 @@ import java.rmi.RemoteException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ServerLauncher {
/**
* Main server launcher that handles both TCP and RMI connections.
* The workflow is divided into two parts: game creation and game execution.
*
* The process flow for game creation is as follows:
* - The first client (TCP/RMI) requests to join the game by providing a username and the desired number of players
* - The TCP/RMI server checks {@link #playerList} and, if it is empty, sets the number of players according to the first user's request using {@link LimitedList#setLimit(int)}
* - The TCP/RMI server creates the {@link Game} with the requested number of players and adds the player to {@link #playerList}
* - Other players request to join the game (their requested number of players is ignored)
* - When the number of players in {@link #playerList} reaches the {@link LimitedList}'s limit, the list calls {@link #run()}
* - All players are notified with the {@link Game}
*
* The process flow for game execution is as follows:
* - The TCP/RMI server receives a {@link NetworkEvent} from a client and adds it to the {@link #actionQueue}
* - The {@link #run()} method repeatedly calls {@link #doFirstEvent()}, which takes the first event in the {@link #actionQueue} and tries to apply it
* - If the event is successfully applied to the model, all players receive the event
* - Otherwise, the player who sent the action receives an error notification
*/
/**
* Main server launcher that handles both TCP and RMI connections.
* The workflow is divided into two parts: game creation and game execution.
*
* The process flow for game creation is as follows:
* - The first client (TCP/RMI) requests to join the game by providing a username and the desired number of players
* - The TCP/RMI server checks {@link #playerList} and, if it is empty, sets the number of players according to the first user's request using {@link LimitedList#setLimit(int)}
* - The TCP/RMI server creates the {@link Game} with the requested number of players and adds the player to {@link #playerList}
* - Other players request to join the game (their requested number of players is ignored)
* - When the number of players in {@link #playerList} reaches the {@link LimitedList}'s limit, the list calls {@link #run()}
* - All players are notified with the {@link Game}
*
* The process flow for game execution is as follows:
* - The TCP/RMI server receives a {@link NetworkEvent} from a client and adds it to the {@link #actionQueue}
* - The {@link #run()} method repeatedly calls {@link #doFirstEvent()}, which takes the first event in the {@link #actionQueue} and tries to apply it
* - If the event is successfully applied to the model, all players receive the event
* - Otherwise, the player who sent the action receives an error notification
*/
public class ServerLauncher {
/**
* List containing the events that have to be applied to the game's model.
* Thread safe by design.
*/
BlockingQueue<NetworkEvent> actionQueue;
/** Game controller. Used to apply events */
GameController gameController;
/** Server RMI. Handles RMI clients */
RMIServer serverRMI;
/** Server TCP. Handles TCP clients */
TCPServer serverTCP;
/**
* List containing the username of joined players.
* {@link LimitedList}'s limit defines at which size the list calls its action
* Both limit and action can be set with {@link LimitedList#setLimit(int)} and {@link LimitedList#setAction(Runnable)}
* The limit is set by the first player joining the game. The action consists in calling {@link #run()}
*/
static LimitedList<String> playerList;
/**
* Class constructor that initializes the attributes.
* @param actionQueue is the list containing the events
* @param gameController is the game controller
* @param serverRMI is the server RMI
* @param serverTCP is the server TCP
*/
public ServerLauncher(BlockingQueue<NetworkEvent> actionQueue, GameController gameController, RMIServer serverRMI, TCPServer serverTCP) {
this.actionQueue = actionQueue;
this.serverRMI = serverRMI;
@@ -47,17 +71,22 @@ public class ServerLauncher {
this.serverTCP = serverTCP;
}
/**
* Takes the first event in the actionQueue and attempt to apply it to the game controller.
* If the event can be applied, all clients (both TCP and RMI) are notified with the event. Otherwise, the user who sent the action will be notified with an error.
* @return the outcome of attempting to apply the event to the controller
* @throws InterruptedException if any problem in accessing actionQueue is issued
* @throws RemoteException if any RMI problem is issued
*/
public boolean doFirstEvent() throws InterruptedException, RemoteException {
NetworkEvent event = actionQueue.take();
if(event.apply(gameController)) {
serverRMI.notifyAll(event);
serverTCP.broadcastUpdate(event);
return true;
} else {
serverRMI.notifyError(event.getUsername(), "Mossa non valida"); // TODO Converrebbe mettere in network event un booleano che dice se è stato accettato e fare una notifyAll anche per errori
//serverTCP // TODO non esiste un notify error (guarda sopra)
return false;
}
event.setIsError(!event.apply(gameController));
serverRMI.notifyAll(event);
serverTCP.notifAll(event);
return !event.getIsError();
}
@@ -91,7 +120,7 @@ public class ServerLauncher {
public void run() throws InterruptedException, RemoteException {
serverRMI.notifyAll(gameController.getModel());
serverTCP.broadcastModel(gameController.getModel());
serverTCP.notifyAll(gameController.getModel());
// Game execution