diff options
6 files changed, 106 insertions, 22 deletions
diff --git a/src/main/java/org/luxons/sevenwonders/actions/StartGameAction.java b/src/main/java/org/luxons/sevenwonders/actions/StartGameAction.java new file mode 100644 index 00000000..632b80ef --- /dev/null +++ b/src/main/java/org/luxons/sevenwonders/actions/StartGameAction.java @@ -0,0 +1,19 @@ +package org.luxons.sevenwonders.actions; + +import javax.validation.constraints.NotNull; + +import org.luxons.sevenwonders.game.Settings; + +public class StartGameAction { + + @NotNull + private Settings settings; + + public Settings getSettings() { + return settings; + } + + public void setSettings(Settings settings) { + this.settings = settings; + } +} diff --git a/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java b/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java index ea262c4e..37041f32 100644 --- a/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java +++ b/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java @@ -2,12 +2,15 @@ package org.luxons.sevenwonders.controllers; import java.security.Principal; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.luxons.sevenwonders.actions.JoinOrCreateGameAction; +import org.luxons.sevenwonders.actions.StartGameAction; import org.luxons.sevenwonders.game.Game; import org.luxons.sevenwonders.game.Lobby; import org.luxons.sevenwonders.game.Player; +import org.luxons.sevenwonders.game.api.PlayerTurnInfo; import org.luxons.sevenwonders.game.data.GameDefinitionLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,6 +19,7 @@ import org.springframework.messaging.handler.annotation.MessageExceptionHandler; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; +import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.annotation.SendToUser; import org.springframework.stereotype.Controller; import org.springframework.validation.annotation.Validated; @@ -30,6 +34,8 @@ public class LobbyController { private final GameDefinitionLoader gameDefinitionLoader; + private final SimpMessagingTemplate template; + private long lastGameId = 0; private Map<String, Lobby> lobbies = new HashMap<>(); @@ -37,8 +43,9 @@ public class LobbyController { private Map<String, Game> games = new HashMap<>(); @Autowired - public LobbyController(GameDefinitionLoader gameDefinitionLoader) { + public LobbyController(GameDefinitionLoader gameDefinitionLoader, SimpMessagingTemplate template) { this.gameDefinitionLoader = gameDefinitionLoader; + this.template = template; } @MessageExceptionHandler @@ -93,10 +100,35 @@ public class LobbyController { return lobby; } + @MessageMapping("/start-game") + public void startGame(SimpMessageHeaderAccessor headerAccessor, @Validated StartGameAction action, + Principal principal) { + Lobby lobby = (Lobby)headerAccessor.getSessionAttributes().get(ATTR_LOBBY); + if (lobby == null) { + logger.error("User {} is not in a game", principal.getName()); + template.convertAndSendToUser(principal.getName(), "/queue/errors", "No game to start"); + return; + } + + if (!lobby.isOwner(principal.getName())) { + logger.error("User {} is not the owner of the game '{}'", principal.getName(), lobby.getName()); + template.convertAndSendToUser(principal.getName(), "/queue/errors", "Only the owner can start the game"); + return; + } + + Game game = lobby.startGame(action.getSettings()); + logger.info("Game {} successfully started", game.getId()); + + List<PlayerTurnInfo> playerTurnInfos = game.startTurn(); + for (PlayerTurnInfo playerTurnInfo : playerTurnInfos) { + Player player = playerTurnInfo.getTable().getPlayers().get(playerTurnInfo.getPlayerIndex()); + String userName = player.getUserName(); + template.convertAndSendToUser(userName, "/queue/game/turn", playerTurnInfo); + } + } + private Player createPlayer(String name, Principal principal) { - Player player = new Player(name); - player.setUserName(principal.getName()); - return player; + return new Player(name, principal.getName()); } private Lobby createGame(String name, Player owner) { @@ -114,7 +146,6 @@ public class LobbyController { public GameNotFoundException(String name) { super(name); } - } private class GameNameAlreadyUsedException extends UniqueIdAlreadyUsedException { @@ -123,5 +154,4 @@ public class LobbyController { super(name); } } - } diff --git a/src/main/java/org/luxons/sevenwonders/game/Game.java b/src/main/java/org/luxons/sevenwonders/game/Game.java index f4dac7ef..2a2fab27 100644 --- a/src/main/java/org/luxons/sevenwonders/game/Game.java +++ b/src/main/java/org/luxons/sevenwonders/game/Game.java @@ -37,22 +37,23 @@ public class Game { this.discardedCards = new ArrayList<>(); this.hands = new HashMap<>(); this.preparedMoves = new HashMap<>(); + startNewAge(); } public long getId() { return id; } - public int startNewAge() { + private void startNewAge() { currentAge++; hands = decks.deal(currentAge, table.getNbPlayers()); - return currentAge; } public List<PlayerTurnInfo> startTurn() { return hands.entrySet() .stream() .map(e -> table.createPlayerTurnInfo(e.getKey(), e.getValue())) + .peek(ptu -> ptu.setCurrentAge(currentAge)) .collect(Collectors.toList()); } @@ -69,10 +70,27 @@ public class Game { return preparedMoves.size() == table.getPlayers().size(); } - public void playTurn() { + public List<Move> playTurn() { + List<Move> playedMoves = mapToList(preparedMoves); + // cards need to be all placed first as some effects depend on just-played cards placePreparedCards(); playPreparedCards(); + preparedMoves.clear(); + + return playedMoves; + } + + private static List<Move> mapToList(Map<Integer, Move> movesPerPlayer) { + List<Move> moves = new ArrayList<>(movesPerPlayer.size()); + for (int p = 0; p < movesPerPlayer.size(); p++) { + Move move = movesPerPlayer.get(p); + if (move == null) { + throw new MissingPreparedMoveException(p); + } + moves.add(move); + } + return moves; } private void placePreparedCards() { @@ -85,10 +103,10 @@ public class Game { // TODO pre-upgrade the level of wonder without effect break; case DISCARD: + discardedCards.add(decks.getCard(move.getCardName())); break; } }); - } private void playPreparedCards() { @@ -108,6 +126,13 @@ public class Game { } - public class InvalidMoveException extends RuntimeException { + private static class MissingPreparedMoveException extends RuntimeException { + + public MissingPreparedMoveException(int playerIndex) { + super("Player " + playerIndex + " is not ready to play"); + } + } + + private static class InvalidMoveException extends RuntimeException { } } diff --git a/src/main/java/org/luxons/sevenwonders/game/Lobby.java b/src/main/java/org/luxons/sevenwonders/game/Lobby.java index 7256936c..7fdffef5 100644 --- a/src/main/java/org/luxons/sevenwonders/game/Lobby.java +++ b/src/main/java/org/luxons/sevenwonders/game/Lobby.java @@ -12,6 +12,8 @@ public class Lobby { private final String name; + private final Player owner; + private final List<Player> players; private final GameDefinition gameDefinition; @@ -21,6 +23,7 @@ public class Lobby { public Lobby(long id, String name, Player owner, GameDefinition gameDefinition) { this.id = id; this.name = name; + this.owner = owner; this.gameDefinition = gameDefinition; this.players = new ArrayList<>(gameDefinition.getMinPlayers()); players.add(owner); @@ -79,6 +82,10 @@ public class Lobby { return "Lobby{" + "id=" + id + ", name='" + name + '\'' + ", state=" + state + '}'; } + public boolean isOwner(String userName) { + return owner.getUserName().equals(userName); + } + public class GameAlreadyStartedException extends IllegalStateException { } diff --git a/src/main/java/org/luxons/sevenwonders/game/Player.java b/src/main/java/org/luxons/sevenwonders/game/Player.java index fd2f254b..66ce566d 100644 --- a/src/main/java/org/luxons/sevenwonders/game/Player.java +++ b/src/main/java/org/luxons/sevenwonders/game/Player.java @@ -2,30 +2,23 @@ package org.luxons.sevenwonders.game; public class Player { - private String displayName; + private final String displayName; - private String userName; + private final String userName; - public Player(String displayName) { + public Player(String displayName, String userName) { this.displayName = displayName; + this.userName = userName; } public String getDisplayName() { return displayName; } - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - public String getUserName() { return userName; } - public void setUserName(String userName) { - this.userName = userName; - } - @Override public String toString() { return "Player{" + "name='" + displayName + '\'' + ", userName='" + userName + '\'' + '}'; diff --git a/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java b/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java index ad9e6da9..b7090ff9 100644 --- a/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java +++ b/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java @@ -8,6 +8,8 @@ public class PlayerTurnInfo { private final Table table; + private int currentAge; + private List<HandCard> hand; private String message; @@ -25,6 +27,14 @@ public class PlayerTurnInfo { return table; } + public int getCurrentAge() { + return currentAge; + } + + public void setCurrentAge(int currentAge) { + this.currentAge = currentAge; + } + public List<HandCard> getHand() { return hand; } |