Add: complete JavaDoc for MiniModel and TCPServer
This commit is contained in:
@@ -1,37 +1,86 @@
|
||||
package it.polimi.ingsw.gc14.Model;
|
||||
|
||||
import it.polimi.ingsw.gc14.Model.Cards.BuildingCard;
|
||||
import it.polimi.ingsw.gc14.Model.Cards.TribeCard;
|
||||
import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character;
|
||||
import it.polimi.ingsw.gc14.Model.GamePackage.Board;
|
||||
import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Lightweight representation of the game model shared with clients.
|
||||
*
|
||||
* <p>The mini model contains only the information required by the client-side
|
||||
* view and controllers to render the current match state and process incoming
|
||||
* network updates.
|
||||
*/
|
||||
public class MiniModel implements Serializable {
|
||||
|
||||
/**
|
||||
* Current game board.
|
||||
*/
|
||||
public Board board;
|
||||
|
||||
/**
|
||||
* Map associating each occupied slot with the corresponding player.
|
||||
*/
|
||||
public Map<Slot, Player> slotPlayerMap;
|
||||
|
||||
/**
|
||||
* Card used to manage the player turn order.
|
||||
*/
|
||||
public OrderLogicCard orderLogicCard;
|
||||
|
||||
/**
|
||||
* Current state of the game.
|
||||
*/
|
||||
public CurrentState currentState;
|
||||
|
||||
/**
|
||||
* Map of players indexed by username.
|
||||
*/
|
||||
public Map<String, Player> players;
|
||||
|
||||
/**
|
||||
* List of totems still available for selection.
|
||||
*/
|
||||
public List<Totems> availableTotems;
|
||||
|
||||
/**
|
||||
* Final standing of the players at the end of the game.
|
||||
*/
|
||||
public List<Player> standingPlayers;
|
||||
|
||||
// --- Costruttori ---
|
||||
|
||||
/**
|
||||
* Constructs an empty mini model.
|
||||
*/
|
||||
public MiniModel() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a mini model containing only the game board.
|
||||
*
|
||||
* @param board the current game board.
|
||||
*/
|
||||
public MiniModel(Board board) {
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
public MiniModel(Board board, Map<Slot, Player> slotPlayerMap, OrderLogicCard orderLogicCard,
|
||||
CurrentState currentState, List<Player> players, List<Totems> availableTotems) {
|
||||
/**
|
||||
* Constructs a complete mini model from the current server-side game data.
|
||||
*
|
||||
* @param board the current game board.
|
||||
* @param slotPlayerMap the map associating occupied slots with players.
|
||||
* @param orderLogicCard the card managing player turn order.
|
||||
* @param currentState the current state of the game.
|
||||
* @param players the list of players in the match.
|
||||
* @param availableTotems the list of totems still available for selection.
|
||||
*/
|
||||
public MiniModel(Board board,
|
||||
Map<Slot, Player> slotPlayerMap,
|
||||
OrderLogicCard orderLogicCard,
|
||||
CurrentState currentState,
|
||||
List<Player> players,
|
||||
List<Totems> availableTotems) {
|
||||
this.board = board;
|
||||
this.slotPlayerMap = slotPlayerMap;
|
||||
this.orderLogicCard = orderLogicCard;
|
||||
@@ -42,43 +91,90 @@ public class MiniModel implements Serializable {
|
||||
setPlayers(players);
|
||||
}
|
||||
|
||||
|
||||
// --- Setter ---
|
||||
|
||||
/**
|
||||
* Sets the current game board.
|
||||
*
|
||||
* @param board the board to assign.
|
||||
*/
|
||||
public void setBoard(Board board) {
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of totems still available for selection.
|
||||
*
|
||||
* @param availableTotems the available totems.
|
||||
*/
|
||||
public void setAvailableTotems(List<Totems> availableTotems) {
|
||||
this.availableTotems = availableTotems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the map associating occupied slots with players.
|
||||
*
|
||||
* @param slotPlayerMap the slot-player map to assign.
|
||||
*/
|
||||
public void setSlotPlayerMap(Map<Slot, Player> slotPlayerMap) {
|
||||
this.slotPlayerMap = slotPlayerMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the card used to manage the player turn order.
|
||||
*
|
||||
* @param orderLogicCard the order logic card to assign.
|
||||
*/
|
||||
public void setOrderLogicCard(OrderLogicCard orderLogicCard) {
|
||||
this.orderLogicCard = orderLogicCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current state of the game.
|
||||
*
|
||||
* @param currentState the current game state.
|
||||
*/
|
||||
public void setCurrentState(CurrentState currentState) {
|
||||
this.currentState = currentState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces or updates the players stored in the mini model.
|
||||
*
|
||||
* <p>Each player is indexed by username.
|
||||
*
|
||||
* @param players the list of players to store.
|
||||
*/
|
||||
public void setPlayers(List<Player> players) {
|
||||
for (Player player : players) {
|
||||
this.players.put(player.getUserName(), player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or updates a single player in the mini model.
|
||||
*
|
||||
* @param player the player to store.
|
||||
*/
|
||||
public void setPlayer(Player player) {
|
||||
players.put(player.getUserName(), player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the final standing of the players.
|
||||
*
|
||||
* @param standingPlayers the final ordered list of players.
|
||||
*/
|
||||
public void setStandingPlayers(ArrayList<Player> standingPlayers) {
|
||||
this.standingPlayers = standingPlayers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the position of the player with the specified username
|
||||
* within the player collection.
|
||||
*
|
||||
* @param username the username of the player to search for.
|
||||
* @return the zero-based position of the player, or {@code -1}
|
||||
* if no matching username is found.
|
||||
*/
|
||||
public int getPositionByUsername(String username) {
|
||||
int i = 0;
|
||||
for (Player player : players.values()) {
|
||||
|
||||
@@ -18,33 +18,96 @@ import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Server TCP. Accepts connections and manages all client handlers.
|
||||
* TCP server responsible for accepting client connections,
|
||||
* handling player registration and reconnection, and sending
|
||||
* game updates to connected clients.
|
||||
*
|
||||
* <p>The server also manages a dedicated heartbeat channel used
|
||||
* to detect disconnected clients and associate each heartbeat
|
||||
* connection with the corresponding {@link ClientHandler}.
|
||||
*/
|
||||
public class TCPServer {
|
||||
|
||||
/**
|
||||
* Main TCP port used for standard client-server communication.
|
||||
*/
|
||||
int port;
|
||||
int heartbeatPort; // ← nuova porta
|
||||
|
||||
/**
|
||||
* TCP port dedicated to heartbeat communication.
|
||||
*/
|
||||
int heartbeatPort;
|
||||
|
||||
/**
|
||||
* Number of players that have successfully connected.
|
||||
*/
|
||||
int connectedPlayers;
|
||||
ServerSocket socketTCP;
|
||||
ServerSocket heartbeatSocketTCP; // ← nuovo ServerSocket
|
||||
|
||||
/**
|
||||
* Main server socket used to accept client connections.
|
||||
*/
|
||||
ServerSocket socketTCP;
|
||||
|
||||
/**
|
||||
* Server socket used to accept heartbeat connections.
|
||||
*/
|
||||
ServerSocket heartbeatSocketTCP;
|
||||
|
||||
/**
|
||||
* Game controller used to manage the server-side game logic.
|
||||
*/
|
||||
final GameController controller;
|
||||
|
||||
/**
|
||||
* Queue containing network events received from clients.
|
||||
*/
|
||||
BlockingQueue<NetworkEvent> actionQueue;
|
||||
|
||||
/**
|
||||
* Map storing the online/offline status of connected players.
|
||||
*/
|
||||
LimitedMap<String, Boolean> playerList;
|
||||
|
||||
/**
|
||||
* List of active TCP client handlers.
|
||||
*/
|
||||
List<ClientHandler> clientHandlers;
|
||||
|
||||
/**
|
||||
* Flag indicating whether the server is recovering from a previous crash.
|
||||
*/
|
||||
boolean serverCrashed;
|
||||
|
||||
/**
|
||||
* Sets whether the server is recovering from a previous crash.
|
||||
*
|
||||
* @param serverCrashed {@code true} if the server is in crash-recovery mode,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public void setServerCrashed(boolean serverCrashed) {
|
||||
this.serverCrashed = serverCrashed;
|
||||
}
|
||||
|
||||
// Mappa temporanea: username → ClientHandler
|
||||
// Serve per associare il socket heartbeat al giusto ClientHandler
|
||||
/**
|
||||
* Temporary map associating each username with the corresponding
|
||||
* {@link ClientHandler} waiting for its heartbeat connection.
|
||||
*/
|
||||
private final Map<String, ClientHandler> pendingHeartbeat = new ConcurrentHashMap<>();
|
||||
|
||||
public TCPServer(GameController controller, int port, int heartbeatPort,
|
||||
BlockingQueue<NetworkEvent> actionQueue, LimitedMap<String, Boolean> playerList) {
|
||||
/**
|
||||
* Constructs a TCP server with the required game and network components.
|
||||
*
|
||||
* @param controller the game controller used to manage the game logic.
|
||||
* @param port the main TCP port used for client communication.
|
||||
* @param heartbeatPort the TCP port dedicated to heartbeat connections.
|
||||
* @param actionQueue the queue containing incoming network events.
|
||||
* @param playerList the map storing the connection status of the players.
|
||||
*/
|
||||
public TCPServer(GameController controller,
|
||||
int port,
|
||||
int heartbeatPort,
|
||||
BlockingQueue<NetworkEvent> actionQueue,
|
||||
LimitedMap<String, Boolean> playerList) {
|
||||
this.port = port;
|
||||
this.heartbeatPort = heartbeatPort;
|
||||
this.connectedPlayers = 0;
|
||||
@@ -54,8 +117,24 @@ public class TCPServer {
|
||||
this.clientHandlers = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the TCP server and begins accepting client connections.
|
||||
*
|
||||
* <p>The method opens both the main TCP server socket and the dedicated
|
||||
* heartbeat server socket. It then starts a separate thread for heartbeat
|
||||
* connections and continuously waits for new players or reconnecting clients.
|
||||
*
|
||||
* <p>When a new connection is received, the first event must be an
|
||||
* {@link AddPlayer} request. Depending on the current server state,
|
||||
* the connection is handled either as a new player joining the game
|
||||
* or as a reconnection attempt.
|
||||
*
|
||||
* @param serverCrashed {@code true} if the server is being restarted after a crash,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public void start(boolean serverCrashed) {
|
||||
this.serverCrashed = serverCrashed;
|
||||
|
||||
try {
|
||||
socketTCP = new ServerSocket(port);
|
||||
heartbeatSocketTCP = new ServerSocket(heartbeatPort);
|
||||
@@ -68,16 +147,19 @@ public class TCPServer {
|
||||
System.out.println("TCP server started on port: " + port);
|
||||
System.out.println("Heartbeat server started on port: " + heartbeatPort);
|
||||
|
||||
// Thread separato per accettare le connessioni heartbeat
|
||||
new Thread(this::acceptHeartbeat, "heartbeat-acceptor").start();
|
||||
|
||||
// Loop principale — invariato nella logica, cambia solo la creazione del ClientHandler
|
||||
while (true) {
|
||||
try {
|
||||
Socket clientSocket = socketTCP.accept();
|
||||
ObjectOutputStream clientSend = new ObjectOutputStream(clientSocket.getOutputStream());
|
||||
ObjectInputStream clientReceive = new ObjectInputStream(clientSocket.getInputStream());
|
||||
|
||||
ObjectOutputStream clientSend =
|
||||
new ObjectOutputStream(clientSocket.getOutputStream());
|
||||
ObjectInputStream clientReceive =
|
||||
new ObjectInputStream(clientSocket.getInputStream());
|
||||
|
||||
NetworkEvent event = (NetworkEvent) clientReceive.readObject();
|
||||
|
||||
if (!(event.getEventType() == EventType.ADD_PLAYER)) {
|
||||
clientSocket.getOutputStream().write(-1);
|
||||
clientSocket.close();
|
||||
@@ -87,136 +169,195 @@ public class TCPServer {
|
||||
|
||||
AddPlayer eventAddPlayer = (AddPlayer) event;
|
||||
|
||||
if (eventAddPlayer.getProposedNPlayer() < 2 || eventAddPlayer.getProposedNPlayer() > 5) {
|
||||
if (eventAddPlayer.getProposedNPlayer() < 2
|
||||
|| eventAddPlayer.getProposedNPlayer() > 5) {
|
||||
clientSocket.getOutputStream().write(-1);
|
||||
clientSocket.close();
|
||||
System.out.println("Invalid parameters. Connection terminated.");
|
||||
continue;
|
||||
}
|
||||
|
||||
synchronized (controller) {
|
||||
synchronized (controller) {
|
||||
String username = eventAddPlayer.getUsername();
|
||||
|
||||
String username = eventAddPlayer.getUsername();
|
||||
if(serverCrashed){
|
||||
if(controller.getModel().getPlayers().stream().anyMatch(p -> p.getUserName().equals(username))&& !playerList.containsKey(username)){
|
||||
playerList.put(username, true);
|
||||
System.out.println("(After crash)Reconnected player: " + username);
|
||||
ClientHandler handler = new ClientHandler(
|
||||
username, clientSocket, clientSend, clientReceive,
|
||||
clientHandlers,playerList, actionQueue
|
||||
);
|
||||
clientSocket.getOutputStream().write(1);
|
||||
pendingHeartbeat.put(username, handler);
|
||||
Thread thread = new Thread(handler);
|
||||
thread.start();
|
||||
clientHandlers.add(handler);
|
||||
connectedPlayers++;
|
||||
}
|
||||
else if(playerList.containsKey(username) && !playerList.get(username)){
|
||||
// riconnessione
|
||||
playerList.put(username, true);
|
||||
System.out.println("Reconnected player: " + username);
|
||||
if (serverCrashed) {
|
||||
if (controller.getModel().getPlayers().stream()
|
||||
.anyMatch(p -> p.getUserName().equals(username))
|
||||
&& !playerList.containsKey(username)) {
|
||||
|
||||
ClientHandler handler = new ClientHandler(
|
||||
username, clientSocket, clientSend, clientReceive,
|
||||
clientHandlers, playerList, actionQueue
|
||||
);
|
||||
clientSocket.getOutputStream().write(1);
|
||||
pendingHeartbeat.put(username, handler);
|
||||
Game game = controller.getModel();
|
||||
handler.notifyMiniModel(new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers(),game.getAvailableTotems()));
|
||||
Thread thread = new Thread(handler);
|
||||
thread.start();
|
||||
clientHandlers.add(handler);
|
||||
connectedPlayers++;
|
||||
actionQueue.add(new ReconnectPlayer(username));
|
||||
}
|
||||
else
|
||||
{
|
||||
clientSocket.getOutputStream().write(-1);
|
||||
clientSocket.close();
|
||||
System.out.println("Player could not be added. Connection terminated.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (playerList.isEmpty()) {
|
||||
Game model = new Game(eventAddPlayer.getProposedNPlayer());
|
||||
controller.setModel(model);
|
||||
playerList.setLimit(eventAddPlayer.getProposedNPlayer());
|
||||
}
|
||||
if (controller.addPlayer(username)) {
|
||||
// nuovo giocatore
|
||||
playerList.put(username, true);
|
||||
System.out.println("Accepted player: " + username);
|
||||
ClientHandler handler = new ClientHandler(
|
||||
username, clientSocket, clientSend, clientReceive,
|
||||
clientHandlers,playerList, actionQueue
|
||||
);
|
||||
clientSocket.getOutputStream().write(1);
|
||||
pendingHeartbeat.put(username, handler);
|
||||
Thread thread = new Thread(handler);
|
||||
thread.start();
|
||||
clientHandlers.add(handler);
|
||||
connectedPlayers++;
|
||||
// metti in attesa del socket heartbeat
|
||||
}
|
||||
else if(playerList.containsKey(username) && !playerList.get(username)){
|
||||
// riconnessione
|
||||
playerList.put(username, true);
|
||||
System.out.println("Reconnected player: " + username);
|
||||
playerList.put(username, true);
|
||||
System.out.println("(After crash)Reconnected player: " + username);
|
||||
|
||||
ClientHandler handler = new ClientHandler(
|
||||
username, clientSocket, clientSend, clientReceive,
|
||||
clientHandlers, playerList, actionQueue
|
||||
);
|
||||
clientSocket.getOutputStream().write(1);
|
||||
pendingHeartbeat.put(username, handler);
|
||||
Game game = controller.getModel();
|
||||
handler.notifyMiniModel(new MiniModel(game.getBoard(),game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers(),game.getAvailableTotems()));
|
||||
Thread thread = new Thread(handler);
|
||||
thread.start();
|
||||
clientHandlers.add(handler);
|
||||
connectedPlayers++;
|
||||
actionQueue.add(new ReconnectPlayer(username));
|
||||
}
|
||||
else{
|
||||
clientSocket.getOutputStream().write(-1);
|
||||
clientSocket.close();
|
||||
System.out.println("Player could not be added. Connection terminated.");
|
||||
}
|
||||
}
|
||||
ClientHandler handler = new ClientHandler(
|
||||
username,
|
||||
clientSocket,
|
||||
clientSend,
|
||||
clientReceive,
|
||||
clientHandlers,
|
||||
playerList,
|
||||
actionQueue
|
||||
);
|
||||
|
||||
}
|
||||
clientSocket.getOutputStream().write(1);
|
||||
pendingHeartbeat.put(username, handler);
|
||||
|
||||
Thread thread = new Thread(handler);
|
||||
thread.start();
|
||||
|
||||
}
|
||||
catch(IOException | ClassNotFoundException e){
|
||||
clientHandlers.add(handler);
|
||||
connectedPlayers++;
|
||||
|
||||
} else if (playerList.containsKey(username)
|
||||
&& !playerList.get(username)) {
|
||||
|
||||
playerList.put(username, true);
|
||||
System.out.println("Reconnected player: " + username);
|
||||
|
||||
ClientHandler handler = new ClientHandler(
|
||||
username,
|
||||
clientSocket,
|
||||
clientSend,
|
||||
clientReceive,
|
||||
clientHandlers,
|
||||
playerList,
|
||||
actionQueue
|
||||
);
|
||||
|
||||
clientSocket.getOutputStream().write(1);
|
||||
pendingHeartbeat.put(username, handler);
|
||||
|
||||
Game game = controller.getModel();
|
||||
handler.notifyMiniModel(new MiniModel(
|
||||
game.getBoard(),
|
||||
game.getSlotMap(),
|
||||
game.orderLogicCard,
|
||||
game.getCurrentState(),
|
||||
game.getPlayers(),
|
||||
game.getAvailableTotems()
|
||||
));
|
||||
|
||||
Thread thread = new Thread(handler);
|
||||
thread.start();
|
||||
|
||||
clientHandlers.add(handler);
|
||||
connectedPlayers++;
|
||||
actionQueue.add(new ReconnectPlayer(username));
|
||||
|
||||
} else {
|
||||
clientSocket.getOutputStream().write(-1);
|
||||
clientSocket.close();
|
||||
System.out.println("Player could not be added. Connection terminated.");
|
||||
}
|
||||
|
||||
} else {
|
||||
if (playerList.isEmpty()) {
|
||||
Game model = new Game(eventAddPlayer.getProposedNPlayer());
|
||||
controller.setModel(model);
|
||||
playerList.setLimit(eventAddPlayer.getProposedNPlayer());
|
||||
}
|
||||
|
||||
if (controller.addPlayer(username)) {
|
||||
playerList.put(username, true);
|
||||
System.out.println("Accepted player: " + username);
|
||||
|
||||
ClientHandler handler = new ClientHandler(
|
||||
username,
|
||||
clientSocket,
|
||||
clientSend,
|
||||
clientReceive,
|
||||
clientHandlers,
|
||||
playerList,
|
||||
actionQueue
|
||||
);
|
||||
|
||||
clientSocket.getOutputStream().write(1);
|
||||
pendingHeartbeat.put(username, handler);
|
||||
|
||||
Thread thread = new Thread(handler);
|
||||
thread.start();
|
||||
|
||||
clientHandlers.add(handler);
|
||||
connectedPlayers++;
|
||||
|
||||
} else if (playerList.containsKey(username)
|
||||
&& !playerList.get(username)) {
|
||||
|
||||
playerList.put(username, true);
|
||||
System.out.println("Reconnected player: " + username);
|
||||
|
||||
ClientHandler handler = new ClientHandler(
|
||||
username,
|
||||
clientSocket,
|
||||
clientSend,
|
||||
clientReceive,
|
||||
clientHandlers,
|
||||
playerList,
|
||||
actionQueue
|
||||
);
|
||||
|
||||
clientSocket.getOutputStream().write(1);
|
||||
pendingHeartbeat.put(username, handler);
|
||||
|
||||
Game game = controller.getModel();
|
||||
handler.notifyMiniModel(new MiniModel(
|
||||
game.getBoard(),
|
||||
game.getSlotMap(),
|
||||
game.orderLogicCard,
|
||||
game.getCurrentState(),
|
||||
game.getPlayers(),
|
||||
game.getAvailableTotems()
|
||||
));
|
||||
|
||||
Thread thread = new Thread(handler);
|
||||
thread.start();
|
||||
|
||||
clientHandlers.add(handler);
|
||||
connectedPlayers++;
|
||||
actionQueue.add(new ReconnectPlayer(username));
|
||||
|
||||
} else {
|
||||
clientSocket.getOutputStream().write(-1);
|
||||
clientSocket.close();
|
||||
System.out.println("Player could not be added. Connection terminated.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accetta connessioni sul socket heartbeat e le associa al ClientHandler giusto.
|
||||
* Il client manda subito il proprio username per identificarsi.
|
||||
* Accepts heartbeat connections and associates them with the correct client handler.
|
||||
*
|
||||
* <p>Each client immediately sends its username on the heartbeat channel.
|
||||
* The method uses that username to retrieve the pending {@link ClientHandler}
|
||||
* and starts a dedicated {@link HeartbeatHandler}. If no pending handler is found,
|
||||
* the heartbeat socket is closed.
|
||||
*/
|
||||
private void acceptHeartbeat() {
|
||||
while (true) {
|
||||
try {
|
||||
Socket hbSocket = heartbeatSocketTCP.accept();
|
||||
ObjectInputStream hbIn = new ObjectInputStream(hbSocket.getInputStream());
|
||||
ObjectInputStream hbIn =
|
||||
new ObjectInputStream(hbSocket.getInputStream());
|
||||
|
||||
// il client manda subito il suo username
|
||||
String username = (String) hbIn.readObject();
|
||||
|
||||
ClientHandler handler = pendingHeartbeat.remove(username);
|
||||
|
||||
if (handler != null) {
|
||||
HeartbeatHandler hb = new HeartbeatHandler(username, hbSocket, handler);
|
||||
HeartbeatHandler hb =
|
||||
new HeartbeatHandler(username, hbSocket, handler);
|
||||
|
||||
new Thread(hb, "heartbeat-" + username).start();
|
||||
System.out.println("Heartbeat connected for: " + username);
|
||||
} else {
|
||||
System.out.println("No pending handler for: " + username + ", closing heartbeat.");
|
||||
System.out.println(
|
||||
"No pending handler for: " + username + ", closing heartbeat."
|
||||
);
|
||||
hbSocket.close();
|
||||
}
|
||||
|
||||
@@ -226,13 +367,27 @@ public class TCPServer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies connected TCP clients of a new network event.
|
||||
*
|
||||
* <p>If the event does not represent an error, it is sent to all connected clients.
|
||||
* If it represents an error, it is sent only to the client that requested the action.
|
||||
*
|
||||
* @param event the network event to send to the clients.
|
||||
*/
|
||||
public void notifyAll(NetworkEvent event) {
|
||||
clientHandlers.forEach(h -> {
|
||||
if (!event.getIsError() || event.getUsername().equals(h.getUsername()))
|
||||
if (!event.getIsError() || event.getUsername().equals(h.getUsername())) {
|
||||
h.notifyEvent(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies all connected TCP clients of a new game model.
|
||||
*
|
||||
* @param model the updated mini model to send to the clients.
|
||||
*/
|
||||
public void notifyAll(MiniModel model) {
|
||||
clientHandlers.forEach(h -> h.notifyMiniModel(model));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user