JavaDOC finished
This commit is contained in:
@@ -160,7 +160,14 @@ public class ClientLauncherTUI {
|
|||||||
view.setLineReader(gameReader);
|
view.setLineReader(gameReader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO
|
/**
|
||||||
|
* Reads login fields from the terminal and connects to the server.
|
||||||
|
*
|
||||||
|
* @param controller the client controller to connect.
|
||||||
|
* @param loginReader line reader used for username, player count, and network type.
|
||||||
|
* @param ipReader line reader with localhost auto-complete for the server IP.
|
||||||
|
* @return {@code true} on successful connection; {@code false} if input is invalid or connection fails.
|
||||||
|
*/
|
||||||
private boolean doLoginInner(ClientController controller, LineReader loginReader, LineReader ipReader) {
|
private boolean doLoginInner(ClientController controller, LineReader loginReader, LineReader ipReader) {
|
||||||
String username, networkStr, ip;
|
String username, networkStr, ip;
|
||||||
int nPlayers;
|
int nPlayers;
|
||||||
|
|||||||
@@ -33,15 +33,15 @@ import java.util.stream.Collectors;
|
|||||||
* thread via {@link #doFirstEvent()}.
|
* thread via {@link #doFirstEvent()}.
|
||||||
*/
|
*/
|
||||||
public class GameEventProcessor {
|
public class GameEventProcessor {
|
||||||
//TODO
|
/** Queue from which incoming client events are consumed one at a time. */
|
||||||
private final BlockingQueue<NetworkEvent> actionQueue;
|
private final BlockingQueue<NetworkEvent> actionQueue;
|
||||||
//TODO
|
/** Server-side game controller; all model mutations go through this. */
|
||||||
private final GameController gameController;
|
private final GameController gameController;
|
||||||
//TODO
|
/** Shared map tracking each player's online status ({@code true} = online). */
|
||||||
private final LimitedMap<String, Boolean> playerList;
|
private final LimitedMap<String, Boolean> playerList;
|
||||||
//TODO
|
/** Broadcaster used to push events and model snapshots to all connected clients. */
|
||||||
private final CompositeClientBroadcaster broadcaster;
|
private final CompositeClientBroadcaster broadcaster;
|
||||||
//TODO
|
/** Persists and deletes game save files. */
|
||||||
private final SaveManager saveManager;
|
private final SaveManager saveManager;
|
||||||
|
|
||||||
/** Single-thread executor used exclusively for the forfeit timer. Daemon so it does not block JVM shutdown. */
|
/** Single-thread executor used exclusively for the forfeit timer. Daemon so it does not block JVM shutdown. */
|
||||||
@@ -340,7 +340,6 @@ public class GameEventProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Utilities ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of players currently marked as online in the player list.
|
* Returns the number of players currently marked as online in the player list.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
* @param <V> the type of mapped values.
|
* @param <V> the type of mapped values.
|
||||||
*/
|
*/
|
||||||
public class LimitedMap<K, V> implements Map<K, V> {
|
public class LimitedMap<K, V> implements Map<K, V> {
|
||||||
//TODO
|
/** The underlying thread-safe hash map storing all key-value pairs. */
|
||||||
private final ConcurrentHashMap<K, V> map = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<K, V> map = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -165,7 +165,13 @@ public class BuildingCard extends PlayableCard implements Cloneable , BuildingEf
|
|||||||
this.effectType = effectTypeFromId(effectId);
|
this.effectType = effectTypeFromId(effectId);
|
||||||
this.effectId = effectId;
|
this.effectId = effectId;
|
||||||
}
|
}
|
||||||
//TODO JV
|
/**
|
||||||
|
* Maps a building effect identifier to its corresponding {@link EffectType}.
|
||||||
|
*
|
||||||
|
* @param effectId the effect identifier to resolve.
|
||||||
|
* @return the {@link EffectType} for the given identifier.
|
||||||
|
* @throws IllegalArgumentException if {@code effectId} does not correspond to any known effect type.
|
||||||
|
*/
|
||||||
private static EffectType effectTypeFromId(int effectId) {
|
private static EffectType effectTypeFromId(int effectId) {
|
||||||
switch (effectId) {
|
switch (effectId) {
|
||||||
case 2, 9, 7, 6, 5: return EffectType.ON_EVENT;
|
case 2, 9, 7, 6, 5: return EffectType.ON_EVENT;
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import it.polimi.ingsw.gc14.Network.TCP.Server.TCPServer;
|
|||||||
* broadcaster without knowing which protocols are active underneath.
|
* broadcaster without knowing which protocols are active underneath.
|
||||||
*/
|
*/
|
||||||
public class CompositeClientBroadcaster {
|
public class CompositeClientBroadcaster {
|
||||||
//TODO
|
/** RMI transport used to reach RMI-connected clients. */
|
||||||
private final RMIServer rmiServer;
|
private final RMIServer rmiServer;
|
||||||
//TODO
|
/** TCP transport used to reach TCP-connected clients. */
|
||||||
private final TCPServer tcpServer;
|
private final TCPServer tcpServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public enum EventType {
|
|||||||
* Event used to notify that the game has ended.
|
* Event used to notify that the game has ended.
|
||||||
*/
|
*/
|
||||||
ENDED_GAME("Ended Game");
|
ENDED_GAME("Ended Game");
|
||||||
//TODO
|
/** Human-readable label for this event type, returned by {@link #toString()}. */
|
||||||
private final String description;
|
private final String description;
|
||||||
EventType(String description) {
|
EventType(String description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
|||||||
@@ -45,7 +45,14 @@ public class InterfaceResolver {
|
|||||||
return socket.getLocalAddress().getHostAddress();
|
return socket.getLocalAddress().getHostAddress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO
|
/**
|
||||||
|
* Returns {@code true} if {@code a} and {@code b} share the same subnet given a CIDR {@code prefix} length.
|
||||||
|
*
|
||||||
|
* @param a first IPv4 address.
|
||||||
|
* @param b second IPv4 address.
|
||||||
|
* @param prefix CIDR prefix length (0–32).
|
||||||
|
* @return {@code true} if both addresses belong to the same subnet.
|
||||||
|
*/
|
||||||
private static boolean sameSubnet(InetAddress a, InetAddress b, int prefix) {
|
private static boolean sameSubnet(InetAddress a, InetAddress b, int prefix) {
|
||||||
if (prefix < 0 || prefix > 32) return false;
|
if (prefix < 0 || prefix > 32) return false;
|
||||||
int maskBits = prefix == 0 ? 0 : (0xFFFFFFFF << (32 - prefix));
|
int maskBits = prefix == 0 ? 0 : (0xFFFFFFFF << (32 - prefix));
|
||||||
@@ -53,7 +60,12 @@ public class InterfaceResolver {
|
|||||||
int addrB = toInt(b.getAddress()) & maskBits;
|
int addrB = toInt(b.getAddress()) & maskBits;
|
||||||
return addrA == addrB;
|
return addrA == addrB;
|
||||||
}
|
}
|
||||||
//TODO
|
/**
|
||||||
|
* Converts a 4-byte big-endian IPv4 address array to a signed 32-bit integer.
|
||||||
|
*
|
||||||
|
* @param bytes the 4-byte address array.
|
||||||
|
* @return the corresponding signed integer.
|
||||||
|
*/
|
||||||
private static int toInt(byte[] bytes) {
|
private static int toInt(byte[] bytes) {
|
||||||
return ((bytes[0] & 0xFF) << 24) |
|
return ((bytes[0] & 0xFF) << 24) |
|
||||||
((bytes[1] & 0xFF) << 16) |
|
((bytes[1] & 0xFF) << 16) |
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ import java.util.Map;
|
|||||||
* always returns {@code false}.
|
* always returns {@code false}.
|
||||||
*/
|
*/
|
||||||
public class ApplyNextRound extends NetworkEvent {
|
public class ApplyNextRound extends NetworkEvent {
|
||||||
//TODO
|
/** Tribe cards shown in the upper row of the board for the new round. */
|
||||||
private final ArrayList<TribeCard> upperListTribeCards;
|
private final ArrayList<TribeCard> upperListTribeCards;
|
||||||
//TODO
|
/** Tribe cards shown in the lower row of the board for the new round. */
|
||||||
private final ArrayList<TribeCard> lowerListTribeCards;
|
private final ArrayList<TribeCard> lowerListTribeCards;
|
||||||
//TODO
|
/** Building cards shown in the upper row of the board for the new round. */
|
||||||
private final ArrayList<BuildingCard> upperListBuildingCards;
|
private final ArrayList<BuildingCard> upperListBuildingCards;
|
||||||
//TODO
|
/** Building cards shown in the lower row of the board for the new round. */
|
||||||
private final ArrayList<BuildingCard> lowerListBuildingCards;
|
private final ArrayList<BuildingCard> lowerListBuildingCards;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,19 +14,19 @@ import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer;
|
|||||||
* Client RMI. Uses the methods exposed by the server RMI.
|
* Client RMI. Uses the methods exposed by the server RMI.
|
||||||
*/
|
*/
|
||||||
public class RMIClient implements IClient {
|
public class RMIClient implements IClient {
|
||||||
//TODO
|
/** Hostname or IP address of the RMI server. */
|
||||||
private final String host;
|
private final String host;
|
||||||
//TODO
|
/** Port of the RMI registry. */
|
||||||
private final int port;
|
private final int port;
|
||||||
//TODO
|
/** Remote stub obtained from the RMI registry after a successful connection. */
|
||||||
private IGameServer stub;
|
private IGameServer stub;
|
||||||
//TODO
|
/** Client-side controller that receives and applies incoming game events. */
|
||||||
private final ClientController controller;
|
private final ClientController controller;
|
||||||
//TODO
|
/** Local IP address advertised to the RMI runtime so callbacks are routed correctly. */
|
||||||
private final String myIp;
|
private final String myIp;
|
||||||
//TODO
|
/** Username of the currently connected player; set during {@link #connect}. */
|
||||||
private String username;
|
private String username;
|
||||||
//TODO
|
/** {@code true} while the heartbeat loop is active; set to {@code false} on disconnect. */
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
|
|
||||||
/** Scheduler that fires ping() every {@value NetworkConfig#KEEPALIVE_INTERVAL_MS} ms. */
|
/** Scheduler that fires ping() every {@value NetworkConfig#KEEPALIVE_INTERVAL_MS} ms. */
|
||||||
|
|||||||
@@ -26,20 +26,20 @@ import java.util.concurrent.*;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public class RMIHeartbeat {
|
public class RMIHeartbeat {
|
||||||
//TODO
|
/** Username of the client monitored by this watchdog. */
|
||||||
private String username;
|
private String username;
|
||||||
//TODO
|
/** Shared map used to mark the player as offline on timeout. */
|
||||||
private final LimitedMap<String, Boolean> playerList;
|
private final LimitedMap<String, Boolean> playerList;
|
||||||
//TODO
|
/** Registry of active RMI callbacks; the entry for this player is removed on disconnect. */
|
||||||
private final Map<String, IClientCallback> clients;
|
private final Map<String, IClientCallback> clients;
|
||||||
//TODO
|
/** Shared event queue; a {@link DisconnectedPlayer} event is posted here on timeout. */
|
||||||
private final BlockingQueue<NetworkEvent> actionQueue;
|
private final BlockingQueue<NetworkEvent> actionQueue;
|
||||||
|
|
||||||
/** Last time a ping was received from this client. */
|
/** Last time a ping was received from this client. */
|
||||||
private volatile long lastPingTime = System.currentTimeMillis();
|
private volatile long lastPingTime = System.currentTimeMillis();
|
||||||
//TODO
|
/** {@code true} while the watchdog is running; set to {@code false} on first disconnect. */
|
||||||
private volatile boolean running = true;
|
private volatile boolean running = true;
|
||||||
//TODO
|
/** Single-thread executor that periodically checks whether the silence threshold has been exceeded. */
|
||||||
private final ScheduledExecutorService watchdog =
|
private final ScheduledExecutorService watchdog =
|
||||||
Executors.newSingleThreadScheduledExecutor(r -> {
|
Executors.newSingleThreadScheduledExecutor(r -> {
|
||||||
Thread t = new Thread(r, "rmi-watchdog-" + username);
|
Thread t = new Thread(r, "rmi-watchdog-" + username);
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ import java.util.stream.Collectors;
|
|||||||
* shared network event queue.
|
* shared network event queue.
|
||||||
*/
|
*/
|
||||||
public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
||||||
//TODO
|
/** Hostname or IP address exposed by the RMI runtime ({@code java.rmi.server.hostname}). */
|
||||||
private final String host;
|
private final String host;
|
||||||
//TODO
|
/** Server-side game controller; all model access is synchronized on this object. */
|
||||||
private final GameController controller;
|
private final GameController controller;
|
||||||
//TODO
|
/** Port on which the RMI registry is bound. */
|
||||||
private final int nPort;
|
private final int nPort;
|
||||||
|
|
||||||
/** username → callback */
|
/** username → callback */
|
||||||
@@ -49,9 +49,9 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
|||||||
* HeartbeatHandler in the TCP stack.
|
* HeartbeatHandler in the TCP stack.
|
||||||
*/
|
*/
|
||||||
private final Map<String, RMIHeartbeat> watchdogs = new ConcurrentHashMap<>();
|
private final Map<String, RMIHeartbeat> watchdogs = new ConcurrentHashMap<>();
|
||||||
//TODO
|
/** Shared queue to which player actions are added for sequential processing. */
|
||||||
private final BlockingQueue<NetworkEvent> actionQueue;
|
private final BlockingQueue<NetworkEvent> actionQueue;
|
||||||
//TODO
|
/** Shared map tracking each player's connection status ({@code true} = online). */
|
||||||
private final LimitedMap<String, Boolean> playerList;
|
private final LimitedMap<String, Boolean> playerList;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* Client TCP. Sends and receives messages with the TCP server.
|
* Client TCP. Sends and receives messages with the TCP server.
|
||||||
*/
|
*/
|
||||||
public class TCPClient implements IClient {
|
public class TCPClient implements IClient {
|
||||||
//TODO
|
/** Byte value sent by the client to signal it is still alive. */
|
||||||
private static final int PING = 1;
|
private static final int PING = 1;
|
||||||
//TODO
|
/** Byte value expected from the server in response to a {@link #PING}. */
|
||||||
private static final int PONG = 2;
|
private static final int PONG = 2;
|
||||||
|
|
||||||
/** Socket TCP */
|
/** Socket TCP */
|
||||||
@@ -37,17 +37,17 @@ public class TCPClient implements IClient {
|
|||||||
|
|
||||||
/** IP address of the server to connect to */
|
/** IP address of the server to connect to */
|
||||||
private final String hostname;
|
private final String hostname;
|
||||||
//TODO
|
/** {@code true} while the connection is active; set to {@code false} on disconnect. */
|
||||||
private boolean running;
|
private boolean running;
|
||||||
/** TCP port */
|
/** TCP port */
|
||||||
private final int mainPort;
|
private final int mainPort;
|
||||||
//TODO
|
/** TCP port dedicated to heartbeat communication. */
|
||||||
private final int heartbeatPort;
|
private final int heartbeatPort;
|
||||||
//TODO
|
/** Socket used exclusively for heartbeat ping/pong exchange. */
|
||||||
private Socket heartbeatSocket;
|
private Socket heartbeatSocket;
|
||||||
//TODO
|
/** Output stream of {@link #heartbeatSocket}, used to write {@link #PING} bytes. */
|
||||||
private OutputStream heartbeatOut;
|
private OutputStream heartbeatOut;
|
||||||
//TODO
|
/** Input stream of {@link #heartbeatSocket}, used to read {@link #PONG} bytes. */
|
||||||
private InputStream heartbeatIn;
|
private InputStream heartbeatIn;
|
||||||
|
|
||||||
|
|
||||||
@@ -113,7 +113,11 @@ public class TCPClient implements IClient {
|
|||||||
return ErrorType.SERVER_UNREACHABLE;
|
return ErrorType.SERVER_UNREACHABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO
|
/**
|
||||||
|
* Sends a {@link #PING} byte to the server every 3 seconds and waits for a {@link #PONG} reply.
|
||||||
|
* If no reply arrives within {@value NetworkConfig#SILENCE_THRESHOLD_MS} ms, the server is
|
||||||
|
* considered unreachable and {@link #disconnect()} is called.
|
||||||
|
*/
|
||||||
private void heartbeatLoop() {
|
private void heartbeatLoop() {
|
||||||
ScheduledExecutorService sender = Executors.newSingleThreadScheduledExecutor();
|
ScheduledExecutorService sender = Executors.newSingleThreadScheduledExecutor();
|
||||||
sender.scheduleAtFixedRate(() -> {
|
sender.scheduleAtFixedRate(() -> {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class ClientHandler implements Runnable {
|
|||||||
* The username of the connected client on this handler
|
* The username of the connected client on this handler
|
||||||
*/
|
*/
|
||||||
private final String username;
|
private final String username;
|
||||||
//TODO
|
/** {@code true} while the handler is actively reading from the socket; set to {@code false} on disconnect. */
|
||||||
private volatile boolean running;
|
private volatile boolean running;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ import it.polimi.ingsw.gc14.Network.NetworkConfig;
|
|||||||
* both the heartbeat connection and the main client connection are disconnected.
|
* both the heartbeat connection and the main client connection are disconnected.
|
||||||
*/
|
*/
|
||||||
public class HeartbeatHandler implements Runnable {
|
public class HeartbeatHandler implements Runnable {
|
||||||
//TODO
|
/** Username of the client associated with this heartbeat connection. */
|
||||||
private final String username;
|
private final String username;
|
||||||
//TODO
|
/** Dedicated socket used solely for heartbeat ping/pong exchange. */
|
||||||
private final Socket socket;
|
private final Socket socket;
|
||||||
//TODO
|
/** Input stream of {@link #socket} used to receive {@code PING} bytes from the client. */
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
//TODO
|
/** Output stream of {@link #socket} used to send {@code PONG} bytes back to the client. */
|
||||||
private final OutputStream out;
|
private final OutputStream out;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ import java.util.*;
|
|||||||
* <p>Displays the final player rankings and a winner/game-over banner.
|
* <p>Displays the final player rankings and a winner/game-over banner.
|
||||||
*/
|
*/
|
||||||
public class LeaderboardFXMLController {
|
public class LeaderboardFXMLController {
|
||||||
//TODO
|
/** Root pane of the leaderboard scene; used to set the background and anchor the popup. */
|
||||||
@FXML private StackPane rootPane;
|
@FXML private StackPane rootPane;
|
||||||
//TODO
|
/** Main vertical container holding the outcome label and ranking rows. */
|
||||||
@FXML private VBox mainVBox;
|
@FXML private VBox mainVBox;
|
||||||
//TODO
|
/** Vertical list populated with one {@code HBox} row per ranked player. */
|
||||||
@FXML private VBox rankingList;
|
@FXML private VBox rankingList;
|
||||||
|
|
||||||
/** Client controller for fetching game state and sending actions. */
|
/** Client controller for fetching game state and sending actions. */
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public enum BorderStyle {
|
|||||||
* Rounded Unicode border style.
|
* Rounded Unicode border style.
|
||||||
*/
|
*/
|
||||||
ROUNDED("╭","╮","╰","╯","─","│","├","┤","┬","┴","┼","├","┤","┼");
|
ROUNDED("╭","╮","╰","╯","─","│","├","┤","┬","┴","┼","├","┤","┼");
|
||||||
//TODO
|
/** Corner (tl/tr/bl/br), line (h/v), outer junction (ml/mr/mt/mb/x), and separator junction (sl/sr/sx) characters. */
|
||||||
private final String tl,tr,bl,br,h,v,ml,mr,mt,mb,x,sl,sr,sx;
|
private final String tl,tr,bl,br,h,v,ml,mr,mt,mb,x,sl,sr,sx;
|
||||||
|
|
||||||
BorderStyle(String tl,String tr,String bl,String br,
|
BorderStyle(String tl,String tr,String bl,String br,
|
||||||
|
|||||||
@@ -229,7 +229,6 @@ class Order3Test {
|
|||||||
assertTrue(order.toString().contains("--"));
|
assertTrue(order.toString().contains("--"));
|
||||||
assertTrue(order.toString().contains("-1🍖/-2🏅"));
|
assertTrue(order.toString().contains("-1🍖/-2🏅"));
|
||||||
|
|
||||||
//TODO testare IndexOutOfBoundsException
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user