From 4f3eec40a87c5e4f52fc89238642dd7a17650540 Mon Sep 17 00:00:00 2001 From: Joffrey Bion Date: Thu, 21 May 2020 13:46:30 +0200 Subject: Allow custom player icons --- .../kotlin/org/luxons/sevenwonders/bot/SevenWondersBot.kt | 3 ++- .../org/luxons/sevenwonders/client/SevenWondersClient.kt | 12 +++--------- .../kotlin/org/luxons/sevenwonders/model/api/Api.kt | 5 ++++- .../org/luxons/sevenwonders/model/api/actions/Actions.kt | 11 ++++++++++- .../org/luxons/sevenwonders/server/api/Converters.kt | 2 +- .../sevenwonders/server/controllers/HomeController.kt | 4 ++-- .../kotlin/org/luxons/sevenwonders/server/lobby/Player.kt | 4 +++- .../sevenwonders/server/repositories/PlayerRepository.kt | 6 ++++-- .../sevenwonders/server/controllers/HomeControllerTest.kt | 4 +++- .../sevenwonders/ui/components/lobby/RadialPlayerList.kt | 15 +++++++++------ .../org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt | 2 +- 11 files changed, 42 insertions(+), 26 deletions(-) diff --git a/sw-bot/src/main/kotlin/org/luxons/sevenwonders/bot/SevenWondersBot.kt b/sw-bot/src/main/kotlin/org/luxons/sevenwonders/bot/SevenWondersBot.kt index deb7e237..89630b63 100644 --- a/sw-bot/src/main/kotlin/org/luxons/sevenwonders/bot/SevenWondersBot.kt +++ b/sw-bot/src/main/kotlin/org/luxons/sevenwonders/bot/SevenWondersBot.kt @@ -11,6 +11,7 @@ import org.luxons.sevenwonders.model.Action import org.luxons.sevenwonders.model.MoveType import org.luxons.sevenwonders.model.PlayerMove import org.luxons.sevenwonders.model.PlayerTurnInfo +import org.luxons.sevenwonders.model.api.actions.Icon import org.luxons.sevenwonders.model.resources.noTransactions import kotlin.random.Random import kotlin.time.Duration @@ -34,7 +35,7 @@ class SevenWondersBot( suspend fun play(serverHost: String, gameId: Long) = withTimeout(botConfig.globalTimeout) { val session = client.connect(serverHost) botDelay() - session.chooseName(displayName) + session.chooseName(displayName, Icon("desktop")) botDelay() session.joinGame(gameId) botDelay() diff --git a/sw-client/src/commonMain/kotlin/org/luxons/sevenwonders/client/SevenWondersClient.kt b/sw-client/src/commonMain/kotlin/org/luxons/sevenwonders/client/SevenWondersClient.kt index 3dca33c1..ce0ef1fd 100644 --- a/sw-client/src/commonMain/kotlin/org/luxons/sevenwonders/client/SevenWondersClient.kt +++ b/sw-client/src/commonMain/kotlin/org/luxons/sevenwonders/client/SevenWondersClient.kt @@ -22,13 +22,7 @@ import org.luxons.sevenwonders.model.PlayerTurnInfo import org.luxons.sevenwonders.model.api.ConnectedPlayer import org.luxons.sevenwonders.model.api.LobbyDTO import org.luxons.sevenwonders.model.api.SEVEN_WONDERS_WS_ENDPOINT -import org.luxons.sevenwonders.model.api.actions.AddBotAction -import org.luxons.sevenwonders.model.api.actions.ChooseNameAction -import org.luxons.sevenwonders.model.api.actions.CreateGameAction -import org.luxons.sevenwonders.model.api.actions.JoinGameAction -import org.luxons.sevenwonders.model.api.actions.PrepareMoveAction -import org.luxons.sevenwonders.model.api.actions.ReorderPlayersAction -import org.luxons.sevenwonders.model.api.actions.UpdateSettingsAction +import org.luxons.sevenwonders.model.api.actions.* import org.luxons.sevenwonders.model.api.errors.ErrorDTO import org.luxons.sevenwonders.model.cards.PreparedCard @@ -63,10 +57,10 @@ class SevenWondersSession(private val stompSession: StompSessionWithKxSerializat fun watchErrors(): Flow = stompSession.subscribe("/user/queue/errors", ErrorDTO.serializer()) - suspend fun chooseName(displayName: String): ConnectedPlayer = stompSession.request( + suspend fun chooseName(displayName: String, icon: Icon? = null): ConnectedPlayer = stompSession.request( sendDestination = "/app/chooseName", receiveDestination = "/user/queue/nameChoice", - payload = ChooseNameAction(displayName), + payload = ChooseNameAction(displayName, icon), serializer = ChooseNameAction.serializer(), deserializer = ConnectedPlayer.serializer() ) 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 7fe266b9..7a337f9a 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 @@ -1,6 +1,7 @@ package org.luxons.sevenwonders.model.api import kotlinx.serialization.Serializable +import org.luxons.sevenwonders.model.api.actions.Icon const val SEVEN_WONDERS_WS_ENDPOINT = "/seven-wonders-websocket" @@ -46,13 +47,15 @@ data class Actionability( @Serializable data class ConnectedPlayer( val username: String, - val displayName: String + val displayName: String, + val icon: Icon? ) @Serializable data class PlayerDTO( val username: String, val displayName: String, + val icon: Icon?, val index: Int, val isGameOwner: Boolean, val isReady: Boolean diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt index a4467667..0687e968 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/actions/Actions.kt @@ -12,7 +12,16 @@ class ChooseNameAction( /** * The display name of the player. May contain spaces and special characters. */ - val playerName: String + val playerName: String, + /** + * The player's icon. + */ + val icon: Icon? +) + +@Serializable +data class Icon( + val name: String ) /** 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 1386c855..6ef13b8e 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 @@ -15,4 +15,4 @@ fun Lobby.toDTO(): LobbyDTO = LobbyDTO( maxPlayersReached = maxPlayersReached() ) -fun Player.toDTO() = PlayerDTO(username, displayName, index, isGameOwner, isReady) +fun Player.toDTO() = PlayerDTO(username, displayName, icon, index, isGameOwner, isReady) diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/HomeController.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/HomeController.kt index c2619f8c..ff668fd9 100644 --- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/HomeController.kt +++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/HomeController.kt @@ -34,10 +34,10 @@ class HomeController @Autowired constructor( @SendToUser("/queue/nameChoice") fun chooseName(@Validated action: ChooseNameAction, principal: Principal): ConnectedPlayer { val username = principal.name - val player = playerRepository.createOrUpdate(username, action.playerName) + val player = playerRepository.createOrUpdate(username, action.playerName, action.icon) logger.info("Player '{}' chose the name '{}'", username, player.displayName) - return ConnectedPlayer(username, player.displayName) + return ConnectedPlayer(username, player.displayName, player.icon) } companion object { diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Player.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Player.kt index 8ed7d048..95b37643 100644 --- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Player.kt +++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/lobby/Player.kt @@ -1,11 +1,13 @@ package org.luxons.sevenwonders.server.lobby import org.luxons.sevenwonders.engine.Game +import org.luxons.sevenwonders.model.api.actions.Icon import org.luxons.sevenwonders.server.ApiMisuseException class Player( val username: String, - var displayName: String + var displayName: String, + var icon: Icon? = null ) { var index: Int = -1 diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/repositories/PlayerRepository.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/repositories/PlayerRepository.kt index b31d2cee..e76bdaea 100644 --- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/repositories/PlayerRepository.kt +++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/repositories/PlayerRepository.kt @@ -1,5 +1,6 @@ package org.luxons.sevenwonders.server.repositories +import org.luxons.sevenwonders.model.api.actions.Icon import org.luxons.sevenwonders.server.ApiMisuseException import org.luxons.sevenwonders.server.lobby.Player import org.springframework.stereotype.Repository @@ -12,9 +13,10 @@ class PlayerRepository { operator fun contains(username: String): Boolean = players.containsKey(username) - fun createOrUpdate(username: String, displayName: String): Player { - val p = players.computeIfAbsent(username) { Player(username, displayName) } + fun createOrUpdate(username: String, displayName: String, icon: Icon? = null): Player { + val p = players.computeIfAbsent(username) { Player(username, displayName, icon) } p.displayName = displayName + p.icon = icon return p } diff --git a/sw-server/src/test/kotlin/org/luxons/sevenwonders/server/controllers/HomeControllerTest.kt b/sw-server/src/test/kotlin/org/luxons/sevenwonders/server/controllers/HomeControllerTest.kt index 31b957e4..d7206490 100644 --- a/sw-server/src/test/kotlin/org/luxons/sevenwonders/server/controllers/HomeControllerTest.kt +++ b/sw-server/src/test/kotlin/org/luxons/sevenwonders/server/controllers/HomeControllerTest.kt @@ -2,6 +2,7 @@ package org.luxons.sevenwonders.server.controllers import org.junit.Test import org.luxons.sevenwonders.model.api.actions.ChooseNameAction +import org.luxons.sevenwonders.model.api.actions.Icon import org.luxons.sevenwonders.server.repositories.PlayerRepository import kotlin.test.assertEquals @@ -12,12 +13,13 @@ class HomeControllerTest { val playerRepository = PlayerRepository() val homeController = HomeController(playerRepository) - val action = ChooseNameAction("Test User") + val action = ChooseNameAction("Test User", Icon("person")) val principal = TestPrincipal("testuser") val player = homeController.chooseName(action, principal) assertEquals("testuser", player.username) assertEquals("Test User", player.displayName) + assertEquals("person", player.icon?.name) } } diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt index 0c1a5570..60962927 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt @@ -1,10 +1,10 @@ package org.luxons.sevenwonders.ui.components.lobby -import com.palantir.blueprintjs.IconName import com.palantir.blueprintjs.Intent import com.palantir.blueprintjs.bpIcon import kotlinx.css.* import org.luxons.sevenwonders.model.api.PlayerDTO +import org.luxons.sevenwonders.model.api.actions.Icon import react.RBuilder import react.ReactElement import react.dom.* @@ -67,7 +67,11 @@ private fun RBuilder.playerItem(player: PlayerDTO, isMe: Boolean): ReactElement alignItems = Align.center } val title = if (player.isGameOwner) "Game owner" else null - userIcon(isMe = isMe, isOwner = player.isGameOwner, title = title) + val icon = player.icon ?: when { + player.isGameOwner -> Icon("badge") + else -> Icon("user") + } + userIcon(isMe = isMe, icon = icon, title = title) styledH5 { css { margin = "0" @@ -83,7 +87,7 @@ private fun RBuilder.playerPlaceholder(): ReactElement = styledDiv { alignItems = Align.center opacity = 0.3 } - userIcon(isMe = false, isOwner = false, title = "Waiting for player...") + userIcon(isMe = false, icon = Icon("user"), title = "Waiting for player...") styledH5 { css { margin = "0" @@ -92,8 +96,7 @@ private fun RBuilder.playerPlaceholder(): ReactElement = styledDiv { } } -private fun RBuilder.userIcon(isMe: Boolean, isOwner: Boolean, title: String?): ReactElement { - val iconName: IconName = if (isOwner) "badge" else "user" +private fun RBuilder.userIcon(isMe: Boolean, icon: Icon, title: String?): ReactElement { val intent: Intent = if (isMe) Intent.WARNING else Intent.NONE - return bpIcon(name = iconName, intent = intent, size = 50, title = title) + return bpIcon(name = icon.name, intent = intent, size = 50, title = title) } diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt index 36c0848e..45cc474b 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt @@ -30,7 +30,7 @@ suspend fun SwSagaContext.rootSaga() = coroutineScope { serverErrorSaga(session) } - val player = session.chooseName(action.playerName) + val player = session.chooseName(action.playerName, null) dispatch(SetCurrentPlayerAction(player)) routerSaga(Route.GAME_BROWSER) { -- cgit