Merge pull request #102 from rubenpirreram/game-ending

Game ending
This commit is contained in:
rubenpirreram
2026-05-15 19:17:56 +02:00
committed by GitHub
10 changed files with 212 additions and 96 deletions
@@ -29,6 +29,11 @@ import java.util.stream.Stream;
*/
public class Game implements Serializable {
private ArrayList<Player> playerStanding;
public List<Player> 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);
}
}
@@ -18,6 +18,7 @@ public class MiniModel implements Serializable {
public CurrentState currentState;
public Map<String, Player> players;
public List<Totems> availableTotems;
public List<Player> 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<Player> standingPlayers) {
this.standingPlayers = standingPlayers;
}
public int getPositionByUsername(String username) {
@@ -18,5 +18,6 @@ public enum EventType {
DISCONNECTED_PLAYER,
RECONNECT_PLAYER,
NEXT_ROUND,
ENDED_GAME,
NO_OPTIONAL_CARD
}
@@ -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<Player> players;
//TODO
public EndedGame(Map<Slot, Player> slotPlayerMap, OrderLogicCard orderLogicCard, CurrentState currentState, List<Player> 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;
}
}
@@ -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();
}
}
}
@@ -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;
@@ -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();
@@ -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);
}
});
}
}
@@ -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() {
@@ -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.