Merge pull request #118 from rubenpirreram/GUI-2.0

G UI 2.0- not ended
This commit is contained in:
rubenpirreram
2026-05-25 15:01:38 +02:00
committed by GitHub
32 changed files with 478 additions and 537 deletions
+1
View File
@@ -4,6 +4,7 @@
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.lang.foreign.Arena,ofAuto,java.lang.foreign.Arena,global,java.util.concurrent.Executors,newSingleThreadExecutor" />
</inspection_tool>
<inspection_tool class="CssInvalidPseudoSelector" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="MissingJavadoc" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
+2
View File
@@ -104,6 +104,7 @@
<transformer>
<mainClass>it.polimi.ingsw.gc14.ClientLauncherGUI</mainClass>
</transformer>
<transformer />
</transformers>
<filters>
<filter>
@@ -112,6 +113,7 @@
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>META-INF/versions/9/module-info.class</exclude>
</excludes>
</filter>
</filters>
+2
View File
@@ -158,6 +158,7 @@
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>it.polimi.ingsw.gc14.ClientLauncherGUI</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
<filters>
<filter>
@@ -166,6 +167,7 @@
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>META-INF/versions/9/module-info.class</exclude>
</excludes>
</filter>
</filters>
@@ -15,7 +15,7 @@ public class ClientLauncherGUI {
public static class GUIApp extends Application {
@Override
public void start(Stage stage) throws Exception {
GUI view = new GUI(stage);
GUI view = new GUI();
ClientController controller = new ClientController(view);
view.setController(controller);
view.start(stage);
@@ -38,7 +38,6 @@ public class ClientController {
public ClientController(IView view) {
this.view = view;
this.client = null;
this.miniModel = new MiniModel();
}
/**
@@ -1,46 +1,69 @@
package it.polimi.ingsw.gc14.Model.GamePackage;
/**
/**
* Represents the possible stages of a game.
*/
public enum GameStages {
/**
* Stage in which the game is waiting for players to join.
*/
WAITING,
WAITING("Waiting"),
/**
* Stage in which players choose their totems.
*/
TOTEM_CHOICE,
TOTEM_CHOICE("Totem"),
/**
* Stage in which players select their action slots.
*/
SLOT_CHOICE,
SLOT_CHOICE("Slot"),
/**
* Stage in which the mandatory actions associated with the chosen slots are resolved.
*/
RES_ACTIONS,
RES_ACTIONS("Actions"),
/**
* Stage in which an optional card effect can be resolved.
*/
OPT_CARD_E,
OPT_CARD_E("Card Effect"),
/**
* Stage in which an event card is being resolved.
*/
RES_EVENT,
RES_EVENT("Event"),
/**
* Stage in which end-of-round or end-of-game operations are processed.
*/
ENDING,
ENDING("Ending"),
/**
* Stage indicating that the game has ended.
*/
ENDED
}
ENDED("Ended");
/** The human-readable name of this stage, used in {@link #toString()}. */
private final String displayName;
/**
* Constructs a {@code GameStages} value with the given display name.
*
* @param displayName the human-readable label for this stage
*/
GameStages(String displayName) {
this.displayName = displayName;
}
/**
* Returns the human-readable name of this stage.
*
* @return the display name (e.g. {@code "Slot"} for {@code SLOT_CHOICE})
*/
@Override
public String toString() {
return displayName;
}
}
@@ -46,12 +46,14 @@ public class AddPlayer extends NetworkEvent implements Serializable {
//TODO
@Override
public boolean apply(MiniModel miniModel){
if(isError)
return false;
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
synchronized (miniModel) {
if (isError)
return false;
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
}
}
}
@@ -59,15 +59,17 @@ public class ApplyNextRound extends NetworkEvent implements Serializable{
}
public boolean apply(MiniModel miniModel)
{
miniModel.setSlotPlayerMap(slotPlayerMap);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setPlayers(players);
miniModel.upperListTribeCards=upperListTribeCards;
miniModel.lowerListTribeCards=lowerListTribeCards;
miniModel.upperListBuildingCards=upperListBuildingCards;
miniModel.lowerListBuildingCards=lowerListBuildingCards;
return true;
synchronized (miniModel) {
miniModel.setSlotPlayerMap(slotPlayerMap);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setPlayers(players);
miniModel.upperListTribeCards = upperListTribeCards;
miniModel.lowerListTribeCards = lowerListTribeCards;
miniModel.upperListBuildingCards = upperListBuildingCards;
miniModel.lowerListBuildingCards = lowerListBuildingCards;
return true;
}
}
}
@@ -33,16 +33,17 @@ public class DisconnectedPlayer extends NetworkEvent implements Serializable{
//TODO
@Override
public boolean apply(MiniModel miniModel){
if(isError)
return false;
if(miniModel!=null)
{
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
synchronized (miniModel) {
if (isError)
return false;
if (miniModel != null) {
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
}
return true;
}
return true;
}
}
@@ -39,16 +39,17 @@ public class DrawLowerBuildingCard extends NetworkEvent implements Serializable
//TODO
@Override
public boolean apply(MiniModel miniModel){
if(isError)
return false;
miniModel.lowerListBuildingCards.remove(pos);
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
synchronized (miniModel) {
if (isError)
return false;
miniModel.lowerListBuildingCards.remove(pos);
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
}
}
}
@@ -38,16 +38,17 @@ public class DrawLowerTribeCard extends NetworkEvent implements Serializable{
//TODO
@Override
public boolean apply(MiniModel miniModel){
if(isError)
return false;
miniModel.lowerListTribeCards.remove(pos);
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
synchronized (miniModel) {
if (isError)
return false;
miniModel.lowerListTribeCards.remove(pos);
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
}
}
}
@@ -39,15 +39,16 @@ public class DrawUpperBuildingCard extends NetworkEvent implements Serializable
//TODO
@Override
public boolean apply(MiniModel miniModel){
if(isError)
return false;
miniModel.upperListBuildingCards.remove(pos);
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
synchronized (miniModel) {
if (isError)
return false;
miniModel.upperListBuildingCards.remove(pos);
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
}
}
}
@@ -38,15 +38,16 @@ public class DrawUpperTribeCard extends NetworkEvent implements Serializable{
//TODO
@Override
public boolean apply(MiniModel miniModel){
if(isError)
return false;
miniModel.upperListTribeCards.remove(pos);
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
synchronized (miniModel) {
if (isError)
return false;
miniModel.upperListTribeCards.remove(pos);
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
}
}
@@ -48,12 +48,14 @@ public class EndedGame extends NetworkEvent implements Serializable{
}
public boolean apply(MiniModel miniModel)
{
miniModel.setSlotPlayerMap(slotPlayerMap);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setPlayers(players);
miniModel.setStandingPlayers(players);
return true;
synchronized (miniModel) {
miniModel.setSlotPlayerMap(slotPlayerMap);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setPlayers(players);
miniModel.setStandingPlayers(players);
return true;
}
}
}
@@ -45,16 +45,18 @@ public class ReconnectPlayer extends NetworkEvent implements Serializable {
*/
@Override
public boolean apply(MiniModel miniModel) {
if (isError)
return false;
synchronized (miniModel) {
if (isError)
return false;
if (miniModel != null) {
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
if (miniModel != null) {
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
}
return true;
}
return true;
}
}
@@ -33,14 +33,15 @@ public class SkipTurn extends NetworkEvent implements Serializable{
//TODO
@Override
public boolean apply(MiniModel miniModel){
if(isError)
return false;
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
synchronized (miniModel) {
if (isError)
return false;
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
}
}
}
@@ -39,14 +39,15 @@ public class SlotChoice extends NetworkEvent implements Serializable {
//TODO
@Override
public boolean apply(MiniModel miniModel){
if(isError)
return false;
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
synchronized (miniModel) {
if (isError)
return false;
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
return true;
}
}
}
@@ -69,14 +69,16 @@ public class TotemChoice extends NetworkEvent implements Serializable {
*/
@Override
public boolean apply(MiniModel miniModel) {
if (isError)
return false;
synchronized (miniModel) {
if (isError)
return false;
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
miniModel.setAvailableTotems(availableTotems);
return true;
miniModel.setPlayers(playerList);
miniModel.setOrderLogicCard(orderLogicCard);
miniModel.setCurrentState(currentState);
miniModel.setSlotPlayerMap(slotPlayerMap);
miniModel.setAvailableTotems(availableTotems);
return true;
}
}
}
@@ -5,6 +5,7 @@ import it.polimi.ingsw.gc14.Model.Game;
import it.polimi.ingsw.gc14.Model.MiniModel;
import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback;
import javafx.application.Platform;
import java.io.Serializable;
import java.rmi.RemoteException;
@@ -53,12 +54,12 @@ 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 {
clientController.view.applyAndRender(event);
}
if(event.getIsError()) {
clientController.view.showError(event.toString());
} else {
event.apply(clientController.miniModel);
clientController.view.render();
}
}
}
@@ -30,7 +30,7 @@ import java.rmi.*;
*/
public class RMIServer extends UnicastRemoteObject implements IGameServer {
private String host;
private GameController controller;
private final GameController controller;
private Registry registry;
private int nPort;
@@ -105,23 +105,13 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
System.out.println("(After crash)Reconnected player: " + username);
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
{
if (playerList.isEmpty()) {
controller.setModel(new Game(preferredInt));
playerList.setLimit(preferredInt);
System.out.println("Game Created With :"+preferredInt+" Players");
}
if (controller.addPlayer(username)) {
clients.put(username, callback);
@@ -130,18 +120,17 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
System.out.println("Accepted player: " + username);
return true;
}
// Reconnection: player was offline
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;
}
}
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;
}
return false;
}
@@ -6,6 +6,7 @@ import it.polimi.ingsw.gc14.Model.MiniModel;
import it.polimi.ingsw.gc14.Network.IClient;
import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.Network.NetworkEvents.*;
import javafx.application.Platform;
import java.io.*;
import java.net.*;
@@ -163,14 +164,13 @@ public class TCPClient implements IClient {
if (event.getIsError()) {
controller.view.showError(event.toString());
} else {
controller.view.applyAndRender(event);
event.apply(controller.miniModel);
controller.view.render();
}
} else if (read instanceof MiniModel model) {
synchronized (controller) {
controller.setModel(model);
controller.view.render();
}
controller.setModel(model);
controller.view.render();
}
} catch (ClassNotFoundException e) {
@@ -179,12 +179,11 @@ public class TCPServer {
synchronized (controller) {
String username = eventAddPlayer.getUsername();
//reconnect players after a server crash
if (serverCrashed) {
if (controller.getModel().getPlayers().stream()
.anyMatch(p -> p.getUserName().equals(username))
&& !playerList.containsKey(username)) {
playerList.put(username, true);
System.out.println("(After crash)Reconnected player: " + username);
@@ -206,54 +205,18 @@ public class TCPServer {
clientHandlers.add(handler);
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()) {
Game model = new Game(eventAddPlayer.getProposedNPlayer());
controller.setModel(model);
playerList.setLimit(eventAddPlayer.getProposedNPlayer());
System.out.println("Game Created With :"+eventAddPlayer.getProposedNPlayer()+" Players");
}
if (controller.addPlayer(username)) {
@@ -278,52 +241,55 @@ public class TCPServer {
clientHandlers.add(handler);
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.");
}
}
//reconnect a previously disconnected player
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.");
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
@@ -52,7 +52,7 @@ public class ServerLauncher {
BlockingQueue<NetworkEvent> actionQueue;
/** Game controller. Used to apply events */
GameController gameController;
final GameController gameController;
/** Server RMI. Handles RMI clients */
RMIServer serverRMI;
@@ -106,8 +106,10 @@ public class ServerLauncher {
*/
public boolean doFirstEvent() throws InterruptedException {
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)
{
event.setIsError(true);
@@ -115,16 +117,24 @@ public class ServerLauncher {
serverTCP.notifyAll(event);
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()) {
disconnectionTimer.cancel(false);
disconnectionTimer = null;
}
int roundPrev=gameController.getModel().getCurrentState().getRound();
synchronized(gameController){
//applies the event and set if is an error
event.setIsError(!event.apply(gameController));
Game game=gameController.getModel();
//if the event wasn't an error , it will be sent to players
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))
{
playerList.remove(event.getUsername());
@@ -132,11 +142,43 @@ public class ServerLauncher {
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().equals(GameStages.WAITING)) {
} else if (event.getEventType().equals(EventType.DISCONNECTED_PLAYER) && game.getCurrentState().getGameStage().equals(GameStages.WAITING)) {
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()){
System.out.println("\n!!! Couldn't delete save !!!\n");
}
@@ -147,48 +189,26 @@ public class ServerLauncher {
serverRMI.setServerCrashed(false);
serverTCP.setServerCrashed(false);
}
else if(!this.gameSave() ){
System.out.println("\n!!! Save failed !!!\n");
//notify the event
else {
serverRMI.notifyAll(event);
serverTCP.notifyAll(event);
}
}
serverRMI.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();
}
}
else{
// removes disconneted players when the game is ended
if(event.getEventType().equals(EventType.DISCONNECTED_PLAYER))
{
playerList.remove(event.getUsername());
if(playerList.isEmpty())
{
gameController.setModel(null);
System.out.println("\n!!! Player list is now empty, ready for a new game init !!!\n");
}
return true;
}
return false;
}
@@ -253,12 +273,12 @@ public class ServerLauncher {
MiniModel miniModel;
synchronized (gameController) {
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);
serverTCP.notifyAll(miniModel);
view = new TUI(miniModel);
view.fullRender();
view.render();
}).start();
});
new Thread(()-> {
@@ -290,10 +310,10 @@ public class ServerLauncher {
while (true) {
try{
this.doFirstEvent();
if(view!=null)
{
view.fullRender();
}
// if(view!=null)
// {
// view.fullRender();
// }
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
@@ -45,12 +45,10 @@ public class GUI extends Application implements IView {
private ClientController controller;
public GUI(Stage stage) {
this.primaryStage = stage;
}
@Override
public void start(Stage stage) throws Exception {
this.primaryStage = stage;
loaderLogin = new FXMLLoader(getClass().getResource("/GUIScene/login.fxml"));
loginScene = new Scene(loaderLogin.load());
controllerLogin = loaderLogin.getController();
@@ -73,7 +71,7 @@ public class GUI extends Application implements IView {
loaderLeaderboard = new FXMLLoader(getClass().getResource("/GUIScene/standing.fxml"));
leaderboardScene = new Scene(loaderLeaderboard.load());
controllerLeaderboard = loaderLeaderboard.getController();
controllerLeaderboard.setController(controller);
controllerLeaderboard.setController(controller,primaryStage,loginScene);
mainScene = new Scene(loaderMain.load());
controllerMain = loaderMain.getController();
@@ -81,10 +79,7 @@ public class GUI extends Application implements IView {
showLogin();
stage.setTitle("Mesos");
primaryStage.setMaximized(true);
primaryStage.setMinWidth(1583);
primaryStage.setMinHeight(734);
primaryStage.setTitle("Mesos");
primaryStage.setOnCloseRequest(e -> {
Platform.exit();
System.exit(0);
@@ -106,48 +101,29 @@ public class GUI extends Application implements IView {
this.controller=controller;
}
public void applyAndRender(NetworkEvent event) {
public void render() {
Platform.runLater(() -> {
event.apply(miniModel);
if (controller.miniModel.currentState.getGameStage() == TOTEM_CHOICE) {
primaryStage.setScene(totemScene);
controllerTotem.render();
} else if (controller.miniModel.currentState.getGameStage() == GameStages.ENDED) {
boolean sceneChange = primaryStage.getScene() != leaderboardScene;
primaryStage.setScene(leaderboardScene);
if (sceneChange) {
primaryStage.setMaximized(false);
Platform.runLater(() -> primaryStage.setMaximized(true));
synchronized (miniModel) {
if (controller.miniModel.currentState.getGameStage() == TOTEM_CHOICE) {
primaryStage.setScene(totemScene);
controllerTotem.render();
} else if (controller.miniModel.currentState.getGameStage() == ENDED) {
primaryStage.setScene(leaderboardScene);
controllerLeaderboard.render();
} else {
double w = primaryStage.getWidth();
double h = primaryStage.getHeight();
primaryStage.setScene(mainScene);
primaryStage.setWidth(w);
primaryStage.setHeight(h);
primaryStage.setMinHeight(h);
primaryStage.setMinWidth(w);
primaryStage.setResizable(false);
controllerMain.render();
}
controllerLeaderboard.render();
} else {
boolean sceneChange = primaryStage.getScene() != mainScene; // era un'altra scena?
primaryStage.setScene(mainScene);
if (sceneChange) {
primaryStage.setMaximized(false);
Platform.runLater(() -> primaryStage.setMaximized(true));
}
controllerMain.render(event);
}
});
}
public void render() {
if (!Platform.isFxApplicationThread()) {
Platform.runLater(this::render);
return;
}
if (controller.miniModel.currentState.getGameStage() == TOTEM_CHOICE) {
primaryStage.setScene(totemScene);
controllerTotem.render();
} else if (controller.miniModel.currentState.getGameStage() == ENDED){
primaryStage.setScene(leaderboardScene);
controllerLeaderboard.render();
}else {
primaryStage.setScene(mainScene);
controllerMain.render();
}
}
@Override
public void showMessage(String message) {
@@ -156,7 +132,12 @@ public class GUI extends Application implements IView {
@Override
public void showError(String message) {
Platform.runLater(() -> {
synchronized (miniModel) {
controllerMain.isError = true;
controllerMain.render();
}
});
}
}
@@ -6,6 +6,7 @@ import javafx.animation.ScaleTransition;
import it.polimi.ingsw.gc14.Model.PlayableCard;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.stage.Popup;
import javafx.geometry.Insets;
@@ -23,6 +24,7 @@ import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.paint.CycleMethod;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.util.Duration;
@@ -42,6 +44,8 @@ public class LeaderboardFXMLController {
// Cache condivisa con MainFXMLController
private static final Map<String, Image> imageCache = new HashMap<>();
private Scene loginScene;
private Stage primaryStage;
private Image loadImage(String path) {
return imageCache.computeIfAbsent(path,
@@ -49,8 +53,10 @@ public class LeaderboardFXMLController {
}
public void setController(ClientController controller) {
public void setController(ClientController controller, Stage primaryStage, Scene loginScene) {
this.controller = controller;
this.loginScene=loginScene;
this.primaryStage=primaryStage;
}
@@ -356,6 +362,6 @@ public class LeaderboardFXMLController {
// ==== ACTIONS ====
@FXML
private void onNewGame() {
//controller.requestNewGame();
primaryStage.setScene(loginScene);
}
}
@@ -7,9 +7,8 @@ import it.polimi.ingsw.gc14.Model.Cards.TribeCard;
import it.polimi.ingsw.gc14.Model.Orders.OrderPlayer;
import it.polimi.ingsw.gc14.Network.EventType;
import it.polimi.ingsw.gc14.Network.NetworkEvent;
import javafx.animation.AnimationTimer;
import javafx.animation.PauseTransition;
import javafx.animation.ScaleTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
@@ -18,8 +17,11 @@ import javafx.fxml.FXML;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.effect.ColorAdjust;
@@ -31,7 +33,7 @@ import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.text.Font;
import javafx.stage.Popup;
import javafx.stage.Stage;
import javafx.stage.Screen;
import javafx.stage.Window;
import javafx.util.Duration;
@@ -39,22 +41,24 @@ import java.util.*;
public class MainFXMLController {
@FXML private ScrollPane playerSide;
@FXML private HBox mainHBox;
@FXML private ImageView backgroundImage;
@FXML private HBox board;
@FXML private HBox upperList;
@FXML private HBox lowerList;
@FXML private HBox myHand;
@FXML private VBox sidePanel;
@FXML private HBox info;
@FXML private Label era;
@FXML private Label round;
@FXML private Label player;
@FXML private Button skipBtn;
@FXML private Button detailsBtn;
@FXML private Label infoText;
private Popup popup;
private HBox popupCards;
private ClientController controller;
public boolean isError;
// ==== IMAGE CACHE ====
private static final Map<String, Image> imageCache = new HashMap<>();
@@ -63,43 +67,41 @@ public class MainFXMLController {
p -> new Image(getClass().getResourceAsStream(p)));
}
public void setController(ClientController controller) {
this.controller = controller;
}
@FXML
public void initialize() {
Font.loadFont(getClass().getResourceAsStream("/Fonts/InknutAntiqua-Regular.ttf"), 14);
popup = new Popup();
mainHBox.sceneProperty().addListener((obs, oldScene, newScene) -> {
if (newScene != null) {
newScene.getRoot().applyCss();
newScene.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
if (popup.isShowing()) popup.hide();
});
newScene.getRoot().applyCss();
newScene.windowProperty().addListener((o2, ow, nw) -> {
if (nw != null) {
nw.focusedProperty().addListener((o3, wf, nf) -> {
if (!nf) popup.hide();
});
}
});
}
});
mainHBox.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
@Override
public void changed(ObservableValue<? extends Bounds> obs, Bounds ov, Bounds nv) {
if (nv.getWidth() > 0 && nv.getHeight() > 0 && controller != null) {
mainHBox.layoutBoundsProperty().removeListener(this);
render();
}
else {
popup.hide();
}
});
initPopup();
renderBackground();
isError=false;
}
// ==== RENDER ====
public void render() {
if (mainHBox.getWidth() == 0 || mainHBox.getHeight() == 0) {
Platform.runLater(() -> render());
return;
}
renderUpper();
renderBoard();
renderLower();
@@ -107,37 +109,15 @@ public class MainFXMLController {
renderSidePanel();
}
public void render(NetworkEvent event) {
if (mainHBox.getWidth() == 0 || mainHBox.getHeight() == 0) {
Platform.runLater(() -> render(event));
return;
}
if (event.getEventType() == EventType.SLOT_CHOICE) {
renderBoard();
renderSidePanel();
} else {
renderUpper();
renderBoard();
renderLower();
renderSidePanel();
if (Objects.equals(event.getUsername(), controller.myUsername)
|| event.getEventType() == EventType.NEXT_ROUND) {
renderMyHand();
}
}
}
// ==== EFFECTS ====
private void addClip(ImageView img) {
Rectangle clip = new Rectangle();
clip.setArcWidth(20);
clip.setArcHeight(20);
clip.heightProperty().bind(img.fitHeightProperty());
clip.widthProperty().bind(img.fitHeightProperty().multiply(
img.getImage().getWidth() / img.getImage().getHeight()
));
img.setClip(clip);
clip.heightProperty().bind(img.layoutBoundsProperty().map(b -> b.getHeight()));
clip.widthProperty().bind(img.layoutBoundsProperty().map(b -> b.getWidth()));
}
private void addHoverZoom(Node node) {
@@ -176,7 +156,7 @@ public class MainFXMLController {
// ==== ELEMENTS ====
private StackPane createOrder(String num) {
ImageView img = new ImageView(loadImage("/GUIImages/Orders/order-" + num + ".png"));
img.fitHeightProperty().bind(board.heightProperty().add(-15));
img.fitHeightProperty().bind(board.heightProperty().multiply(0.94));
img.setPreserveRatio(true);
addClip(img);
return new StackPane(img);
@@ -185,7 +165,7 @@ public class MainFXMLController {
private StackPane createSlot(Slot slot, boolean withZoom, boolean withShadow) {
ImageView img = new ImageView(loadImage("/GUIImages/Fronts/card-" + slot.getSlotId() + ".png"));
img.setPreserveRatio(true);
img.fitHeightProperty().bind(board.heightProperty().add(-15));
img.fitHeightProperty().bind(board.heightProperty().multiply(0.94)); // TODO perchè è tutto moltiplicato per una costante ma in board facciamo -15?
addClip(img);
StackPane wrapper = new StackPane(img);
@@ -195,10 +175,7 @@ public class MainFXMLController {
totem.fitHeightProperty().bind(img.fitHeightProperty().multiply(0.332));
totem.setPreserveRatio(true);
StackPane.setAlignment(totem, Pos.TOP_LEFT);
StackPane.setMargin(totem, new Insets(0, 0, 0, 0.224 * img.getFitHeight()));
img.fitHeightProperty().addListener((obs, ov, nv) -> {
StackPane.setMargin(totem, new Insets(0, 0, 0, 0.224 * nv.doubleValue()));
});
StackPane.setMargin(totem, new Insets(0, 0, 0, 0.224 * img.getFitHeight())); // TODO perchè margine sx incrementa con altezza e non larghezza?
wrapper.getChildren().add(totem);
}
@@ -210,7 +187,7 @@ public class MainFXMLController {
private StackPane createCard(PlayableCard card, boolean withZoom, boolean withShadow, Region parent) {
ImageView img = new ImageView(loadImage("/GUIImages/Fronts/card-" + card.getIdIMG() + ".png"));
img.setPreserveRatio(true);
img.fitHeightProperty().bind(parent.heightProperty().multiply(0.85));
img.fitHeightProperty().bind(parent.heightProperty().multiply(0.90));
addClip(img);
StackPane wrapper = new StackPane(img);
if (withShadow) addShadow(wrapper);
@@ -218,54 +195,6 @@ public class MainFXMLController {
return wrapper;
}
private void renderIcons(HBox iconsRow1, HBox iconsRow2, Player player) {
String[][] iconTypes = {
{"Artist", "artists"},
{"Gatherer", "gatherers"},
{"Inventor", "inventors"},
{"Builder", "builders"},
{"Shaman", "shamans"},
{"Hunter", "hunters"}
};
for (int i = 0; i < iconTypes.length; i++) {
String iconName = iconTypes[i][0];
String fieldName = iconTypes[i][1];
ImageView icon = new ImageView();
icon.setFitWidth(28);
icon.setFitHeight(28);
icon.setPreserveRatio(true);
icon.setImage(loadImage("/GUIImages/Icons/" + iconName + ".png"));
ArrayList<PlayableCard> cards = getPlayerCards(player.getUserName(), fieldName);
if (cards.isEmpty()) {
ColorAdjust grayscale = new ColorAdjust();
icon.setEffect(grayscale);
icon.setOpacity(0.3);
} else {
icon.setOnMouseClicked(e -> openPopup(new ArrayList<>(cards)));
addHoverZoom(icon);
}
if (i < 3) iconsRow1.getChildren().add(icon);
else iconsRow2.getChildren().add(icon);
}
}
private ArrayList<PlayableCard> getPlayerCards(String username, String type) {
Player p = controller.miniModel.players.get(username);
return switch (type) {
case "artists" -> new ArrayList<>(p.artists);
case "gatherers" -> new ArrayList<>(p.gatherers);
case "inventors" -> new ArrayList<>(p.inventors);
case "builders" -> new ArrayList<>(p.builders);
case "shamans" -> new ArrayList<>(p.shamans);
case "hunters" -> new ArrayList<>(p.hunters);
case "building" -> new ArrayList<>(p.buildingCards);
default -> new ArrayList<>();
};
}
// ==== GROUPS ====
@@ -331,9 +260,9 @@ public class MainFXMLController {
}
}
private void drawMyHandList(ArrayList<? extends PlayableCard> cardList, HBox parent) {
private void drawMyHandList(ArrayList<? extends PlayableCard> cardList) {
if (!cardList.isEmpty()) {
StackPane img = createCard(cardList.getLast(), true, true, parent);
StackPane img = createCard(cardList.getLast(), true, true, myHand);
Label label = new Label(String.valueOf(cardList.size()));
label.setTranslateY(-55);
label.setTranslateX(10);
@@ -341,23 +270,30 @@ public class MainFXMLController {
StackPane.setAlignment(label, Pos.TOP_RIGHT);
img.getChildren().add(label);
img.setOnMouseClicked(e -> openPopup(new ArrayList<>(cardList)));
parent.getChildren().add(img);
myHand.getChildren().add(img);
} else {
Region placeholder = new Region();
placeholder.prefHeightProperty().bind(parent.heightProperty().multiply(0.85));
placeholder.prefHeightProperty().bind(myHand.heightProperty().multiply(0.90));
placeholder.prefWidthProperty().bind(placeholder.prefHeightProperty().multiply(0.675));
placeholder.setStyle("-fx-background-color: transparent;");
parent.getChildren().add(placeholder);
myHand.getChildren().add(placeholder);
}
}
private void renderPlayer(Player player,VBox target) {
VBox card = new VBox(3);
VBox.setMargin(card, new Insets(15,15,15,15));
VBox.setMargin(card, new Insets(8,15,8,15));
card.getStyleClass().add("player-card");
card.setPadding(new Insets(8));
addHoverZoom(card);
addShadow(card);
card.setPadding(new Insets(4));
if(player.getUserName().equals(controller.miniModel.currentState.getCurrentPlayer().getUserName())) {
ScaleTransition scaleUp = new ScaleTransition(Duration.millis(150), card);
scaleUp.setToX(1.1);
scaleUp.setToY(1.1);
scaleUp.play();
}
// Riga 1: totem + nome
HBox headerRow = new HBox(8);
@@ -369,6 +305,17 @@ public class MainFXMLController {
usernameLabel.getStyleClass().add("label-medium");
if (player.getUserName().equals(controller.myUsername)) {
usernameLabel.setStyle("-fx-text-fill: #9d0208");
if(isError) {
TranslateTransition tt = new TranslateTransition(Duration.millis(50), card);
tt.setFromX(0);
tt.setByX(10);
tt.setCycleCount(6);
tt.setAutoReverse(true);
tt.play();
isError=false;
}
}
headerRow.getChildren().addAll(totem, usernameLabel);
@@ -425,6 +372,55 @@ public class MainFXMLController {
target.getChildren().add(card);
}
private void renderIcons(HBox iconsRow1, HBox iconsRow2, Player player) {
String[][] iconTypes = {
{"Artist", "artists"},
{"Gatherer", "gatherers"},
{"Inventor", "inventors"},
{"Builder", "builders"},
{"Shaman", "shamans"},
{"Hunter", "hunters"}
};
for (int i = 0; i < iconTypes.length; i++) {
String iconName = iconTypes[i][0];
String fieldName = iconTypes[i][1];
ImageView icon = new ImageView();
icon.setFitWidth(28);
icon.setFitHeight(28);
icon.setPreserveRatio(true);
icon.setImage(loadImage("/GUIImages/Icons/" + iconName + ".png"));
ArrayList<PlayableCard> cards = getPlayerCards(player.getUserName(), fieldName);
if (cards.isEmpty()) {
ColorAdjust grayscale = new ColorAdjust();
icon.setEffect(grayscale);
icon.setOpacity(0.3);
} else {
icon.setOnMouseClicked(e -> openPopup(new ArrayList<>(cards)));
addHoverZoom(icon);
}
if (i < 3) iconsRow1.getChildren().add(icon);
else iconsRow2.getChildren().add(icon);
}
}
private ArrayList<PlayableCard> getPlayerCards(String username, String type) {
Player p = controller.miniModel.players.get(username);
return switch (type) {
case "artists" -> new ArrayList<>(p.artists);
case "gatherers" -> new ArrayList<>(p.gatherers);
case "inventors" -> new ArrayList<>(p.inventors);
case "builders" -> new ArrayList<>(p.builders);
case "shamans" -> new ArrayList<>(p.shamans);
case "hunters" -> new ArrayList<>(p.hunters);
case "building" -> new ArrayList<>(p.buildingCards);
default -> new ArrayList<>();
};
}
// ==== ABSOLUTES ====
private void renderBackground() {
@@ -458,7 +454,7 @@ public class MainFXMLController {
default -> "/GUIImages/Backs/back-001.png";
};
ImageView back = new ImageView(loadImage(path));
back.fitHeightProperty().bind(board.heightProperty().add(-15));
back.fitHeightProperty().bind(board.heightProperty().multiply(0.94));
back.setPreserveRatio(true);
addClip(back);
addShadow(back);
@@ -476,7 +472,6 @@ public class MainFXMLController {
4, new double[]{0.142, 0.316, 0.503, 0.690},
5, new double[]{0.066, 0.251, 0.433, 0.617, 0.802}
);
double[] positions = slotPositions.get(numPlayers);
if (positions == null) return;
@@ -523,17 +518,6 @@ public class MainFXMLController {
card.getChildren().add(overlay);
board.getChildren().add(card);
}
private Color totemColor(Totems totem) {
return switch (totem) {
case ORANGE -> Color.rgb(223, 76, 17);
case BLUE -> Color.rgb(42, 155, 179);
case PURPLE -> Color.rgb(65, 20, 42);
case YELLOW -> Color.rgb(248, 201, 57);
case WHITE -> Color.rgb(232, 232, 231);
// aggiungi i tuoi valori reali
default -> Color.GRAY;
};
}
private void renderSlotMap() {
int i = 0;
@@ -553,61 +537,33 @@ public class MainFXMLController {
myHand.setAlignment(Pos.CENTER);
Player me = controller.miniModel.players.get(controller.myUsername);
drawMyHandList(me.artists,myHand);
drawMyHandList(me.gatherers,myHand);
drawMyHandList(me.inventors,myHand);
drawMyHandList(me.builders,myHand);
drawMyHandList(me.shamans,myHand);
drawMyHandList(me.hunters,myHand);
drawMyHandList(me.buildingCards,myHand);
drawMyHandList(me.artists);
drawMyHandList(me.gatherers);
drawMyHandList(me.inventors);
drawMyHandList(me.builders);
drawMyHandList(me.shamans);
drawMyHandList(me.hunters);
drawMyHandList(me.buildingCards);
}
private void renderSidePanel() {
sidePanel.getChildren().clear();
sidePanel.setSpacing(6);
era.setText(Integer.toString(controller.miniModel.currentState.getEra()));
round.setText(Integer.toString(controller.miniModel.currentState.getRound()));
player.setText(controller.miniModel.currentState.getCurrentPlayer().getUserName());
VBox.setMargin(info, new Insets(5, 5, 5, 5));
sidePanel.getChildren().add(info);
HBox buttonRow = new HBox(8);
buttonRow.setAlignment(Pos.CENTER);
VBox.setMargin(buttonRow, new Insets(0, 5, 5, 5));
javafx.scene.control.Button skipBtn = new javafx.scene.control.Button("Skip Turn");
skipBtn.getStyleClass().add("action-button");
infoText.setText("Round: "+Integer.toString(controller.miniModel.currentState.getRound()) + "" + controller.miniModel.currentState.getGameStage().toString());
skipBtn.setOnAction(e -> controller.skipTurn(controller.myUsername));
addHoverZoom(skipBtn);
javafx.scene.control.Button detailsBtn = new javafx.scene.control.Button("Ending Details");
detailsBtn.getStyleClass().add("action-button");
detailsBtn.setOnAction(e -> openDetailsPopup());
addHoverZoom(skipBtn);
addHoverZoom(detailsBtn);
buttonRow.getChildren().addAll(skipBtn, detailsBtn);
sidePanel.getChildren().add(buttonRow);
// VBox separato solo per i player
VBox playerList = new VBox(6);
VBox playerList = new VBox();
playerList.setFillWidth(true);
for (Player p : controller.miniModel.players.values()) {
renderPlayer(p, playerList); // passa playerList invece di sidePanel
renderPlayer(p, playerList);
}
ScrollPane scrollPane = new ScrollPane(playerList);
scrollPane.setFitToWidth(true);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
scrollPane.setStyle("-fx-background: transparent; -fx-background-color: transparent;");
VBox.setVgrow(scrollPane, Priority.ALWAYS);
sidePanel.getChildren().add(scrollPane);
playerSide.setContent(playerList);
}
// ==== POPUP ====
private void initPopup() {
public void initPopup() {
popupCards = new HBox(10);
popupCards.setAlignment(Pos.CENTER);
popupCards.setPadding(new Insets(10));
@@ -619,10 +575,8 @@ public class MainFXMLController {
"-fx-background-radius: 10;"
);
popup = new Popup();
popup.getContent().add(popupCards);
popup.setAutoHide(false); // gestito manualmente per permettere click sulle carte
popup.setAutoHide(false);
popup.addEventHandler(Event.ANY, e -> {
if (popup.getScene() != null) {
popup.getScene().setFill(Color.TRANSPARENT);
@@ -676,6 +630,7 @@ public class MainFXMLController {
}
showPopup();
}
private void openDetailsPopup() {
popupCards.getChildren().clear();
ImageView img = new ImageView(loadImage("/GUIImages/Backs/back-118.png"));
@@ -7,7 +7,6 @@ import it.polimi.ingsw.gc14.Network.NetworkEvent;
public interface IView {
public void setModel(MiniModel miniModel);
public void render();
public void applyAndRender(NetworkEvent event);
public void showMessage(String message);
public void showError(String message);
@@ -59,10 +59,6 @@ public class TUI implements IView {
this.model = model;
this.username = "";
}
public void applyAndRender(NetworkEvent event) {
event.apply(model);
render();
}
/**
* Sets the username of the local player.
-1
View File
@@ -6,7 +6,6 @@
<StackPane xmlns="http://javafx.com/javafx/21"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="it.polimi.ingsw.gc14.View.GUI.LoginFXMLController"
prefWidth="1280" prefHeight="720"
style="-fx-background-color: #09060300;"
stylesheets="@styles.css">
+27 -35
View File
@@ -4,15 +4,16 @@
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.Pane?>
<HBox fx:id="mainHBox"
maxHeight="Infinity" maxWidth="Infinity"
prefHeight="1080.0" prefWidth="1920.0"
xmlns="http://javafx.com/javafx/26"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="it.polimi.ingsw.gc14.View.GUI.MainFXMLController"
stylesheets="@styles.css">
<children>
<children>
<!-- VBox sinistra: si espande per riempire tutto lo spazio disponibile -->
<VBox alignment="CENTER"
fillWidth="false"
@@ -29,7 +30,7 @@
</VBox.margin>
</HBox>
<HBox fx:id="board" prefHeight="220" minHeight="220" maxHeight="220" styleClass="card-list" VBox.vgrow="NEVER">
<HBox fx:id="board" prefHeight="280" minHeight="280" maxHeight="280" styleClass="card-list" VBox.vgrow="NEVER">
<VBox.margin>
<Insets top="5" right="5" bottom="5" left="5" />
</VBox.margin>
@@ -48,8 +49,7 @@
</HBox>
</children>
</VBox>
<!-- VBox destra: dimensione fissa, non si espande -->
<!-- VBox destra: dimensione fissa, non si espande -->
<VBox fx:id="sidePanel"
prefWidth="250.0"
maxWidth="250.0"
@@ -60,37 +60,29 @@
<Insets bottom="10" left="10" right="10" top="10" />
</HBox.margin>
<children>
<ScrollPane fitToWidth="true" hbarPolicy="NEVER" vbarPolicy="AS_NEEDED" VBox.vgrow="ALWAYS">
<content>
<VBox spacing="10">
<children>
<HBox fx:id="info" prefHeight="107.0" prefWidth="483.0" styleClass="frame">
<children>
<VBox alignment="CENTER" prefHeight="107.0" prefWidth="161.0" spacing="2">
<children>
<Label styleClass="label-medium" text="Era" />
<Label fx:id="era" styleClass="label-medium" text="VALORE" />
</children>
</VBox>
<VBox alignment="CENTER" prefHeight="107.0" prefWidth="161.0" spacing="2">
<children>
<Label styleClass="label-medium" text="Round" />
<Label fx:id="round" styleClass="label-medium" text="VALORE" />
</children>
</VBox>
<VBox alignment="CENTER" prefHeight="107.0" prefWidth="161.0" spacing="2">
<children>
<Label styleClass="label-medium" text="Player" />
<Label fx:id="player" styleClass="label-medium" text="VALORE" />
</children>
</VBox>
</children>
</HBox>
<!-- altri elementi qui sotto -->
</children>
</VBox>
</content>
<HBox fx:id="info" prefHeight="80.0" prefWidth="483.0" styleClass="frame" alignment="CENTER">
<Label fx:id="infoText" styleClass="label-medium" text="VALORE" />
</HBox>
<ScrollPane fx:id="playerSide" fitToWidth="true"
style="-fx-background: transparent; -fx-background-color: transparent;" hbarPolicy="NEVER"
vbarPolicy="AS_NEEDED" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets top="5"/>
</VBox.margin>
</ScrollPane>
<Pane HBox.hgrow="ALWAYS"/>
<HBox alignment="CENTER" fx:id="buttonRow" >
<HBox spacing="10">
<Button fx:id="skipBtn" styleClass="action-button" text="Skip Turn"/>
<Button fx:id="detailsBtn" styleClass="action-button" text="Ending Details"/>
</HBox>
<VBox.margin>
<Insets top="5" right="5" bottom="5" left="5"/>
</VBox.margin>
</HBox>
</children>
</VBox>
+2 -8
View File
@@ -43,14 +43,8 @@
}
.frame {
-fx-background-color:
#8B6914,
#FFF8DC,
#8B6914,
#FFF8DC;
-fx-background-insets: 0, 5, 10, 15;
-fx-background-radius: 15, 12, 8, 4;
-fx-padding: 15 15 15 15;
-fx-background-color: rgba(255,255,255,0.35);
-fx-background-radius: 15 15 0 0;
}
.action-button {
-1
View File
@@ -9,7 +9,6 @@
<StackPane xmlns="http://javafx.com/javafx/21"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="it.polimi.ingsw.gc14.View.GUI.TotemFXMLController"
prefWidth="1280" prefHeight="720"
style="-fx-background-color: #09060300;">
<ImageView fx:id="backgroundImage" fitWidth="1920" fitHeight="1080" preserveRatio="false">
</ImageView>