Merge pull request #117
Fixed: now after a forfeit win, when the player is disconnected can be created a new game without any bug. Added: comment in some functions like doFirstEvent, RMIServer start and TCPServer start.
This commit is contained in:
@@ -30,7 +30,7 @@ import java.rmi.*;
|
|||||||
*/
|
*/
|
||||||
public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
||||||
private String host;
|
private String host;
|
||||||
private GameController controller;
|
private final GameController controller;
|
||||||
private Registry registry;
|
private Registry registry;
|
||||||
private int nPort;
|
private int nPort;
|
||||||
|
|
||||||
@@ -105,23 +105,13 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
|||||||
System.out.println("(After crash)Reconnected player: " + username);
|
System.out.println("(After crash)Reconnected player: " + username);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (playerList.containsKey(username) && !playerList.get(username)) {
|
|
||||||
playerList.put(username, true);
|
|
||||||
clients.put(username, callback);
|
|
||||||
System.out.println("Reconnected player: " + username);
|
|
||||||
startWatchdog(username);
|
|
||||||
Game game = controller.getModel();
|
|
||||||
callback.onGameInit(new MiniModel(game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers(),game.getAvailableTotems(),game.getUpperListTribeCards(),game.getLowerListTribeCards(),game.getUpperListBuilding(),game.getLowerListBuilding()));
|
|
||||||
System.out.println("Model sent: " + username);
|
|
||||||
actionQueue.add(new ReconnectPlayer(username));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (playerList.isEmpty()) {
|
if (playerList.isEmpty()) {
|
||||||
controller.setModel(new Game(preferredInt));
|
controller.setModel(new Game(preferredInt));
|
||||||
playerList.setLimit(preferredInt);
|
playerList.setLimit(preferredInt);
|
||||||
|
System.out.println("Game Created With :"+preferredInt+" Players");
|
||||||
}
|
}
|
||||||
if (controller.addPlayer(username)) {
|
if (controller.addPlayer(username)) {
|
||||||
clients.put(username, callback);
|
clients.put(username, callback);
|
||||||
@@ -130,7 +120,7 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
|||||||
System.out.println("Accepted player: " + username);
|
System.out.println("Accepted player: " + username);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Reconnection: player was offline
|
}
|
||||||
if (playerList.containsKey(username) && !playerList.get(username)) {
|
if (playerList.containsKey(username) && !playerList.get(username)) {
|
||||||
playerList.put(username, true);
|
playerList.put(username, true);
|
||||||
clients.put(username, callback);
|
clients.put(username, callback);
|
||||||
@@ -142,7 +132,6 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
|
|||||||
actionQueue.add(new ReconnectPlayer(username));
|
actionQueue.add(new ReconnectPlayer(username));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,12 +179,11 @@ public class TCPServer {
|
|||||||
|
|
||||||
synchronized (controller) {
|
synchronized (controller) {
|
||||||
String username = eventAddPlayer.getUsername();
|
String username = eventAddPlayer.getUsername();
|
||||||
|
//reconnect players after a server crash
|
||||||
if (serverCrashed) {
|
if (serverCrashed) {
|
||||||
if (controller.getModel().getPlayers().stream()
|
if (controller.getModel().getPlayers().stream()
|
||||||
.anyMatch(p -> p.getUserName().equals(username))
|
.anyMatch(p -> p.getUserName().equals(username))
|
||||||
&& !playerList.containsKey(username)) {
|
&& !playerList.containsKey(username)) {
|
||||||
|
|
||||||
playerList.put(username, true);
|
playerList.put(username, true);
|
||||||
System.out.println("(After crash)Reconnected player: " + username);
|
System.out.println("(After crash)Reconnected player: " + username);
|
||||||
|
|
||||||
@@ -206,54 +205,18 @@ public class TCPServer {
|
|||||||
|
|
||||||
clientHandlers.add(handler);
|
clientHandlers.add(handler);
|
||||||
connectedPlayers++;
|
connectedPlayers++;
|
||||||
|
return;
|
||||||
|
|
||||||
} 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.getSlotMap(),
|
|
||||||
game.orderLogicCard,
|
|
||||||
game.getCurrentState(),
|
|
||||||
game.getPlayers(),
|
|
||||||
game.getAvailableTotems(),
|
|
||||||
game.getUpperListTribeCards(),game.getLowerListTribeCards(),game.getUpperListBuilding(),game.getLowerListBuilding()
|
|
||||||
));
|
|
||||||
|
|
||||||
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 {
|
}
|
||||||
|
//manages a new player adding
|
||||||
|
else {
|
||||||
if (playerList.isEmpty()) {
|
if (playerList.isEmpty()) {
|
||||||
Game model = new Game(eventAddPlayer.getProposedNPlayer());
|
Game model = new Game(eventAddPlayer.getProposedNPlayer());
|
||||||
controller.setModel(model);
|
controller.setModel(model);
|
||||||
playerList.setLimit(eventAddPlayer.getProposedNPlayer());
|
playerList.setLimit(eventAddPlayer.getProposedNPlayer());
|
||||||
|
System.out.println("Game Created With :"+eventAddPlayer.getProposedNPlayer()+" Players");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller.addPlayer(username)) {
|
if (controller.addPlayer(username)) {
|
||||||
@@ -278,8 +241,12 @@ public class TCPServer {
|
|||||||
|
|
||||||
clientHandlers.add(handler);
|
clientHandlers.add(handler);
|
||||||
connectedPlayers++;
|
connectedPlayers++;
|
||||||
|
return;
|
||||||
|
|
||||||
} else if (playerList.containsKey(username)
|
}
|
||||||
|
}
|
||||||
|
//reconnect a previously disconnected player
|
||||||
|
if (playerList.containsKey(username)
|
||||||
&& !playerList.get(username)) {
|
&& !playerList.get(username)) {
|
||||||
|
|
||||||
playerList.put(username, true);
|
playerList.put(username, true);
|
||||||
@@ -306,7 +273,6 @@ public class TCPServer {
|
|||||||
game.getPlayers(),
|
game.getPlayers(),
|
||||||
game.getAvailableTotems(),
|
game.getAvailableTotems(),
|
||||||
game.getUpperListTribeCards(),game.getLowerListTribeCards(),game.getUpperListBuilding(),game.getLowerListBuilding()
|
game.getUpperListTribeCards(),game.getLowerListTribeCards(),game.getUpperListBuilding(),game.getLowerListBuilding()
|
||||||
|
|
||||||
));
|
));
|
||||||
|
|
||||||
Thread thread = new Thread(handler);
|
Thread thread = new Thread(handler);
|
||||||
@@ -322,7 +288,7 @@ public class TCPServer {
|
|||||||
System.out.println("Player could not be added. Connection terminated.");
|
System.out.println("Player could not be added. Connection terminated.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException | ClassNotFoundException e) {
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class ServerLauncher {
|
|||||||
BlockingQueue<NetworkEvent> actionQueue;
|
BlockingQueue<NetworkEvent> actionQueue;
|
||||||
|
|
||||||
/** Game controller. Used to apply events */
|
/** Game controller. Used to apply events */
|
||||||
GameController gameController;
|
final GameController gameController;
|
||||||
|
|
||||||
/** Server RMI. Handles RMI clients */
|
/** Server RMI. Handles RMI clients */
|
||||||
RMIServer serverRMI;
|
RMIServer serverRMI;
|
||||||
@@ -106,8 +106,10 @@ public class ServerLauncher {
|
|||||||
*/
|
*/
|
||||||
public boolean doFirstEvent() throws InterruptedException {
|
public boolean doFirstEvent() throws InterruptedException {
|
||||||
NetworkEvent event = actionQueue.take();
|
NetworkEvent event = actionQueue.take();
|
||||||
if(gameController.getModel()!=null && !gameController.getModel().getCurrentState().equals(GameStages.ENDED))
|
//Verify that the model exist and if it exists that's not ended
|
||||||
|
if(gameController.getModel()!=null && gameController.getModel().getCurrentState().getGameStage()!=GameStages.ENDED)
|
||||||
{
|
{
|
||||||
|
//if there is only one player ignore every event different by reconnection
|
||||||
if(disconnectionTimer!=null && event.getEventType() != EventType.RECONNECT_PLAYER)
|
if(disconnectionTimer!=null && event.getEventType() != EventType.RECONNECT_PLAYER)
|
||||||
{
|
{
|
||||||
event.setIsError(true);
|
event.setIsError(true);
|
||||||
@@ -115,16 +117,24 @@ public class ServerLauncher {
|
|||||||
serverTCP.notifyAll(event);
|
serverTCP.notifyAll(event);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Cancel the timer if another player is reconnected , so there are more than one player
|
||||||
if (event.getEventType() == EventType.RECONNECT_PLAYER && disconnectionTimer != null && !disconnectionTimer.isDone()) {
|
if (event.getEventType() == EventType.RECONNECT_PLAYER && disconnectionTimer != null && !disconnectionTimer.isDone()) {
|
||||||
disconnectionTimer.cancel(false);
|
disconnectionTimer.cancel(false);
|
||||||
disconnectionTimer = null;
|
disconnectionTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int roundPrev=gameController.getModel().getCurrentState().getRound();
|
int roundPrev=gameController.getModel().getCurrentState().getRound();
|
||||||
synchronized(gameController){
|
synchronized(gameController){
|
||||||
|
//applies the event and set if is an error
|
||||||
event.setIsError(!event.apply(gameController));
|
event.setIsError(!event.apply(gameController));
|
||||||
Game game=gameController.getModel();
|
Game game=gameController.getModel();
|
||||||
|
//if the event wasn't an error , it will be sent to players
|
||||||
if(!event.getIsError())
|
if(!event.getIsError())
|
||||||
{
|
{
|
||||||
|
if(!this.gameSave() ){
|
||||||
|
System.out.println("\n!!! Save failed !!!\n");
|
||||||
|
}
|
||||||
if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER)&& game.getCurrentState().getGameStage().equals(GameStages.WAITING))
|
if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER)&& game.getCurrentState().getGameStage().equals(GameStages.WAITING))
|
||||||
{
|
{
|
||||||
playerList.remove(event.getUsername());
|
playerList.remove(event.getUsername());
|
||||||
@@ -132,11 +142,43 @@ public class ServerLauncher {
|
|||||||
event.setData(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(), game.getPlayers());
|
event.setData(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(), game.getPlayers());
|
||||||
if (event.getEventType().equals(EventType.TOTEM_CHOICE)) {
|
if (event.getEventType().equals(EventType.TOTEM_CHOICE)) {
|
||||||
((TotemChoice) event).setAvailableTotems(gameController.getModel().getAvailableTotems());
|
((TotemChoice) event).setAvailableTotems(gameController.getModel().getAvailableTotems());
|
||||||
} else if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && game.getCurrentState().equals(GameStages.WAITING)) {
|
} else if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && game.getCurrentState().getGameStage().equals(GameStages.WAITING)) {
|
||||||
playerList.remove(event.getUsername());
|
playerList.remove(event.getUsername());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(game.getCurrentState().getGameStage() == GameStages.ENDED){
|
//if there is only one player the game will be suspended and starts the forfeit timer
|
||||||
|
if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && playerList.values().stream().filter(x -> x).count() == 1&& game.getCurrentState().getGameStage() != GameStages.ENDED) {
|
||||||
|
if (disconnectionTimer != null && !disconnectionTimer.isDone()) {
|
||||||
|
disconnectionTimer.cancel(false);
|
||||||
|
}
|
||||||
|
//schedule endgame for forfeit
|
||||||
|
disconnectionTimer = timerExecutor.schedule(() -> {
|
||||||
|
game.EndGameForFeit();
|
||||||
|
serverRMI.notifyAll(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding()));
|
||||||
|
serverTCP.notifyAll(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding()));
|
||||||
|
System.out.println("Timer expired: no player reconnected in 60s.");
|
||||||
|
for(Map.Entry<String,Boolean> entry:playerList.entrySet()){
|
||||||
|
if(!entry.getValue())
|
||||||
|
playerList.remove(entry.getKey());
|
||||||
|
}
|
||||||
|
if(!this.deleteSave()){
|
||||||
|
System.out.println("\n!!! Couldn't delete save !!!\n");
|
||||||
|
}
|
||||||
|
disconnectionTimer = null;
|
||||||
|
}, 1, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
//if the round is changed send a new next round event , the previous event is ignored and directly sent the next round(also upper and lower lists updated)
|
||||||
|
if(game.getCurrentState().getRound()!=roundPrev)
|
||||||
|
{
|
||||||
|
ApplyNextRound nextRound=new ApplyNextRound(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayers(),game.getUpperListTribeCards(),game.getLowerListTribeCards(),game.getUpperListBuilding(),game.getLowerListBuilding());
|
||||||
|
serverRMI.notifyAll(nextRound);
|
||||||
|
serverTCP.notifyAll(nextRound);
|
||||||
|
}
|
||||||
|
// if the game ends after the event, delete the game. await that all players are disconnected and then create a new game
|
||||||
|
else if(game.getCurrentState().getGameStage().equals(GameStages.ENDED))
|
||||||
|
{
|
||||||
|
serverRMI.notifyAll(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding()));
|
||||||
|
serverTCP.notifyAll(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding()));
|
||||||
if(!this.deleteSave()){
|
if(!this.deleteSave()){
|
||||||
System.out.println("\n!!! Couldn't delete save !!!\n");
|
System.out.println("\n!!! Couldn't delete save !!!\n");
|
||||||
}
|
}
|
||||||
@@ -147,48 +189,26 @@ public class ServerLauncher {
|
|||||||
serverRMI.setServerCrashed(false);
|
serverRMI.setServerCrashed(false);
|
||||||
serverTCP.setServerCrashed(false);
|
serverTCP.setServerCrashed(false);
|
||||||
}
|
}
|
||||||
else if(!this.gameSave() ){
|
//notify the event
|
||||||
System.out.println("\n!!! Save failed !!!\n");
|
else {
|
||||||
}
|
|
||||||
}
|
|
||||||
serverRMI.notifyAll(event);
|
serverRMI.notifyAll(event);
|
||||||
serverTCP.notifyAll(event);
|
serverTCP.notifyAll(event);
|
||||||
if(game.getCurrentState().getRound()!=roundPrev)
|
|
||||||
{
|
|
||||||
ApplyNextRound nextRound=new ApplyNextRound(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayers(),game.getUpperListTribeCards(),game.getLowerListTribeCards(),game.getUpperListBuilding(),game.getLowerListBuilding());
|
|
||||||
serverRMI.notifyAll(nextRound);
|
|
||||||
serverTCP.notifyAll(nextRound);
|
|
||||||
}
|
}
|
||||||
else if(game.getCurrentState().getGameStage().equals(GameStages.ENDED))
|
|
||||||
{
|
|
||||||
serverRMI.notifyAll(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding()));
|
|
||||||
serverTCP.notifyAll(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding()));
|
|
||||||
}
|
|
||||||
if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && playerList.values().stream().filter(x -> x).count() == 1&& game.getCurrentState().getGameStage() != GameStages.ENDED) {
|
|
||||||
if (disconnectionTimer != null && !disconnectionTimer.isDone()) {
|
|
||||||
disconnectionTimer.cancel(false);
|
|
||||||
}
|
|
||||||
disconnectionTimer = timerExecutor.schedule(() -> {
|
|
||||||
game.EndGameForFeit();
|
|
||||||
serverRMI.notifyAll(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding()));
|
|
||||||
serverTCP.notifyAll(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding()));
|
|
||||||
System.out.println("Timer expired: no player reconnected in 60s.");
|
|
||||||
if(!this.deleteSave()){
|
|
||||||
System.out.println("\n!!! Couldn't delete save !!!\n");
|
|
||||||
}
|
|
||||||
}, 1, TimeUnit.MINUTES);
|
|
||||||
}
|
}
|
||||||
return !event.getIsError();
|
return !event.getIsError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
// removes disconneted players when the game is ended
|
||||||
if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER))
|
if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER))
|
||||||
{
|
{
|
||||||
playerList.remove(event.getUsername());
|
playerList.remove(event.getUsername());
|
||||||
if(playerList.isEmpty())
|
if(playerList.isEmpty())
|
||||||
{
|
{
|
||||||
gameController.setModel(null);
|
gameController.setModel(null);
|
||||||
|
System.out.println("\n!!! Player list is now empty, ready for a new game init !!!\n");
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -253,12 +273,12 @@ public class ServerLauncher {
|
|||||||
MiniModel miniModel;
|
MiniModel miniModel;
|
||||||
synchronized (gameController) {
|
synchronized (gameController) {
|
||||||
Game game = gameController.getModel();
|
Game game = gameController.getModel();
|
||||||
miniModel= new MiniModel(game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers(), new ArrayList<>(List.of(Totems.values())),game.getUpperListTribeCards(),game.getLowerListTribeCards(),game.getUpperListBuilding(),game.getLowerListBuilding());
|
miniModel= new MiniModel(game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers(), game.getAvailableTotems(),game.getUpperListTribeCards(),game.getLowerListTribeCards(),game.getUpperListBuilding(),game.getLowerListBuilding());
|
||||||
}
|
}
|
||||||
serverRMI.notifyAll(miniModel);
|
serverRMI.notifyAll(miniModel);
|
||||||
serverTCP.notifyAll(miniModel);
|
serverTCP.notifyAll(miniModel);
|
||||||
view = new TUI(miniModel);
|
view = new TUI(miniModel);
|
||||||
view.fullRender();
|
view.render();
|
||||||
}).start();
|
}).start();
|
||||||
});
|
});
|
||||||
new Thread(()-> {
|
new Thread(()-> {
|
||||||
@@ -290,10 +310,10 @@ public class ServerLauncher {
|
|||||||
while (true) {
|
while (true) {
|
||||||
try{
|
try{
|
||||||
this.doFirstEvent();
|
this.doFirstEvent();
|
||||||
if(view!=null)
|
// if(view!=null)
|
||||||
{
|
// {
|
||||||
view.fullRender();
|
// view.fullRender();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
catch(InterruptedException e){
|
catch(InterruptedException e){
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
|
|||||||
Reference in New Issue
Block a user