diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java b/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java index 297bef1..6ef4e2a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java @@ -21,6 +21,7 @@ public class MiniModel implements Serializable { public ArrayList lowerListTribeCards; public ArrayList upperListBuildingCards; public ArrayList lowerListBuildingCards; + public ArrayList disconnectedPlayers; /** * Map associating each occupied slot with the corresponding player. @@ -64,6 +65,7 @@ public class MiniModel implements Serializable { this.lowerListTribeCards = lowerListTribeCards; this.upperListBuildingCards = upperListBuildingCards; this.lowerListBuildingCards = lowerListBuildingCards; + this.disconnectedPlayers = new ArrayList<>(); } /** @@ -80,7 +82,7 @@ public class MiniModel implements Serializable { OrderLogicCard orderLogicCard, CurrentState currentState, List players, - List availableTotems,ArrayList upperListTribeCards,ArrayListlowerListTribeCards,ArrayList upperListBuildingCards,ArrayListlowerListBuildingCards) { + List availableTotems,ArrayList upperListTribeCards,ArrayListlowerListTribeCards,ArrayList upperListBuildingCards,ArrayListlowerListBuildingCards, ArrayList disconnectedPlayers) { this.slotPlayerMap = slotPlayerMap; this.orderLogicCard = orderLogicCard; @@ -92,6 +94,7 @@ public class MiniModel implements Serializable { this.lowerListTribeCards = lowerListTribeCards; this.upperListBuildingCards = upperListBuildingCards; this.lowerListBuildingCards = lowerListBuildingCards; + this.disconnectedPlayers = disconnectedPlayers; setPlayers(players); } @@ -181,4 +184,9 @@ public class MiniModel implements Serializable { } return -1; } + + //TODO + public void setDisconnectedPlayers (ArrayList disconnectedPlayers){ + this.disconnectedPlayers=disconnectedPlayers; + } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DisconnectedPlayer.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DisconnectedPlayer.java index d774916..f0acee5 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DisconnectedPlayer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/DisconnectedPlayer.java @@ -6,13 +6,20 @@ import it.polimi.ingsw.gc14.Model.MiniModel; import it.polimi.ingsw.gc14.Network.EventType; import it.polimi.ingsw.gc14.Network.NetworkEvent; +import javax.smartcardio.Card; import java.io.Serializable; +import java.util.ArrayList; /** * NetworkEvent to avoid drawing a card from the lower card list */ public class DisconnectedPlayer extends NetworkEvent implements Serializable{ + private ArrayList disconnectedPlayers; + public void setDisconnected(ArrayList players) + { + this.disconnectedPlayers=players; + } /** * Class constructor. * Initializes all the attributes. @@ -22,6 +29,7 @@ public class DisconnectedPlayer extends NetworkEvent implements Serializable{ super(username, EventType.DISCONNECTED_PLAYER, false, ErrorType.GENERIC_ERROR); } + /** * @param gameController the Game Controller on which to apply the event * @return true if the player could skipTheTurn, false otherwise @@ -42,6 +50,7 @@ public class DisconnectedPlayer extends NetworkEvent implements Serializable{ miniModel.setOrderLogicCard(orderLogicCard); miniModel.setCurrentState(currentState); miniModel.setSlotPlayerMap(slotPlayerMap); + miniModel.setDisconnectedPlayers(disconnectedPlayers); } return true; } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/ReconnectPlayer.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/ReconnectPlayer.java index bb4e809..c4448d3 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/ReconnectPlayer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/ReconnectPlayer.java @@ -7,12 +7,17 @@ import it.polimi.ingsw.gc14.Network.EventType; import it.polimi.ingsw.gc14.Network.NetworkEvent; import java.io.Serializable; +import java.util.ArrayList; /** * Network event used to notify that a player has reconnected to the game. */ public class ReconnectPlayer extends NetworkEvent implements Serializable { - + private ArrayList disconnectedPlayers; + public void setDisconnected(ArrayList players) + { + this.disconnectedPlayers=players; + } /** * Constructs a reconnection event for the specified player. * @@ -55,6 +60,7 @@ public class ReconnectPlayer extends NetworkEvent implements Serializable { miniModel.setOrderLogicCard(orderLogicCard); miniModel.setCurrentState(currentState); miniModel.setSlotPlayerMap(slotPlayerMap); + miniModel.setDisconnectedPlayers(disconnectedPlayers); } return true; diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java index 87c68c4..53287a5 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Server/RMIServer.java @@ -15,11 +15,14 @@ import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; +import java.util.ArrayList; +import java.util.Collections; import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.rmi.*; +import java.util.stream.Collectors; /** @@ -127,7 +130,7 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer { 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())); + callback.onGameInit(new MiniModel(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(), game.getPlayers(), game.getAvailableTotems(), game.getUpperListTribeCards(), game.getLowerListTribeCards(), game.getUpperListBuilding(), game.getLowerListBuilding(), game.disconnetedPlayers.entrySet().stream().filter(Map.Entry::getValue).map(x -> x.getKey().getUserName()).collect(Collectors.toCollection(ArrayList::new)))); System.out.println("Model sent: " + username); actionQueue.add(new ReconnectPlayer(username)); return null; diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java index 8e5af26..81cfb9b 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * TCP server responsible for accepting client connections, @@ -265,7 +266,7 @@ public class TCPServer { game.getCurrentState(), game.getPlayers(), game.getAvailableTotems(), - game.getUpperListTribeCards(), game.getLowerListTribeCards(), game.getUpperListBuilding(), game.getLowerListBuilding() + game.getUpperListTribeCards(), game.getLowerListTribeCards(), game.getUpperListBuilding(), game.getLowerListBuilding(), game.disconnetedPlayers.entrySet().stream().filter(Map.Entry::getValue).map(x -> x.getKey().getUserName()).collect(Collectors.toCollection(ArrayList::new)) )); Thread thread = new Thread(handler); diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index d385f74..53e123a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -9,9 +9,7 @@ import it.polimi.ingsw.gc14.Model.Player; import it.polimi.ingsw.gc14.Model.Totems; import it.polimi.ingsw.gc14.Network.EventType; import it.polimi.ingsw.gc14.Network.NetworkEvent; -import it.polimi.ingsw.gc14.Network.NetworkEvents.ApplyNextRound; -import it.polimi.ingsw.gc14.Network.NetworkEvents.EndedGame; -import it.polimi.ingsw.gc14.Network.NetworkEvents.TotemChoice; +import it.polimi.ingsw.gc14.Network.NetworkEvents.*; import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer; import it.polimi.ingsw.gc14.Network.TCP.Server.TCPServer; import it.polimi.ingsw.gc14.View.TUI.TUI; @@ -24,6 +22,7 @@ import java.rmi.RemoteException; import java.util.*; import java.util.concurrent.*; import java.net.*; +import java.util.stream.Collectors; /** @@ -110,19 +109,25 @@ public class ServerLauncher { 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.setIsError(true); - serverRMI.notifyAll(event); - serverTCP.notifyAll(event); - return false; + if(event.getEventType() != EventType.RECONNECT_PLAYER) + { + event.setIsError(true); + serverRMI.notifyAll(event); + serverTCP.notifyAll(event); + return false; + }else if(event.getEventType() != EventType.DISCONNECTED_PLAYER) + { + disconnectionTimer.cancel(true); + disconnectionTimer = null; + playerList.clear(); + gameController.setModel(null); + System.out.println("\n!!! Player list is now empty, ready for a new game init !!!\n"); + return true; + } } - //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()) { - disconnectionTimer.cancel(false); - disconnectionTimer = null; - } synchronized(gameController){ int roundPrev=gameController.getModel().getCurrentState().getRound(); //applies the event and set if is an error @@ -131,19 +136,29 @@ public class ServerLauncher { //if the event wasn't an error , it will be sent to players if(!event.getIsError()) { + //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()) { + disconnectionTimer.cancel(false); + disconnectionTimer = null; + } if(!this.gameSave() ){ System.out.println("\n!!! Save failed !!!\n"); } if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER)&& game.getCurrentState().getGameStage().equals(GameStages.WAITING)) { playerList.remove(event.getUsername()); + return true; }else { event.setData(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(), game.getPlayers()); - if (event.getEventType().equals(EventType.TOTEM_CHOICE)) { - ((TotemChoice) event).setAvailableTotems(gameController.getModel().getAvailableTotems()); - } else if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && game.getCurrentState().getGameStage().equals(GameStages.WAITING)) { - playerList.remove(event.getUsername()); - } + } + if (event.getEventType().equals(EventType.TOTEM_CHOICE)) { + ((TotemChoice) event).setAvailableTotems(gameController.getModel().getAvailableTotems()); + }else if (event.getEventType().equals(EventType.RECONNECT_PLAYER)) + { + ((ReconnectPlayer) event).setDisconnected(game.disconnetedPlayers.entrySet().stream().filter(Map.Entry::getValue).map(x -> x.getKey().getUserName()).collect(Collectors.toCollection(ArrayList::new))); + }else if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER)) + { + ((DisconnectedPlayer) event).setDisconnected(game.disconnetedPlayers.entrySet().stream().filter(Map.Entry::getValue).map(x -> x.getKey().getUserName()).collect(Collectors.toCollection(ArrayList::new))); } //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) { @@ -274,7 +289,7 @@ public class ServerLauncher { MiniModel miniModel; synchronized (gameController) { Game game = gameController.getModel(); - miniModel= new MiniModel(game.getSlotMap(), game.orderLogicCard,game.getCurrentState(),game.getPlayers(), game.getAvailableTotems(),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(), game.disconnetedPlayers.entrySet().stream().filter(Map.Entry::getValue).map(x -> x.getKey().getUserName()).collect(Collectors.toCollection(ArrayList::new))); } serverRMI.notifyAll(miniModel); serverTCP.notifyAll(miniModel); diff --git a/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainFXMLController.java b/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainFXMLController.java index 9fdf3a0..cd563f5 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainFXMLController.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/GUI/MainFXMLController.java @@ -324,6 +324,9 @@ public class MainFXMLController { tt.play(); } } + if (controller.miniModel.disconnectedPlayers.contains(player.getUserName())) { + card.getStyleClass().add("player-card-crashed"); + } headerRow.getChildren().addAll(totem, usernameLabel); // Riga 2: cibo + prestigio + building diff --git a/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java b/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java index a6ec413..5a431cc 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/GUI/TotemFXMLController.java @@ -75,7 +75,7 @@ public class TotemFXMLController { if (myTurn) { turnBanner.setText("✦ It's your turn to choose ✦"); turnBanner.setStyle( - "-fx-font-family: 'Cinzel'; -fx-font-size: 13; -fx-letter-spacing: 3;" + + "-fx-font-family: 'Cinzel'; -fx-font-size: 13; -fx-font-weight: 'bold'; -fx-letter-spacing: 3;" + "-fx-text-fill: #000000;" + "-fx-background-color: linear-gradient(to right, #f4c05a, #c8791a, #f4c05a);" + "-fx-border-color: #000000; -fx-border-width: 1;" + diff --git a/src/main/resources/GUIScene/styles.css b/src/main/resources/GUIScene/styles.css index 8962330..8a979fd 100644 --- a/src/main/resources/GUIScene/styles.css +++ b/src/main/resources/GUIScene/styles.css @@ -41,6 +41,13 @@ -fx-background-radius: 15; -fx-background-color: #f18f1c; } +.player-card-crashed { + -fx-border-color: #711423; + -fx-border-width: 2; + -fx-border-radius: 15; + -fx-background-radius: 15; + -fx-background-color: #8C8C8CFF; +} .frame { -fx-background-color: rgba(255,255,255,0.35);