diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java index e3e5bec..8fefc33 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -29,6 +29,11 @@ import java.util.stream.Stream; */ public class Game implements Serializable { + + private ArrayList playerStanding; + public List getPlayerStanding() { + return playerStanding; + } /** * Returns the list of players participating in the game. * @@ -950,6 +955,9 @@ public class Game implements Serializable { forEach(x -> x.applyEffect(p)) ); currentState.GameStageUpdate(GameStages.ENDED); + playerStanding=new ArrayList<>(playersList); + playerStanding.sort((y,x)->x.getPrestigeValue()==y.getPrestigeValue()?Integer.compare(x.getFoodValue(),y.getFoodValue()):Integer.compare(x.getPrestigeValue(),y.getPrestigeValue())); + } /** @@ -984,5 +992,13 @@ public class Game implements Serializable { return true; } + public void EndGameForFeit(Player winner) { + currentState.GameStageUpdate(GameStages.ENDED); + playerStanding=new ArrayList<>(playersList); + playerStanding.remove(winner); + playerStanding.sort((y,x)->x.getPrestigeValue()==y.getPrestigeValue()?Integer.compare(x.getFoodValue(),y.getFoodValue()):Integer.compare(x.getPrestigeValue(),y.getPrestigeValue())); + playerStanding.addFirst(winner); + } + } 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 78c9d10..ebbeb10 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/MiniModel.java @@ -18,6 +18,7 @@ public class MiniModel implements Serializable { public CurrentState currentState; public Map players; public List availableTotems; + public List standingPlayers; // --- Costruttori --- @@ -37,6 +38,7 @@ public class MiniModel implements Serializable { this.currentState = currentState; this.players = new HashMap<>(); this.availableTotems = availableTotems; + this.standingPlayers = new ArrayList<>(); setPlayers(players); } @@ -72,6 +74,9 @@ public class MiniModel implements Serializable { public void setPlayer(Player player) { players.put(player.getUserName(), player); } + public void setStandingPlayers(List standingPlayers) { + this.standingPlayers = standingPlayers; + } public int getPositionByUsername(String username) { diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/EventType.java b/src/main/java/it/polimi/ingsw/gc14/Network/EventType.java index 2bf097f..72d4394 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/EventType.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/EventType.java @@ -18,5 +18,6 @@ public enum EventType { DISCONNECTED_PLAYER, RECONNECT_PLAYER, NEXT_ROUND, + ENDED_GAME, NO_OPTIONAL_CARD } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/EndedGame.java b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/EndedGame.java new file mode 100644 index 0000000..cfe3998 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/Network/NetworkEvents/EndedGame.java @@ -0,0 +1,50 @@ +package it.polimi.ingsw.gc14.Network.NetworkEvents; + +import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState; +import it.polimi.ingsw.gc14.Model.MiniModel; +import it.polimi.ingsw.gc14.Model.OrderLogicCard; +import it.polimi.ingsw.gc14.Model.Player; +import it.polimi.ingsw.gc14.Model.Slot; +import it.polimi.ingsw.gc14.Network.EventType; +import it.polimi.ingsw.gc14.Network.NetworkEvent; +import it.polimi.ingsw.gc14.View.IView; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * NetworkEvent to draw a tribe card from the lower card list. + */ +public class EndedGame extends NetworkEvent implements Serializable{ + + List players; + //TODO + public EndedGame(Map slotPlayerMap, OrderLogicCard orderLogicCard, CurrentState currentState, List players){ + super("SERVER",EventType.ENDED_GAME,false); + this.slotPlayerMap = slotPlayerMap; + this.orderLogicCard = orderLogicCard; + this.currentState = currentState; + this.players = players; + } + + /** + * @param gameController the Game Controller on which to apply the event + * @return true if the player could draw the card, false otherwise + */ + @Override + public boolean apply(GameController gameController){ + return false; + } + public boolean apply(MiniModel miniModel) + { + miniModel.setSlotPlayerMap(slotPlayerMap); + miniModel.setOrderLogicCard(orderLogicCard); + miniModel.setCurrentState(currentState); + miniModel.setPlayers(players); + miniModel.setStandingPlayers(players); + return true; + } + +} diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java index 02b3d08..d434fac 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java @@ -53,14 +53,15 @@ public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCa */ @Override public void onAction(NetworkEvent event) throws RemoteException { - synchronized (clientController) - { - if(event.getIsError()) { - clientController.view.showError(event.toString()); - } else { + if(event.getIsError()) { + clientController.view.showError(event.toString()); + } else { + synchronized (clientController) + { event.apply(clientController.miniModel); - clientController.view.render(); } + clientController.view.render(); + } } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java index b9b09fb..0499fb5 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java @@ -156,20 +156,25 @@ public class TCPClient implements IClient { e.printStackTrace(); break; } - synchronized (controller) { - if (read instanceof NetworkEvent event) { - if (event.getIsError()) { - controller.view.showError(event.toString()); - } else { - event.apply(controller.miniModel); - controller.view.render(); - } - } else if (read instanceof MiniModel model) { - controller.setModel(model); + if (read instanceof NetworkEvent event) { + if (event.getIsError()) { + controller.view.showError(event.toString()); + } else { + synchronized (controller) { + event.apply(controller.miniModel); + } controller.view.render(); + } + + } else if (read instanceof MiniModel model) { + synchronized (controller) { + controller.setModel(model); + } + controller.view.render(); } + } catch (ClassNotFoundException e) { e.printStackTrace(); break; diff --git a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java index 2321955..bf9224b 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java +++ b/src/main/java/it/polimi/ingsw/gc14/ServerLauncher.java @@ -11,6 +11,7 @@ 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.DisconnectedPlayer; +import it.polimi.ingsw.gc14.Network.NetworkEvents.EndedGame; import it.polimi.ingsw.gc14.Network.NetworkEvents.TotemChoice; import it.polimi.ingsw.gc14.Network.RMI.Server.RMIServer; import it.polimi.ingsw.gc14.Network.TCP.Server.TCPServer; @@ -130,16 +131,6 @@ public class ServerLauncher { playerList.remove(event.getUsername()); } } - } - serverRMI.notifyAll(event); - serverTCP.notifyAll(event); - if(game.getCurrentState().getRound()!=roundPrev) - { - ApplyNextRound nextRound=new ApplyNextRound(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayers()); - serverRMI.notifyAll(nextRound); - serverTCP.notifyAll(nextRound); - } - if(!event.getIsError()){ if(game.getCurrentState().getGameStage() == GameStages.ENDED){ if(!this.deleteSave()){ System.out.println("\n!!! Couldn't delete save !!!\n"); @@ -155,11 +146,26 @@ public class ServerLauncher { System.out.println("\n!!! Save failed !!!\n"); } } + serverRMI.notifyAll(event); + serverTCP.notifyAll(event); + if(game.getCurrentState().getRound()!=roundPrev) + { + ApplyNextRound nextRound=new ApplyNextRound(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayers()); + 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(game.getPlayerByUsername(playerList.keySet().stream().toList().getFirst())); + actionQueue.offer(new EndedGame(game.getSlotMap(), game.orderLogicCard, game.getCurrentState(),game.getPlayerStanding())); System.out.println("Timer expired: no player reconnected in 60s."); }, 1, TimeUnit.MINUTES); } @@ -237,7 +243,8 @@ public class ServerLauncher { launcher.run(); } catch (Exception e) { - System.out.println("Generic exception occurred"+e.getMessage()); + System.out.println("Generic exception occurred"); + e.printStackTrace(); } }).start(); diff --git a/src/main/java/it/polimi/ingsw/gc14/View/GUI/GUI.java b/src/main/java/it/polimi/ingsw/gc14/View/GUI/GUI.java index 9dd099e..f1b14b3 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/GUI/GUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/GUI/GUI.java @@ -82,15 +82,19 @@ public class GUI extends Application implements IView { public void render() { if(controller.miniModel.currentState.getGameStage()==TOTEM_CHOICE) { Platform.runLater(() -> { - controllerTotem.render(); - primaryStage.setScene(totemScene); - primaryStage.setFullScreen(true); + synchronized (this) { + controllerTotem.render(); + primaryStage.setScene(totemScene); + primaryStage.setFullScreen(true); + } }); } else { Platform.runLater(() -> { - controllerMain.render(); - primaryStage.setScene(mainScene); - primaryStage.setFullScreen(true); + synchronized (this) { + controllerMain.render(); + primaryStage.setScene(mainScene); + primaryStage.setFullScreen(true); + } }); } } 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 e32a6af..e05577b 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 @@ -86,40 +86,36 @@ public class MainFXMLController { - public void render() { - - synchronized (controller) - { - if (old_state_stage==null) { - renderBackground(); - renderUpper(); - renderBoard(); - renderLower(); + public synchronized void render() { + if (old_state_stage==null) { + renderBackground(); + renderUpper(); + renderBoard(); + renderLower(); + renderMyHand(); + renderSidePanel(); + } else if (old_state_stage==SLOT_CHOICE ) { + System.out.println("OLD: "+old_state_stage+", NEW: "+controller.miniModel.currentState.getGameStage()); + System.out.println("RIDISEGNO BOARD\n"); + renderBoard(); + } else if (old_state_stage==RES_ACTIONS) { + System.out.println("OLD: "+old_state_stage+", NEW: "+controller.miniModel.currentState.getGameStage()); + System.out.println("RIDISEGNO TUTTO. USERNAME: "+old_state_username); + renderUpper(); + renderBoard(); + renderLower(); + renderSidePanel(); + if (Objects.equals(old_state_username, controller.myUsername)) { renderMyHand(); - renderSidePanel(); - } else if (old_state_stage==SLOT_CHOICE ) { - System.out.println("OLD: "+old_state_stage+", NEW: "+controller.miniModel.currentState.getGameStage()); - System.out.println("RIDISEGNO BOARD\n"); - renderBoard(); - } else if (old_state_stage==RES_ACTIONS) { - System.out.println("OLD: "+old_state_stage+", NEW: "+controller.miniModel.currentState.getGameStage()); - System.out.println("RIDISEGNO TUTTO. USERNAME: "+old_state_username); - renderUpper(); - renderBoard(); - renderLower(); - renderSidePanel(); - if (Objects.equals(old_state_username, controller.myUsername)) { - renderMyHand(); - } - - // TODO: se sono io a pescare renderizzo myHand, altrimenti no (non è scontato) - } else { - System.out.println("NON GESTITO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); } - old_state_stage=controller.miniModel.currentState.getGameStage(); - old_state_username=controller.miniModel.currentState.getCurrentPlayer().getUserName(); + // TODO: se sono io a pescare renderizzo myHand, altrimenti no (non è scontato) + } else { + System.out.println("NON GESTITO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); } + + old_state_stage=controller.miniModel.currentState.getGameStage(); + old_state_username=controller.miniModel.currentState.getCurrentPlayer().getUserName(); // TODO: le info in sidepanel non vengono aggiornate sempre aggiornate, bisogna prima capire dove metterle } @@ -272,21 +268,24 @@ public class MainFXMLController { upperList.setAlignment(Pos.CENTER); upperList.getChildren().clear(); - int i = 0; - for (TribeCard card : controller.miniModel.board.upperListTribe) { - final int index = i; - StackPane img = createCard(card, true, true); - img.setOnMouseClicked(e -> controller.drawUpperTribeCard(controller.myUsername, index)); - upperList.getChildren().add(img); - i++; - } - i = 0; - for (BuildingCard card : controller.miniModel.board.upperListBuilding) { - final int index = i; - StackPane img = createCard(card, true, true); - img.setOnMouseClicked(e -> controller.drawUpperBuildingCard(controller.myUsername, index)); - upperList.getChildren().add(img); - i++; + synchronized (controller) + { + int i = 0; + for (TribeCard card : controller.miniModel.board.upperListTribe) { + final int index = i; + StackPane img = createCard(card, true, true); + img.setOnMouseClicked(e -> controller.drawUpperTribeCard(controller.myUsername, index)); + upperList.getChildren().add(img); + i++; + } + i = 0; + for (BuildingCard card : controller.miniModel.board.upperListBuilding) { + final int index = i; + StackPane img = createCard(card, true, true); + img.setOnMouseClicked(e -> controller.drawUpperBuildingCard(controller.myUsername, index)); + upperList.getChildren().add(img); + i++; + } } } private void renderLower() { @@ -294,21 +293,24 @@ public class MainFXMLController { lowerList.setAlignment(Pos.CENTER); lowerList.getChildren().clear(); - int i = 0; - for (TribeCard card : controller.miniModel.board.lowerListTribe) { - final int index = i; - StackPane img = createCard(card, true, true); - img.setOnMouseClicked(e -> controller.drawLowerTribeCard(controller.myUsername, index)); - lowerList.getChildren().add(img); - i++; - } - i = 0; - for (BuildingCard card : controller.miniModel.board.lowerListBuilding) { - final int index = i; - StackPane img = createCard(card, true, true); - img.setOnMouseClicked(e -> controller.drawLowerBuildingCard(controller.myUsername, index)); - lowerList.getChildren().add(img); - i++; + synchronized (controller) + { + int i = 0; + for (TribeCard card : controller.miniModel.board.lowerListTribe) { + final int index = i; + StackPane img = createCard(card, true, true); + img.setOnMouseClicked(e -> controller.drawLowerTribeCard(controller.myUsername, index)); + lowerList.getChildren().add(img); + i++; + } + i = 0; + for (BuildingCard card : controller.miniModel.board.lowerListBuilding) { + final int index = i; + StackPane img = createCard(card, true, true); + img.setOnMouseClicked(e -> controller.drawLowerBuildingCard(controller.myUsername, index)); + lowerList.getChildren().add(img); + i++; + } } } private void renderDeck() { diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java index 2ccaf7e..deed706 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java @@ -89,7 +89,7 @@ public class TUI implements IView { * Delegates to {@link #renderBoard()}. */ @Override - public void render() { + public synchronized void render() { if(model != null) { if(model.currentState.getGameStage().equals(GameStages.TOTEM_CHOICE)) @@ -98,8 +98,8 @@ public class TUI implements IView { } else if(model.currentState.getGameStage().equals(GameStages.ENDED)) { - //renderStanding - renderBoard(); + renderStanding(); + return; } else { @@ -109,6 +109,31 @@ public class TUI implements IView { } } + private void renderStanding() { + if(model.standingPlayers!=null) + { + StringBuilder stringBuilder=new StringBuilder(); + for(int i = 0; i< model.standingPlayers.size()/2; i++) + { + stringBuilder.append(AsciiTable.sideBySide(List.of(model.standingPlayers.get((i*2)).toString().split("\n")),List.of(model.standingPlayers.get((i*2+1)).toString().split("\n")),2)); + } + stringBuilder.append("\n"); + if(model.standingPlayers.size()%2!=0) + { + stringBuilder.append(model.standingPlayers.get(model.standingPlayers.size()-1).toString()); + stringBuilder.append("\n"); + } + System.out.println(stringBuilder); + if(model.standingPlayers.get(0).getUserName().equals(username)) + { + System.out.println("GAME ENDED: !!!YOU WON!!!"); + } + else { + System.out.println("GAME ENDED: !!!YOU LOST!!!"); + } + } + } + /** * Renders a full view of the game, combining both player status * and board status.