diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/game/Game.java b/Projekte/mdga/model/src/main/java/pp.mdga/game/Game.java index 23f135e9..4e09869b 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/game/Game.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/game/Game.java @@ -22,8 +22,12 @@ public class Game { private Map playerConnectionID; private ArrayList observers = new ArrayList<>(); + private Player startPlayer; private Boolean gameHasStarted = false; private Boolean playerHasDisconnected = false; + private Boolean gameIsInterrupted = false; + private Boolean allRanked = false; + private Boolean movablePieces = false; private static final int AMOUNT_OF_TURBO_CARDS = 16; private static final int AMOUNT_OF_SHIELD_AND_SWAP_CARDS = 12; @@ -297,7 +301,6 @@ public Boolean getGameHasStarted() { */ public void setGameHasStarted(Boolean gameHasStarted) { this.gameHasStarted = gameHasStarted; - if (gameHasStarted) notifyObservers(); } /** @@ -309,6 +312,44 @@ public Boolean playerHasDisconnected() { return playerHasDisconnected; } + /** + * This method sets the game interruption state. + * + * @param gameIsInterrupted the new game interruption state + */ + public void setGameIsInterrupted(Boolean gameIsInterrupted) { + this.gameIsInterrupted = gameIsInterrupted; + if (!gameIsInterrupted) notifyObservers(); + } + + /** + * This method returns whether the game is interrupted. + * + * @return true if the game is interrupted, false otherwise + */ + public Boolean gameIsInterrupted() { + return gameIsInterrupted; + } + + /** + * This method returns whether the game is interrupted. + * + * @return true if the game is interrupted, false otherwise + */ + public Boolean getMovablePieces() { + return movablePieces; + } + + /** + * This method sets the game interruption state. + * + * @param movablePieces the new game interruption state + */ + public void setMovablePieces(Boolean movablePieces) { + this.movablePieces = movablePieces; + if (!movablePieces) notifyObservers(); + } + /** * This method sets the player has disconnected. * @@ -316,9 +357,44 @@ public Boolean playerHasDisconnected() { */ public void setPlayerHasDisconnected(Boolean playerHasDisconnected) { this.playerHasDisconnected = playerHasDisconnected; - if (playerHasDisconnected) { - notifyObservers(); - } + if (playerHasDisconnected) notifyObservers(); + } + + /** + * This method returns whether all players have ranked. + * + * @return true if all players have ranked, false otherwise + */ + public Boolean allRanked() { + return allRanked; + } + + /** + * This method sets whether all players have ranked. + * + * @param allRanked the new all ranked state + */ + public void setAllRanked(Boolean allRanked) { + this.allRanked = allRanked; + if (allRanked) notifyObservers(); + } + + /** + * This method returns the start player. + * + * @return the start player + */ + public Player getStartPlayer() { + return startPlayer; + } + + /** + * This method sets the start player. + * + * @param startPlayer the new start player + */ + public void setStartPlayer(Player startPlayer) { + this.startPlayer = startPlayer; } /** diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/Animation.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/Animation.java new file mode 100644 index 00000000..74d95b65 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/Animation.java @@ -0,0 +1,16 @@ +package pp.mdga.server; + +import pp.mdga.message.client.AnimationEnd; +import pp.mdga.message.server.DiceNow; + +public class Animation extends ServerState { + public Animation(ServerState parent, ServerGameLogic logic) { + super(parent, logic); + } + + @Override + public void receivedAnimationEnd(AnimationEnd msg, int from) { + logic.send(logic.getGame().getStartPlayer(), new DiceNow()); + parent.gotoState(new Turn(parent, logic)); + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/ChoosePieceStateMachine.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/ChoosePieceStateMachine.java index 89dbefeb..2558e028 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/ChoosePieceStateMachine.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/ChoosePieceStateMachine.java @@ -6,7 +6,7 @@ public ChoosePieceStateMachine(ServerState parent, ServerGameLogic logic) { } @Override - public ServerState initialState() { - return null; + public NoPiece initialState() { + return new NoPiece(this, logic); } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/DetermineStartPlayer.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/DetermineStartPlayer.java index 6160701f..0ff4b48e 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/DetermineStartPlayer.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/DetermineStartPlayer.java @@ -1,7 +1,44 @@ package pp.mdga.server; +import pp.mdga.game.Player; +import pp.mdga.message.client.RequestDice; +import pp.mdga.message.server.*; + +import java.util.ArrayList; +import java.util.List; + public class DetermineStartPlayer extends ServerState { + private final List player = new ArrayList<>(); + public DetermineStartPlayer(ServerState parent, ServerGameLogic logic) { super(parent, logic); + logic.getGame().addObserver(this); + } + + @Override + public void receivedRequestDice(RequestDice msg, int from) { + logic.send(); + + broadcastUpdate(new Dice()); + } + + @Override + public void update() { + if (Boolean.TRUE.equals(logic.getGame().allRanked())) { + broadcastUpdate(new RankingResponce()); + if (logic.getGame().getOrder().isEmpty()) { + // todo: save the players with the same value? + broadcastUpdate(new RankingRollAgain()); + broadcastUpdate(new EndOfTurn()); + } else { + // todo: set start player + Player startPlayer = new Player(1); + logic.getGame().setStartPlayer(startPlayer); + logic.send(startPlayer, new DiceNow()); + broadcastUpdate(new EndOfTurn()); + parent.gotoState(new Animation(parent, logic)); + logic.getGame().removeObserver(this); + } + } } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/FirstRoll.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/FirstRoll.java index daa811dd..3c687bf7 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/FirstRoll.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/FirstRoll.java @@ -1,7 +1,28 @@ package pp.mdga.server; +import pp.mdga.message.client.RequestDice; + public class FirstRoll extends ServerState { public FirstRoll(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + + @Override + public void receivedRequestDice(RequestDice msg, int from) { + // todo: implement player.hasMovablePieces() +// if (player.hasMovablePieces()) { +// // todo: goto ChoosePiece +// } else { +// // todo: implement roll +// if (roll == 6) { +// // todo: send to everyone? or one player? +// logic.send(new Player(1), new Dice()); +// // todo: goto ChoosePiece +// } else { +// // todo: send to everyone? or one player? +// logic.send(new Player(1), new DiceAgain()); +// parent.gotoState(new SecondRoll(parent, logic)); +// } +// } + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/GameState.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/GameState.java index 53ee5901..dab977c8 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/GameState.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/GameState.java @@ -1,8 +1,9 @@ package pp.mdga.server; -import pp.mdga.game.Piece; import pp.mdga.message.client.*; +import pp.mdga.message.server.PauseGame; import pp.mdga.message.server.PossibleCard; +import pp.mdga.message.server.RankingResponce; public class GameState extends ServerState { private final GameStateMachine gameStateMachine = new GameStateMachine(this, logic); @@ -18,57 +19,50 @@ public void entry() { } @Override - public void receivedAnimationEnd(AnimationEnd msg) { - gameStateMachine.receivedAnimationEnd(msg); - } - - // todo piece? - @Override - public void receivedConfirmPiece(Piece piece) { - gameStateMachine.receivedConfirmPiece(piece); + public void exit() { + parent.gotoState(new Ceremony(parent, logic)); } @Override - public void receivedNoPowerCard(NoPowerCard msg) { - gameStateMachine.receivedNoPowerCard(msg); + public void receivedAnimationEnd(AnimationEnd msg, int from) { + gameStateMachine.receivedAnimationEnd(msg, from); } @Override - public void receivedPowerCardChoice(SelectCard msg) { - gameStateMachine.receivedPowerCardChoice(msg); + public void receivedNoPowerCard(NoPowerCard msg, int from) { + gameStateMachine.receivedNoPowerCard(msg, from); } @Override - public void receivedRequestDice(RequestDice msg) { - gameStateMachine.receivedRequestDice(msg); - } - - // todo msg? - @Override - public void receivedRollRankingDice() { - gameStateMachine.receivedRollRankingDice(); + public void receivedSelectCard(SelectCard msg, int from) { + gameStateMachine.receivedSelectCard(msg, from); } @Override - public void receivedSelectedPieces(SelectedPieces msg) { - gameStateMachine.receivedSelectedPieces(msg); + public void receivedRequestDice(RequestDice msg, int from) { + gameStateMachine.receivedRequestDice(msg, from); } @Override - public void sentPossibleCard(PossibleCard msg) { - gameStateMachine.sentPossibleCard(msg); + public void receivedSelectedPieces(SelectedPieces msg, int from) { + gameStateMachine.receivedSelectedPieces(msg, from); } - // todo msg?, sent to everyone? @Override - public void sentRankingResponse() { - gameStateMachine.sentRankingResponse(); + public void sentPossibleCard(PossibleCard msg, int from) { + gameStateMachine.sentPossibleCard(msg, from); + } + + @Override + public void sentRankingResponse(RankingResponce msg, int from) { + gameStateMachine.sentRankingResponse(msg, from); } @Override public void update() { - if (logic.getGame().playerHasDisconnected()) { - parent.gotoState(new Ceremony(parent, logic)); + if (Boolean.TRUE.equals(logic.getGame().playerHasDisconnected())) { + broadcastUpdate(new PauseGame()); + parent.gotoState(new Interrupt(parent, logic, this)); logic.getGame().removeObserver(this); } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/GameStateMachine.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/GameStateMachine.java index b01981de..2e14808b 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/GameStateMachine.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/GameStateMachine.java @@ -1,10 +1,24 @@ package pp.mdga.server; -public class GameStateMachine extends ServerStateMachine{ +/** + * The GameStateMachine class represents the state machine for the game state. + */ +public class GameStateMachine extends ServerStateMachine { + /** + * Constructs a new GameStateMachine with the specified parent state and game logic. + * + * @param parent the parent state + * @param logic the server game logic + */ public GameStateMachine(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + /** + * Returns the initial state of the state machine, which is DetermineStartPlayer. + * + * @return the initial state + */ @Override public DetermineStartPlayer initialState() { return new DetermineStartPlayer(this, logic); diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/Interrupt.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/Interrupt.java index 0f9e0fdc..ca59ca86 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/Interrupt.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/Interrupt.java @@ -1,7 +1,22 @@ package pp.mdga.server; +import pp.mdga.message.server.ResumeGame; + public class Interrupt extends ServerState { - public Interrupt(ServerState parent, ServerGameLogic logic) { + private final GameState lastState; + + public Interrupt(ServerState parent, ServerGameLogic logic, GameState lastState) { super(parent, logic); + this.lastState = lastState; + logic.getGame().addObserver(this); + } + + @Override + public void update() { + if (Boolean.FALSE.equals(logic.getGame().gameIsInterrupted())) { + broadcastUpdate(new ResumeGame()); + parent.gotoState(lastState); + logic.getGame().removeObserver(this); + } } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/Lobby.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/Lobby.java index b3bb2330..a612f0f2 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/Lobby.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/Lobby.java @@ -1,52 +1,74 @@ package pp.mdga.server; import pp.mdga.message.client.*; -import pp.mdga.message.server.ServerMessage; +import pp.mdga.message.server.ServerStartGame; import pp.mdga.message.server.UpdateReady; import pp.mdga.message.server.UpdateTSK; +/** + * Represents the lobby state of the server. + */ public class Lobby extends ServerState { + /** + * Constructs a new Lobby state. + * + * @param parent the parent state + * @param logic the server game logic + */ public Lobby(ServerState parent, ServerGameLogic logic) { super(parent, logic); - logic.getGame().addObserver(this); } + /** + * Handles the DeselectTSK message. + * + * @param msg the DeselectTSK message + */ @Override - public void receivedDeselectTSK(DeselectTSK msg) { + public void receivedDeselectTSK(DeselectTSK msg, int from) { broadcastUpdate(new UpdateTSK()); } + /** + * Handles the LobbyNotReady message. + * + * @param msg the LobbyNotReady message + */ @Override - public void receivedNotReady(LobbyNotReady msg) { + public void receivedNotReady(LobbyNotReady msg, int from) { broadcastUpdate(new UpdateReady()); } + /** + * Handles the LobbyReady message. + * + * @param msg the LobbyReady message + */ @Override - public void receivedReady(LobbyReady msg) { + public void receivedReady(LobbyReady msg, int from) { broadcastUpdate(new UpdateReady()); } + /** + * Handles the SelectTSK message. + * + * @param msg the SelectTSK message + */ @Override - public void receivedSelectTSK(SelectTSK msg) { + public void receivedSelectTSK(SelectTSK msg, int from) { broadcastUpdate(new UpdateTSK()); } - private void broadcastUpdate(ServerMessage updateMessage) { - for (var entry : logic.getGame().getPlayers().entrySet()) { - logic.send(entry.getValue(), updateMessage); - } - } - + /** + * Handles the ClientStartGame message. + * + * @param msg the ClientStartGame message + */ @Override - public void receivedStartGame(ClientStartGame msg) { - // todo: implement?? - } - - @Override - public void update() { - if (logic.getGame().getGameHasStarted()) { + public void receivedStartGame(ClientStartGame msg, int from) { + if (Boolean.TRUE.equals(logic.getGame().allRanked())) { + broadcastUpdate(new ServerStartGame()); parent.gotoState(new GameState(parent, logic)); - logic.getGame().removeObserver(this); } } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/NoPiece.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/NoPiece.java index 9b2cbb48..6326bfb1 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/NoPiece.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/NoPiece.java @@ -1,7 +1,55 @@ package pp.mdga.server; +import pp.mdga.game.Player; +import pp.mdga.message.server.WaitPiece; + public class NoPiece extends ServerState { public NoPiece(ServerState parent, ServerGameLogic logic) { super(parent, logic); + entry(); + } + + @Override + public void entry() { +// if (hasTurbo() || turbo == 0) { +// if (roll == 6 && +// logic.getGame().getBoard().getPlayerData().getWaitingArea().hasPieces() && +// logic.getGame().getBoard().getNodes().getStartNode(Color).isOccupied()) { +// parent.gotoState(new WaitingPiece(parent, logic)); +// } else { +// parent.gotoState(new NoTurn(parent, logic)); +// } +// } else { +// validateHasPieces(); +// } + } + + private void validateHasPieces() { +// if (logic.getGame().getBoard().getPlayerData().getWaitingArea().hasPieces()) { +// if (logic.getGame().getBoard().getNodes().getStartNode(Color).isOccupied()) { +// if (roll == 6) { +// logic.send(new Player(1), new WaitPiece()); +// } else { +// validateMove(); +// } +// } else { +// if (logic.getGame().getBoard().getNodes().getStartNode(Color).getPiece().canMove()) { +// logic.send(new Player(1), new WaitPiece()); +// parent.gotoState(new StartPiece(parent, logic)); +// } else { +// validateMove(); +// } +// } +// } else { +// validateMove(); +// } + } + + private void validateMove() { +// if (player.canMove()) { +// parent.gotoState(new NoTurn(parent, logic)); +// } else { +// logic.send(new Player(1), new SelectPiece()); +// } } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/NoTurn.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/NoTurn.java index 9986437b..388f50bf 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/NoTurn.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/NoTurn.java @@ -1,7 +1,14 @@ package pp.mdga.server; +import pp.mdga.message.server.EndOfTurn; + public class NoTurn extends ServerState { public NoTurn(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + + @Override + public void sentEndOfTurn(EndOfTurn msg, int from) { + // todo: goto end of turn + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/PlayPowerCard.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/PlayPowerCard.java new file mode 100644 index 00000000..cc7cf7b0 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/PlayPowerCard.java @@ -0,0 +1,7 @@ +package pp.mdga.server; + +public class PlayPowerCard extends ServerState { + public PlayPowerCard(ServerState parent, ServerGameLogic logic) { + super(parent, logic); + } +} diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/PowerCard.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/PowerCard.java index fef94ce2..a66f0104 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/PowerCard.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/PowerCard.java @@ -1,7 +1,54 @@ package pp.mdga.server; +import pp.mdga.game.Player; +import pp.mdga.message.client.NoPowerCard; +import pp.mdga.message.client.SelectCard; +import pp.mdga.message.client.SelectedPieces; +import pp.mdga.message.server.DiceNow; +import pp.mdga.message.server.PossibleCard; + public class PowerCard extends ServerState { public PowerCard(ServerState parent, ServerGameLogic logic) { super(parent, logic); + logic.getGame().addObserver(this); + } + + @Override + public void receivedNoPowerCard(NoPowerCard msg, int from) { + // todo: send to everyone? or one player? + // todo: right msg? + logic.send(new Player(1), new DiceNow()); + parent.gotoState(new RollDice(parent, logic)); + } + + @Override + public void receivedSelectCard(SelectCard msg, int from) { + // todo: send to everyone? or one player? + logic.send(new Player(1), new PossibleCard()); + } + + @Override + public void receivedSelectedPieces(SelectedPieces msg, int from) { +// if (verifySelectedPieces()) { +// // todo: send to everyone? or one player? +// // todo: msg PowerCardAnimation? +// logic.send(new Player(1), new PowerCardAnimation()); +// parent.gotoState(new PlayPowerCard(parent, logic)); +// } + } + + @Override + public void sentPossibleCard(PossibleCard msg, int from) { + // todo: implement + } + + @Override + public void update() { + if (!super.getMoveablePieces(logic.getGame().getActiveColor()).isEmpty()) { + // todo: send to everyone? or one player? + // todo: right msg? + logic.send(new Player(1), new DiceNow()); + parent.gotoState(new RollDice(parent, logic)); + } } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/RollDiceMachine.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/RollDiceMachine.java index 49117d0c..bc788947 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/RollDiceMachine.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/RollDiceMachine.java @@ -6,7 +6,7 @@ public RollDiceMachine(ServerState parent, ServerGameLogic logic) { } @Override - public ServerState initialState() { - return null; + public FirstRoll initialState() { + return new FirstRoll(this, logic); } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/SecondRoll.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/SecondRoll.java index 63b98b9a..d149236b 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/SecondRoll.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/SecondRoll.java @@ -1,7 +1,25 @@ package pp.mdga.server; +import pp.mdga.game.Player; +import pp.mdga.message.client.RequestDice; +import pp.mdga.message.server.Dice; +import pp.mdga.message.server.DiceAgain; + public class SecondRoll extends ServerState { public SecondRoll(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + + @Override + public void receivedRequestDice(RequestDice msg, int from) { +// if (roll == 6) { +// // todo: send to everyone? or one player? +// logic.send(new Player(1), new Dice()); +// // todo: goto ChoosePiece +// } else { +// // todo: send to everyone? or one player? +// logic.send(new Player(1), new DiceAgain()); +// parent.gotoState(new ThirdRoll(parent, logic)); +// } + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/SelectPiece.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/SelectPiece.java index f3e21d28..9cd71e6a 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/SelectPiece.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/SelectPiece.java @@ -1,7 +1,22 @@ package pp.mdga.server; +import pp.mdga.game.Piece; +import pp.mdga.game.Player; +import pp.mdga.message.client.RequestMove; +import pp.mdga.message.server.StartPiece; + public class SelectPiece extends ServerState { public SelectPiece(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + + @Override + public void receivedRequestMove(RequestMove msg, int from) { +// if (verifyPiece(p)) { +// logic.send(new Player(1), new Animation()); +// // todo: goto state +// } else { +// logic.send(new Player(1), new StartPiece()); +// } + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerAutomaton.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerAutomaton.java index 4d8bbd31..14061e81 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerAutomaton.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerAutomaton.java @@ -1,11 +1,25 @@ package pp.mdga.server; +/** + * The ServerAutomaton class represents the top-level state machine for the server. + * It initializes the state machine and sets the initial state to Lobby. + */ public class ServerAutomaton extends ServerStateMachine { + /** + * Constructs a new ServerAutomaton with the specified game logic. + * + * @param logic the server game logic + */ public ServerAutomaton(ServerGameLogic logic) { super(null, logic); entry(); } + /** + * Returns the initial state of the state machine, which is Lobby. + * + * @return the initial state + */ @Override public Lobby initialState() { return new Lobby(this, logic); diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerGameLogic.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerGameLogic.java index c278a929..2dbb77f5 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerGameLogic.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerGameLogic.java @@ -125,7 +125,6 @@ public Game getGame() { return game; } - // todo: remove public ServerState getState() { return state; } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerState.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerState.java index 56ed1be3..90c08897 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerState.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerState.java @@ -6,63 +6,177 @@ import pp.mdga.game.PieceState; import pp.mdga.game.PlayerData; import pp.mdga.message.client.*; +import pp.mdga.message.server.EndOfTurn; import pp.mdga.message.server.PossibleCard; +import pp.mdga.message.server.RankingResponce; +import pp.mdga.message.server.ServerMessage; + import java.lang.System.Logger; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +/** + * Abstract class representing a state in the server's state machine. + * Implements the Observer pattern to observe changes in the game state. + */ public abstract class ServerState implements Observer { + /** + * Logger for logging messages within the application. + */ protected static final Logger LOGGER = System.getLogger(ServerState.class.getName()); + + /** + * The parent state of the current state. + */ protected ServerState parent; + + /** + * The game logic associated with the server state. + */ protected ServerGameLogic logic; - public ServerState(ServerState parent, ServerGameLogic logic) { + /** + * Constructs a new ServerState with the specified parent state and game logic. + * + * @param parent the parent state of the current state + * @param logic the game logic associated with the server state + */ + protected ServerState(ServerState parent, ServerGameLogic logic) { this.parent = parent; this.logic = logic; } + /** + * This method is called when the state is entered. + */ public void entry() { /* do nothing */ } - public void receivedAnimationEnd(AnimationEnd msg) { /* do nothing */ } + /** + * This method is called when the state is exited. + */ + public void exit() { /* do nothing */ } - // todo piece? - public void receivedConfirmPiece(Piece piece) { /* do nothing */ } + /** + * This method is called when an animation ends. + * + * @param msg the animation end message + */ + public void receivedAnimationEnd(AnimationEnd msg, int from) { /* do nothing */ } - public void receivedDeselectTSK(DeselectTSK msg) { /* do nothing */ } + /** + * This method is called when a TSK is deselected. + * + * @param msg the deselect TSK message + */ + public void receivedDeselectTSK(DeselectTSK msg, int from) { /* do nothing */ } - public void receivedNoPowerCard(NoPowerCard msg) { /* do nothing */ } + /** + * This method is called when a NoPowerCard message is received. + * + * @param msg the NoPowerCard message + */ + public void receivedNoPowerCard(NoPowerCard msg, int from) { /* do nothing */ } - public void receivedNotReady(LobbyNotReady msg) { /* do nothing */ } + /** + * This method is called when a LobbyNotReady message is received. + * + * @param msg the LobbyNotReady message + */ + public void receivedNotReady(LobbyNotReady msg, int from) { /* do nothing */ } - public void receivedPowerCardChoice(SelectCard msg) { /* do nothing */ } + /** + * This method is called when a LobbyReady message is received. + * + * @param msg the LobbyReady message + */ + public void receivedReady(LobbyReady msg, int from) { /* do nothing */ } - public void receivedReady(LobbyReady msg) { /* do nothing */ } + /** + * This method is called when a RequestDice message is received. + * + * @param msg the RequestDice message + */ + public void receivedRequestDice(RequestDice msg, int from) { /* do nothing */ } - public void receivedRequestDice(RequestDice msg) { /* do nothing */ } + /** + * This method is called when a RequestMove message is received. + * + * @param msg the RequestMove message + */ + public void receivedRequestMove(RequestMove msg, int from) { /* do nothing */ } - // todo msg? - public void receivedRollRankingDice() { /* do nothing */ } + /** + * This method is called when a SelectCard message is received. + * + * @param msg the SelectCard message + */ + public void receivedSelectCard(SelectCard msg, int from) { /* do nothing */ } - public void receivedSelectTSK(SelectTSK msg) { /* do nothing */ } + /** + * This method is called when a SelectTSK message is received. + * + * @param msg the SelectTSK message + */ + public void receivedSelectTSK(SelectTSK msg, int from) { /* do nothing */ } - public void receivedSelectedPieces(SelectedPieces msg) { /* do nothing */ } + /** + * This method is called when a SelectedPieces message is received. + * + * @param msg the SelectedPieces message + */ + public void receivedSelectedPieces(SelectedPieces msg, int from) { /* do nothing */ } - public void receivedStartGame(ClientStartGame msg) { /* do nothing */ } + /** + * This method is called when a StartGame message is received. + * + * @param msg the StartGame message + */ + public void receivedStartGame(ClientStartGame msg, int from) { /* do nothing */ } - public void sentPossibleCard(PossibleCard msg) { /* do nothing */ } + /** + * This method is called when an EndOfTurn message is sent. + * + * @param msg the EndOfTurn message + */ + public void sentEndOfTurn(EndOfTurn msg, int from) { /* do nothing */ } - // todo msg?, sent to everyone? - public void sentRankingResponse() { /* do nothing */ } + /** + * This method is called when a PossibleCard message is sent. + * + * @param msg the PossibleCard message + */ + public void sentPossibleCard(PossibleCard msg, int from) { /* do nothing */ } + /** + * This method is called when a RankingResponce message is sent. + * + * @param msg the RankingResponce message + */ + public void sentRankingResponse(RankingResponce msg, int from) { /* do nothing */ } + + /** + * This method transitions to a new state. + * + * @param state the new state to transition to + * @throws IllegalStateException if called outside a state machine + */ public void gotoState(ServerState state) { throw new IllegalStateException("not in a statemachine"); } + /** + * Returns the parent state of the current state. + * + * @return the parent state + */ public ServerState getParent() { return parent; } + /** + * This method is called when the observed object is changed. + * It is part of the Observer pattern implementation. + */ public void update() { /* do nothing */ } /** @@ -70,7 +184,7 @@ public void update() { /* do nothing */ } * * @return the steps a piece can move */ - private int calculateSteps(){ + private int calculateSteps() { return logic.getGame().getDiceEyes() * logic.getGame().getDiceModifier(); } @@ -81,14 +195,15 @@ private int calculateSteps(){ * @return true if the piece can be moved, false otherwise */ protected boolean tryMove(Piece piece) { - if (piece.getState() == PieceState.HOME){ - return tryHomeMove(piece, calculateSteps()); + int steps = calculateSteps(); + if (piece.getState() == PieceState.HOME) { + return tryHomeMove(piece, steps); } else { - int homeMoves = getHomeMoves(piece, calculateSteps()); - if (homeMoves > 0){ + int homeMoves = getHomeMoves(piece, steps); + if (homeMoves > 0) { return tryHomeMove(piece, homeMoves); } else { - return tryInfieldMove(piece, calculateSteps()); + return tryInfieldMove(piece, steps); } } } @@ -105,12 +220,12 @@ protected int getHomeMoves(Piece piece, int steps) { Color col = piece.getColor(); int startIndex = logic.getGame().getBoard().getPlayerData().get(col).getStartNodeIndex(); int moveIndex = startIndex + steps; - if (moveIndex > logic.getGame().getBoard().getInfield().length){ + if (moveIndex > logic.getGame().getBoard().getInfield().length) { moveIndex %= logic.getGame().getBoard().getInfield().length; - if(moveIndex >= startIndex){ + if (moveIndex >= startIndex) { return moveIndex - startIndex + 1; } - } else if (figureIndex < startIndex && moveIndex >= startIndex){ + } else if (figureIndex < startIndex && moveIndex >= startIndex) { return moveIndex - startIndex + 1; } return 0; @@ -123,11 +238,11 @@ protected int getHomeMoves(Piece piece, int steps) { * @param steps the steps the piece would move * @return true if the piece can move in the infield, false otherwise */ - protected boolean tryInfieldMove(Piece piece, int steps){ + protected boolean tryInfieldMove(Piece piece, int steps) { int figureIndex = logic.getGame().getBoard().getInfieldIndexOfPiece(piece); int moveIndex = (figureIndex + steps) % logic.getGame().getBoard().getInfield().length; Piece occupant = logic.getGame().getBoard().getInfield()[moveIndex].getOccupant(); - if(occupant != null){ + if (occupant != null) { return occupant.getColor() != piece.getColor(); } return true; @@ -140,22 +255,23 @@ protected boolean tryInfieldMove(Piece piece, int steps){ * @param steps the steps the piece would move * @return true if the piece can move into the home area, false otherwise */ - protected boolean tryHomeMove(Piece piece, int steps){ + protected boolean tryHomeMove(Piece piece, int steps) { Color col = piece.getColor(); PlayerData playerData = logic.getGame().getBoard().getPlayerData().get(col); Node[] homeNodes = playerData.getHomeNodes(); int index; - if (playerData.homeIncludes(piece)){ + if (playerData.homeIncludes(piece)) { index = playerData.getIndexInHome(piece); } else { index = 0; } - if(index + steps >= homeNodes.length){ + + if (index + steps >= homeNodes.length) { return false; } else { - for(int i = index; i <= index + steps; i++){ - if(homeNodes[i].getOccupant() != null){ + for (int i = index; i <= index + steps; i++) { + if (homeNodes[i].getOccupant() != null) { return false; } } @@ -173,7 +289,7 @@ protected List getMoveablePieces(Color color) { ArrayList moveablePieces = new ArrayList<>(); ArrayList pieces = new ArrayList<>(); for (Piece piece : logic.getGame().getBoard().getPlayerData().get(color).getPieces()) { - if(piece.getState() == PieceState.ACTIVE || piece.getState() == PieceState.HOME){ + if (piece.getState() == PieceState.ACTIVE || piece.getState() == PieceState.HOME) { pieces.add(piece); } } @@ -185,6 +301,22 @@ protected List getMoveablePieces(Color color) { return moveablePieces; } + /** + * Broadcasts an update message to all players. + * + * @param updateMessage the update message to be sent + */ + protected void broadcastUpdate(ServerMessage updateMessage) { + for (var entry : logic.getGame().getPlayers().entrySet()) { + logic.send(entry.getValue(), updateMessage); + } + } + + /** + * Returns a string representation of the object. + * + * @return the simple name of the class + */ @Override public String toString() { return getClass().getSimpleName(); diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerStateMachine.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerStateMachine.java index f97d54f2..a55c0ef0 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerStateMachine.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/ServerStateMachine.java @@ -1,25 +1,50 @@ package pp.mdga.server; -import pp.mdga.game.Piece; import pp.mdga.message.client.*; +import pp.mdga.message.server.EndOfTurn; import pp.mdga.message.server.PossibleCard; +import pp.mdga.message.server.RankingResponce; +/** + * Abstract class representing a state machine for the server. + * It manages the transitions between different states and delegates + * the handling of messages to the current state. + */ public abstract class ServerStateMachine extends ServerState { - + /** + * The current state of the state machine. + */ private ServerState state; - public ServerStateMachine(ServerState parent, ServerGameLogic logic) { + /** + * Constructs a new instance of ServerStateMachine. + * + * @param parent the parent state + * @param logic the server game logic + */ + protected ServerStateMachine(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + /** + * Creates the initial state of a state machine. + */ public abstract ServerState initialState(); + /** + * Transitions to a new state. + * + * @param newState the new state to transition to + */ @Override public void gotoState(ServerState newState) { LOGGER.log(System.Logger.Level.DEBUG, "{0}: {1} --> {2}", this, state, newState); enter(newState); } + /** + * This method is called when the state is entered. + */ @Override public void entry() { final ServerState newState = initialState(); @@ -27,6 +52,12 @@ public void entry() { enter(newState); } + /** + * Enters a new state. + * + * @param newState the new state to enter + * @throws IllegalArgumentException if the new state does not belong to this state machine + */ private void enter(ServerState newState) { if (newState.parent != this) throw new IllegalArgumentException("Wrong state: " + newState + " belongs to " + newState.parent + " instead of " + this); @@ -34,81 +65,170 @@ private void enter(ServerState newState) { state.entry(); } + /** + * This method is called when the state is exited. + */ @Override - public void receivedAnimationEnd(AnimationEnd msg) { - state.receivedAnimationEnd(msg); + public void exit() { + state.exit(); } - // todo piece? + /** + * This method is called when an animation ends. + * + * @param msg the animation end message + */ @Override - public void receivedConfirmPiece(Piece piece) { - state.receivedConfirmPiece(piece); + public void receivedAnimationEnd(AnimationEnd msg, int from) { + state.receivedAnimationEnd(msg, from); } + /** + * This method is called when a TSK is deselected. + * + * @param msg the deselect TSK message + */ @Override - public void receivedDeselectTSK(DeselectTSK msg) { - state.receivedDeselectTSK(msg); + public void receivedDeselectTSK(DeselectTSK msg, int from) { + state.receivedDeselectTSK(msg, from); } + /** + * This method is called when a NoPowerCard message is received. + * + * @param msg the NoPowerCard message + */ @Override - public void receivedNoPowerCard(NoPowerCard msg) { - state.receivedNoPowerCard(msg); + public void receivedNoPowerCard(NoPowerCard msg, int from) { + state.receivedNoPowerCard(msg, from); } + /** + * This method is called when a LobbyNotReady message is received. + * + * @param msg the LobbyNotReady message + */ @Override - public void receivedNotReady(LobbyNotReady msg) { - state.receivedNotReady(msg); + public void receivedNotReady(LobbyNotReady msg, int from) { + state.receivedNotReady(msg, from); } + /** + * This method is called when a LobbyReady message is received. + * + * @param msg the LobbyReady message + */ @Override - public void receivedPowerCardChoice(SelectCard msg) { - state.receivedPowerCardChoice(msg); + public void receivedReady(LobbyReady msg, int from) { + state.receivedReady(msg, from); } + /** + * This method is called when a RequestDice message is received. + * + * @param msg the RequestDice message + */ @Override - public void receivedReady(LobbyReady msg) { - state.receivedReady(msg); + public void receivedRequestDice(RequestDice msg, int from) { + state.receivedRequestDice(msg, from); } + /** + * This method is called when a RequestMove message is received. + * + * @param msg the RequestMove message + */ @Override - public void receivedRequestDice(RequestDice msg) { - state.receivedRequestDice(msg); + public void receivedRequestMove(RequestMove msg, int from) { + state.receivedRequestMove(msg, from); } - // todo msg? + /** + * This method is called when a SelectCard message is received. + * + * @param msg the SelectCard message + */ @Override - public void receivedRollRankingDice() { - state.receivedRollRankingDice(); + public void receivedSelectCard(SelectCard msg, int from) { + state.receivedSelectCard(msg, from); } + /** + * This method is called when a SelectTSK message is received. + * + * @param msg the SelectTSK message + */ @Override - public void receivedSelectTSK(SelectTSK msg) { - state.receivedSelectTSK(msg); + public void receivedSelectTSK(SelectTSK msg, int from) { + state.receivedSelectTSK(msg, from); } + /** + * This method is called when a SelectedPieces message is received. + * + * @param msg the SelectedPieces message + */ @Override - public void receivedSelectedPieces(SelectedPieces msg) { - state.receivedSelectedPieces(msg); + public void receivedSelectedPieces(SelectedPieces msg, int from) { + state.receivedSelectedPieces(msg, from); } + /** + * This method is called when a StartGame message is received. + * + * @param msg the StartGame message + */ @Override - public void receivedStartGame(ClientStartGame msg) { - state.receivedStartGame(msg); + public void receivedStartGame(ClientStartGame msg, int from) { + state.receivedStartGame(msg, from); } + /** + * This method is called when an EndOfTurn message is sent. + * + * @param msg the EndOfTurn message + */ @Override - public void sentPossibleCard(PossibleCard msg) { - state.sentPossibleCard(msg); + public void sentEndOfTurn(EndOfTurn msg, int from) { + state.sentEndOfTurn(msg, from); } - // todo msg?, sent to everyone? + /** + * This method is called when a PossibleCard message is sent. + * + * @param msg the PossibleCard message + */ @Override - public void sentRankingResponse() { - state.sentRankingResponse(); + public void sentPossibleCard(PossibleCard msg, int from) { + state.sentPossibleCard(msg, from); } + /** + * This method is called when a RankingResponce message is sent. + * + * @param msg the RankingResponce message + */ + @Override + public void sentRankingResponse(RankingResponce msg, int from) { + state.sentRankingResponse(msg, from); + } + + /** + * Returns a string representation of the object, including the current state. + * + * @return the string representation of the object + */ @Override public String toString() { return super.toString() + "(in " + state + ")"; } + + /** + * Returns the current state. + * + * @return the current state + */ + public ServerState getState() { + return state; + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/StartPiece.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/StartPiece.java index 24e23b60..f18641a2 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/StartPiece.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/StartPiece.java @@ -1,7 +1,21 @@ package pp.mdga.server; +import pp.mdga.game.Piece; +import pp.mdga.game.Player; +import pp.mdga.message.client.RequestMove; + public class StartPiece extends ServerState { public StartPiece(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + + @Override + public void receivedRequestMove(RequestMove msg, int from) { +// if (verifyPiece(p)) { +// logic.send(new Player(1), new Animation()); +// // todo: goto state +// } else { +// logic.send(new Player(1), new pp.mdga.message.server.StartPiece()); +// } + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/ThirdRoll.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/ThirdRoll.java index 5f5245d1..ebe9fd77 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/ThirdRoll.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/ThirdRoll.java @@ -1,7 +1,25 @@ package pp.mdga.server; +import pp.mdga.game.Player; +import pp.mdga.message.client.RequestDice; +import pp.mdga.message.server.Dice; +import pp.mdga.message.server.DiceAgain; + public class ThirdRoll extends ServerState { public ThirdRoll(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + + @Override + public void receivedRequestDice(RequestDice msg, int from) { +// if (roll == 6) { +// // todo: send to everyone? or one player? +// logic.send(new Player(1), new Dice()); +// // todo: goto ChoosePiece +// } else { +// // todo: send to everyone? or one player? +// logic.send(new Player(1), new DiceAgain()); +// // todo: goto End from Turn +// } + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/Turn.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/Turn.java index ce1447a6..d2eacc7b 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/Turn.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/Turn.java @@ -1,9 +1,36 @@ package pp.mdga.server; +import pp.mdga.client.Spectator; +import pp.mdga.game.Player; +import pp.mdga.message.server.ActivePlayer; +import pp.mdga.message.server.Ceremony; +import pp.mdga.message.server.EndOfTurn; + public class Turn extends ServerState { private final TurnStateMachine turnStateMachine = new TurnStateMachine(this, logic); public Turn(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + + // todo: when TurnStateMachine is in the end state, and then? + @Override + public void exit() { + Player player = logic.getGame().getStartPlayer(); + +// if (player.isFinished()) { +// logic.send(player, new Spectator()); +// } else { +// logic.send(player, new EndOfTurn()); +// } + + if (logic.getGame().getPlayers().size() == 1) { + broadcastUpdate(new Ceremony()); + this.getParent().getParent().exit(); + } else { + // todo: next player + broadcastUpdate(new ActivePlayer()); + parent.gotoState(new Animation(parent, logic)); + } + } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/TurnStateMachine.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/TurnStateMachine.java index b54f2e07..a5974332 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/TurnStateMachine.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/TurnStateMachine.java @@ -6,7 +6,7 @@ public TurnStateMachine(ServerState parent, ServerGameLogic logic) { } @Override - public ServerState initialState() { - return null; + public PowerCard initialState() { + return new PowerCard(this, logic); } } diff --git a/Projekte/mdga/model/src/main/java/pp.mdga/server/WaitingPiece.java b/Projekte/mdga/model/src/main/java/pp.mdga/server/WaitingPiece.java index dcc28f3c..a284a451 100644 --- a/Projekte/mdga/model/src/main/java/pp.mdga/server/WaitingPiece.java +++ b/Projekte/mdga/model/src/main/java/pp.mdga/server/WaitingPiece.java @@ -1,7 +1,23 @@ package pp.mdga.server; +import pp.mdga.game.Piece; +import pp.mdga.game.Player; +import pp.mdga.message.client.RequestDice; +import pp.mdga.message.client.RequestMove; +import pp.mdga.message.server.StartPiece; + public class WaitingPiece extends ServerState { public WaitingPiece(ServerState parent, ServerGameLogic logic) { super(parent, logic); } + + @Override + public void receivedRequestMove(RequestMove msg, int from) { +// if (verifyPiece(p)) { +// logic.send(new Player(1), new Animation()); +// // todo: goto state +// } else { +// logic.send(new Player(1), new StartPiece()); +// } + } }