summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt9
-rw-r--r--sw-server/src/main/kotlin/org/luxons/sevenwonders/server/api/Converters.kt8
-rw-r--r--sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameBrowserController.kt24
-rw-r--r--sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt6
-rw-r--r--sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Lobby.kt23
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt4
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/Lobby.kt3
7 files changed, 51 insertions, 26 deletions
diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt
index 503141c4..5816edaf 100644
--- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt
+++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/Api.kt
@@ -15,7 +15,14 @@ data class LobbyDTO(
val owner: String,
val players: List<PlayerDTO>,
val state: State,
- val canBeStarted: Boolean
+ val joinAction: Actionability,
+ val startAction: Actionability
+)
+
+@Serializable
+data class Actionability(
+ val canDo: Boolean,
+ val tooltip: String
)
@Serializable
diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/api/Converters.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/api/Converters.kt
index 390dc839..5fb73b23 100644
--- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/api/Converters.kt
+++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/api/Converters.kt
@@ -5,9 +5,11 @@ import org.luxons.sevenwonders.model.api.PlayerDTO
import org.luxons.sevenwonders.server.lobby.Lobby
import org.luxons.sevenwonders.server.lobby.Player
-fun Lobby.toDTO(currentUser: String): LobbyDTO {
- val players = getPlayers().map { it.toDTO(currentUser) }
- return LobbyDTO(id, name, owner.username, players, state, canBeStarted())
+fun Lobby.toDTO(currentPlayer: Player): LobbyDTO {
+ val players = getPlayers().map { it.toDTO(currentPlayer.username) }
+ val joinability = joinability(currentPlayer.displayName)
+ val startability = startability(currentPlayer.username)
+ return LobbyDTO(id, name, owner.username, players, state, joinability, startability)
}
fun Player.toDTO(currentUser: String) =
diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameBrowserController.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameBrowserController.kt
index e2f0458e..aa98f121 100644
--- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameBrowserController.kt
+++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameBrowserController.kt
@@ -30,7 +30,6 @@ class GameBrowserController @Autowired constructor(
private val playerRepository: PlayerRepository,
private val template: SimpMessagingTemplate
) {
-
/**
* Gets the created or updated games. The list of existing games is received on this topic at once upon
* subscription, and then each time the list changes.
@@ -42,7 +41,8 @@ class GameBrowserController @Autowired constructor(
@SubscribeMapping("/games") // prefix /topic not shown
fun listGames(principal: Principal): Collection<LobbyDTO> {
logger.info("Player '{}' subscribed to /topic/games", principal.name)
- return lobbyRepository.list().map { it.toDTO(principal.name) }
+ val player = playerRepository.find(principal.name)
+ return lobbyRepository.list().map { it.toDTO(player) }
}
/**
@@ -58,15 +58,13 @@ class GameBrowserController @Autowired constructor(
fun createGame(@Validated action: CreateGameAction, principal: Principal): LobbyDTO {
checkThatUserIsNotInAGame(principal, "cannot create another game")
- val gameOwner = playerRepository.find(principal.name)
- val lobby = lobbyRepository.create(action.gameName, gameOwner)
+ val player = playerRepository.find(principal.name)
+ val lobby = lobbyRepository.create(action.gameName, owner = player)
- logger.info(
- "Game '{}' ({}) created by {} ({})", lobby.name, lobby.id, gameOwner.displayName, gameOwner.username
- )
+ logger.info("Game '{}' ({}) created by {} ({})", lobby.name, lobby.id, player.displayName, player.username)
// notify everyone that a new game exists
- val lobbyDto = lobby.toDTO(principal.name)
+ val lobbyDto = lobby.toDTO(player)
template.convertAndSend("/topic/games", listOf(lobbyDto))
return lobbyDto
}
@@ -85,13 +83,11 @@ class GameBrowserController @Autowired constructor(
checkThatUserIsNotInAGame(principal, "cannot join another game")
val lobby = lobbyRepository.find(action.gameId)
- val newPlayer = playerRepository.find(principal.name)
- lobby.addPlayer(newPlayer)
+ val player = playerRepository.find(principal.name)
+ lobby.addPlayer(player)
- logger.info(
- "Player '{}' ({}) joined game {}", newPlayer.displayName, newPlayer.username, lobby.name
- )
- val lobbyDTO = lobby.toDTO(principal.name)
+ logger.info("Player '{}' ({}) joined game {}", player.displayName, player.username, lobby.name)
+ val lobbyDTO = lobby.toDTO(player)
lobbyController.sendLobbyUpdateToPlayers(lobbyDTO)
return lobbyDTO
}
diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt
index 19834ef1..477a6739 100644
--- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt
+++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/LobbyController.kt
@@ -44,7 +44,7 @@ class LobbyController @Autowired constructor(
}
logger.info("Player {} left game '{}'", player, lobby.name)
- sendLobbyUpdateToPlayers(lobby.toDTO(principal.name))
+ sendLobbyUpdateToPlayers(lobby.toDTO(principal.player))
}
/**
@@ -61,7 +61,7 @@ class LobbyController @Autowired constructor(
lobby.reorderPlayers(action.orderedPlayers)
logger.info("Players in game '{}' reordered to {}", lobby.name, action.orderedPlayers)
- sendLobbyUpdateToPlayers(lobby.toDTO(principal.name))
+ sendLobbyUpdateToPlayers(lobby.toDTO(principal.player))
}
/**
@@ -78,7 +78,7 @@ class LobbyController @Autowired constructor(
lobby.settings = action.settings
logger.info("Updated settings of game '{}'", lobby.name)
- sendLobbyUpdateToPlayers(lobby.toDTO(principal.name))
+ sendLobbyUpdateToPlayers(lobby.toDTO(principal.player))
}
internal fun sendLobbyUpdateToPlayers(lobby: LobbyDTO) {
diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Lobby.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Lobby.kt
index 599d889f..5368bedf 100644
--- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Lobby.kt
+++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Lobby.kt
@@ -3,6 +3,7 @@ package org.luxons.sevenwonders.server.lobby
import org.luxons.sevenwonders.engine.Game
import org.luxons.sevenwonders.engine.data.GameDefinition
import org.luxons.sevenwonders.model.CustomizableSettings
+import org.luxons.sevenwonders.model.api.Actionability
import org.luxons.sevenwonders.model.api.State
class Lobby(
@@ -40,11 +41,24 @@ class Lobby(
players.add(player)
}
+ fun joinability(userDisplayName: String): Actionability = when {
+ hasStarted() -> Actionability(false, "Cannot join: the game has already started")
+ maxPlayersReached() -> Actionability(
+ false,
+ "Cannot join: the game is full (${gameDefinition.maxPlayers} players max)"
+ )
+ playerNameAlreadyUsed(userDisplayName) -> Actionability(
+ false,
+ "Cannot join: already a player named '$userDisplayName' in this game"
+ )
+ else -> Actionability(true, "Join game")
+ }
+
private fun hasStarted(): Boolean = state != State.LOBBY
private fun maxPlayersReached(): Boolean = players.size >= gameDefinition.maxPlayers
- private fun playerNameAlreadyUsed(name: String?): Boolean = players.any { it.displayName == name }
+ private fun playerNameAlreadyUsed(name: String): Boolean = players.any { it.displayName == name }
@Synchronized
fun startGame(): Game {
@@ -57,7 +71,12 @@ class Lobby(
return game
}
- fun canBeStarted(): Boolean = hasEnoughPlayers()
+ fun startability(username: String): Actionability = when {
+ !hasEnoughPlayers() -> Actionability(false, "Cannot start: min ${gameDefinition.minPlayers} players required"
+ )
+ owner.username != username -> Actionability(false, "Cannot start the game: only the owner can")
+ else -> Actionability(true, "Start game")
+ }
private fun hasEnoughPlayers(): Boolean = players.size >= gameDefinition.minPlayers
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
index 375ac96f..10d5c868 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
@@ -108,9 +108,9 @@ private fun RBuilder.playerCount(nPlayers: Int) {
private fun RBuilder.joinButton(lobby: LobbyDTO, joinGame: (Long) -> Unit) {
bpButton(
minimal = true,
- title = "Join Game",
+ title = lobby.joinAction.tooltip,
icon = "arrow-right",
- disabled = lobby.state != State.LOBBY,
+ disabled = !lobby.joinAction.canDo,
onClick = { joinGame(lobby.id) }
)
}
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/Lobby.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/Lobby.kt
index 62f1c524..668a41c2 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/Lobby.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/Lobby.kt
@@ -40,7 +40,8 @@ class LobbyPresenter(props: LobbyProps) : RComponent<LobbyProps, RState>(props)
large = true,
intent = Intent.PRIMARY,
icon = "play",
- disabled = !currentGame.canBeStarted,
+ title = currentGame.startAction.tooltip,
+ disabled = !currentGame.startAction.canDo,
onClick = { props.startGame() }
) {
+ "START"
bgstack15