Fixed:Client Resilience (TCP)

This commit is contained in:
rubenpirreram
2026-05-08 17:16:09 +02:00
parent e78096d2e0
commit 9fe23c6f9e
7 changed files with 91 additions and 10 deletions
@@ -38,6 +38,14 @@ public class GameController {
return false; return false;
return model.SkipNotConnectedPlayer(player); return model.SkipNotConnectedPlayer(player);
} }
//TODO
public boolean ReconnectPlayer(String username)
{
Player player= model.getPlayerByUsername(username);
if(player==null)
return false;
return model.ReconnectPlayer(player);
}
/** /**
* Returns the game model managed by this controller. * Returns the game model managed by this controller.
* *
@@ -40,6 +40,9 @@ public class Game implements Serializable {
public List<Player> getPlayers() { public List<Player> getPlayers() {
return playersList; return playersList;
} }
//TODO
Map<Player,Boolean> disconnetedPlayers = new HashMap<>();
//TODO //TODO
public boolean SkipNotConnectedPlayer(Player player) public boolean SkipNotConnectedPlayer(Player player)
{ {
@@ -47,9 +50,28 @@ public class Game implements Serializable {
{ {
return false; return false;
} }
nextPlayerSetup();
return true;
if(currentState.getGameStage().equals(GameStages.SLOT_CHOICE))
{
nextPlayerSetup();
disconnetedPlayers.put(player,false);
}
else
{
nextPlayerSetup();
}
return true;
}
//TODO
public boolean ReconnectPlayer(Player player)
{
if(!disconnetedPlayers.containsKey(player))
{
return false;
}
return disconnetedPlayers.put(player,false);
} }
/** /**
* Returns the current number of players participating in the game. * Returns the current number of players participating in the game.
@@ -728,6 +750,14 @@ public class Game implements Serializable {
if (currentState.getRound() < 10) { if (currentState.getRound() < 10) {
nextRound(); nextRound();
for(Map.Entry<Player,Boolean> entry: disconnetedPlayers.entrySet())
{
if(!entry.getValue())
{
orderLogicCard.pushNoEffect(entry.getKey());
disconnetedPlayers.remove(entry.getKey());
}
}
currentState.PlayerUpdate(orderLogicCard.pull(), null); currentState.PlayerUpdate(orderLogicCard.pull(), null);
currentState.GameStageUpdate(GameStages.SLOT_CHOICE); currentState.GameStageUpdate(GameStages.SLOT_CHOICE);
} else { } else {
@@ -59,6 +59,20 @@ public abstract class OrderLogicCard implements Serializable {
} }
/**
* Adds the player to the end of the queue, without effects.
*
* @param player the player to be pushed into the queue.
*/
public void pushNoEffect(Player player){
if(players.size()==0)
{
playerList=new ArrayList<>();
}
playerList.add(new OrderPlayer(player,false));
players.add(player);
}
/** /**
* Removes and returns the first player in the queue. * Removes and returns the first player in the queue.
@@ -15,5 +15,6 @@ public enum EventType {
PICK_OPTIONAL_BUILD, PICK_OPTIONAL_BUILD,
SKIP_NO_DRAWABLE, SKIP_NO_DRAWABLE,
SKIP_PLAYER_DISCONNECTED, SKIP_PLAYER_DISCONNECTED,
RECONNECT_PLAYER,
NO_OPTIONAL_CARD NO_OPTIONAL_CARD
} }
@@ -0,0 +1,30 @@
package it.polimi.ingsw.gc14.Network.NetworkEvents;
import it.polimi.ingsw.gc14.Controller.GameController;
import it.polimi.ingsw.gc14.Network.EventType;
import it.polimi.ingsw.gc14.Network.NetworkEvent;
import java.io.Serializable;
//TODO
public class ReconnectPlayer extends NetworkEvent implements Serializable{
/**
* Class constructor.
* Initializes all the attributes.
* @param username the name of the player requesting the event
*/
public ReconnectPlayer(String username){
super(username, EventType.RECONNECT_PLAYER, false);
}
/**
* @param gameController the Game Controller on which to apply the event
* @return true if the player could skipTheTurn, false otherwise
*/
@Override
public boolean apply(GameController gameController){
return gameController.ReconnectPlayer(username);
}
}
@@ -81,6 +81,7 @@ public class TCPClient implements IClient {
return false; return false;
} }
new Thread(this::receiveMessage, "tcp-reader").start(); new Thread(this::receiveMessage, "tcp-reader").start();
// Socket heartbeat // Socket heartbeat
this.heartbeatSocket = new Socket(hostname, heartbeatPort); this.heartbeatSocket = new Socket(hostname, heartbeatPort);
this.heartbeatOut =heartbeatSocket.getOutputStream() ; this.heartbeatOut =heartbeatSocket.getOutputStream() ;
@@ -89,10 +90,11 @@ public class TCPClient implements IClient {
// manda subito username per associare i due socket lato server // manda subito username per associare i due socket lato server
new ObjectOutputStream(heartbeatSocket.getOutputStream()).writeObject(user); new ObjectOutputStream(heartbeatSocket.getOutputStream()).writeObject(user);
heartbeatOut.flush(); heartbeatOut.flush();
new Thread(this::heartbeatLoop, "heartbeat").start();
running = true; running = true;
new Thread(this::heartbeatLoop, "heartbeat").start();
return true; return true;
} catch (IOException e) { } catch (IOException e) {
@@ -7,6 +7,7 @@ import it.polimi.ingsw.gc14.Network.ClientPlayer;
import it.polimi.ingsw.gc14.Network.EventType; import it.polimi.ingsw.gc14.Network.EventType;
import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer;
import it.polimi.ingsw.gc14.Network.NetworkEvents.ReconnectPlayer;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
@@ -124,17 +125,12 @@ public class TCPServer {
); );
clientSocket.getOutputStream().write(1); clientSocket.getOutputStream().write(1);
pendingHeartbeat.put(username, handler); pendingHeartbeat.put(username, handler);
synchronized (controller) {
handler.notifyModel(controller.getModel()); handler.notifyModel(controller.getModel());
}
Thread thread = new Thread(handler); Thread thread = new Thread(handler);
thread.start(); thread.start();
clientHandlers.add(handler); clientHandlers.add(handler);
connectedPlayers++; connectedPlayers++;
actionQueue.add(new ReconnectPlayer(username));
} else { } else {
clientSocket.getOutputStream().write(-1); clientSocket.getOutputStream().write(-1);
clientSocket.close(); clientSocket.close();