From 78aff48d30f7943a720c2d0714d5fe304685c29b Mon Sep 17 00:00:00 2001 From: Joffrey Bion Date: Sat, 28 Mar 2020 23:00:18 +0100 Subject: Improve state updates for turn info --- .../sevenwonders/ui/components/game/GameScene.kt | 72 +++++++++++++++++----- .../org/luxons/sevenwonders/ui/redux/Actions.kt | 3 - .../org/luxons/sevenwonders/ui/redux/Reducers.kt | 25 ++++---- .../sevenwonders/ui/redux/sagas/GameSagas.kt | 3 - 4 files changed, 70 insertions(+), 33 deletions(-) (limited to 'sw-ui-kt/src') diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt index 11ce09c1..d9de85d9 100644 --- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt +++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt @@ -2,6 +2,7 @@ package org.luxons.sevenwonders.ui.components.game import com.palantir.blueprintjs.Intent import com.palantir.blueprintjs.bpButton +import com.palantir.blueprintjs.bpButtonGroup import com.palantir.blueprintjs.bpNonIdealState import com.palantir.blueprintjs.org.luxons.sevenwonders.ui.components.game.handComponent import kotlinx.css.CSSBuilder @@ -12,10 +13,16 @@ import kotlinx.css.backgroundSize import kotlinx.css.bottom import kotlinx.css.left import kotlinx.css.overflow +import kotlinx.css.pct import kotlinx.css.position +import kotlinx.css.properties.transform +import kotlinx.css.properties.translate import kotlinx.css.px +import kotlinx.css.rem import kotlinx.css.right import kotlinx.css.top +import kotlinx.html.DIV +import org.luxons.sevenwonders.model.Action import org.luxons.sevenwonders.model.PlayerMove import org.luxons.sevenwonders.model.PlayerTurnInfo import org.luxons.sevenwonders.model.api.PlayerDTO @@ -28,11 +35,14 @@ import react.RClass import react.RComponent import react.RProps import react.RState +import react.ReactElement import react.dom.* +import styled.StyledDOMBuilder import styled.css import styled.styledDiv interface GameSceneStateProps: RProps { + var playerIsReady: Boolean var players: List var turnInfo: PlayerTurnInfo? } @@ -55,45 +65,76 @@ private class GameScene(props: GameSceneProps) : RComponent Unit) { + private fun RBuilder.gamePreStart() { bpNonIdealState( description = createElement { p { +"Click 'ready' when you are"} }, action = createElement { + sayReadyButton() + } + ) + } + + private fun RBuilder.sayReadyButton(block: StyledDOMBuilder
.() -> Unit = {}): ReactElement { + val isReady = props.playerIsReady + val intent = if (isReady) Intent.SUCCESS else Intent.PRIMARY + return styledDiv { + bpButtonGroup { bpButton( large = true, - intent = Intent.PRIMARY, - icon = "play", - onClick = { onReadyClicked() } + disabled = isReady, + intent = intent, + icon = if (isReady) "tick-circle" else "play", + onClick = { props.sayReady() } ) { +"READY" } + bpButton( + large = true, + icon = "people", + disabled = isReady, + intent = intent + ) { + +"${props.players.count { it.isReady }}/${props.players.size}" + } } - ) + block() + } } private fun RBuilder.turnInfoScene(turnInfo: PlayerTurnInfo) { val board = turnInfo.table.boards[turnInfo.playerIndex] div { + // TODO use blueprint's Callout component without header and primary intent p { + turnInfo.message } boardComponent(board = board) - handComponent( - cards = turnInfo.hand, - wonderUpgradable = turnInfo.wonderBuildability.isBuildable, - prepareMove = props.prepareMove - ) - productionBar( - gold = board.gold, - production = board.production - ) + val hand = turnInfo.hand + if (hand != null) { + handComponent( + cards = hand, + wonderUpgradable = turnInfo.wonderBuildability.isBuildable, + prepareMove = props.prepareMove + ) + } + if (turnInfo.action == Action.SAY_READY) { + sayReadyButton { + css { + position = Position.absolute + bottom = 4.rem + left = 50.pct + transform { translate(tx = (-50).pct) } + } + } + } + productionBar(gold = board.gold, production = board.production) } } } @@ -108,6 +149,7 @@ private val gameScene: RClass = connectStateAndDispatch + playerIsReady = state.currentPlayer?.isReady == true players = state.currentLobby?.players ?: emptyList() turnInfo = state.currentTurnInfo } diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt index 223cd5c1..37238e0a 100644 --- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt +++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt @@ -1,6 +1,5 @@ package org.luxons.sevenwonders.ui.redux -import org.luxons.sevenwonders.model.GameState import org.luxons.sevenwonders.model.PlayerTurnInfo import org.luxons.sevenwonders.model.api.LobbyDTO import org.luxons.sevenwonders.model.api.PlayerDTO @@ -24,5 +23,3 @@ data class TurnInfoEvent(val turnInfo: PlayerTurnInfo): RAction data class PreparedCardEvent(val card: PreparedCard): RAction data class PlayerReadyEvent(val username: String): RAction - -data class TableUpdateEvent(val table: GameState): RAction diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt index 28bb7993..507a3941 100644 --- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt +++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt @@ -1,6 +1,5 @@ package org.luxons.sevenwonders.ui.redux -import org.luxons.sevenwonders.model.GameState import org.luxons.sevenwonders.model.PlayerTurnInfo import org.luxons.sevenwonders.model.api.LobbyDTO import org.luxons.sevenwonders.model.api.PlayerDTO @@ -11,8 +10,7 @@ data class SwState( val gamesById: Map = emptyMap(), val currentPlayerUsername: String? = null, val currentLobbyId: Long? = null, - val currentTurnInfo: PlayerTurnInfo? = null, - val currentTable: GameState? = null + val currentTurnInfo: PlayerTurnInfo? = null ) { val games: List = gamesById.values.toList() val currentLobby: LobbyDTO? = currentLobbyId?.let { gamesById[it] } @@ -24,14 +22,15 @@ fun rootReducer(state: SwState, action: RAction): SwState = state.copy( gamesById = gamesReducer(state.gamesById, action), currentPlayerUsername = currentPlayerReducer(state.currentPlayerUsername, action), currentLobbyId = currentLobbyReducer(state.currentLobbyId, action), - currentTurnInfo = currentTurnInfoReducer(state.currentTurnInfo, action), - currentTable = currentTableReducer(state.currentTable, action) + currentTurnInfo = currentTurnInfoReducer(state.currentTurnInfo, action) ) private fun playersReducer(playersByUsername: Map, action: RAction): Map = when (action) { is UpdatePlayers -> playersByUsername + action.players is UpdateLobbyAction -> playersByUsername + action.lobby.players.associateBy { it.username } is SetCurrentPlayerAction -> playersByUsername + (action.player.username to action.player) + is PlayerReadyEvent -> playersByUsername + (action.username to playersByUsername.getValue(action.username) + .copy(isReady = true)) else -> playersByUsername } @@ -39,6 +38,15 @@ private fun gamesReducer(games: Map, action: RAction): Map action.games.associateBy { it.id } // replaces because should remove deleted games is EnterLobbyAction -> games + (action.lobby.id to action.lobby) is UpdateLobbyAction -> games + (action.lobby.id to action.lobby) + is PlayerReadyEvent -> games.mapValues { (_, l) -> + if (l.players.any { it.username == action.username }) { + l.copy(players = l.players.map { p -> + if (p.username == action.username) p.copy(isReady = true) else p + }) + } else { + l + } + } else -> games } @@ -54,12 +62,5 @@ private fun currentLobbyReducer(currentLobbyId: Long?, action: RAction): Long? = private fun currentTurnInfoReducer(currentTurnInfo: PlayerTurnInfo?, action: RAction): PlayerTurnInfo? = when (action) { is TurnInfoEvent -> action.turnInfo - is TableUpdateEvent -> null else -> currentTurnInfo } - -private fun currentTableReducer(currentTable: GameState?, action: RAction): GameState? = when (action) { - is TurnInfoEvent -> action.turnInfo.table - is TableUpdateEvent -> action.table - else -> currentTable -} diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameSagas.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameSagas.kt index e3675799..cadf56e9 100644 --- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameSagas.kt +++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameSagas.kt @@ -7,7 +7,6 @@ import org.luxons.sevenwonders.ui.redux.PlayerReadyEvent import org.luxons.sevenwonders.ui.redux.PreparedCardEvent import org.luxons.sevenwonders.ui.redux.RequestPrepareMove import org.luxons.sevenwonders.ui.redux.RequestSayReady -import org.luxons.sevenwonders.ui.redux.TableUpdateEvent import org.luxons.sevenwonders.ui.redux.TurnInfoEvent suspend fun SwSagaContext.gameSaga(session: SevenWondersSession) { @@ -15,13 +14,11 @@ suspend fun SwSagaContext.gameSaga(session: SevenWondersSession) { coroutineScope { val playerReadySub = session.watchPlayerReady(lobby.id) val preparedCardsSub = session.watchPreparedCards(lobby.id) - val tableUpdatesSub = session.watchTableUpdates(lobby.id) val turnInfoSub = session.watchTurns() val sayReadyJob = launch { onEach { session.sayReady() } } val prepareMoveJob = launch { onEach { session.prepareMove(it.move) } } launch { dispatchAll(playerReadySub.messages) { PlayerReadyEvent(it) } } launch { dispatchAll(preparedCardsSub.messages) { PreparedCardEvent(it) } } - launch { dispatchAll(tableUpdatesSub.messages) { TableUpdateEvent(it) } } launch { dispatchAll(turnInfoSub.messages) { TurnInfoEvent(it) } } // TODO await game end // TODO unsubscribe all subs, cancel all jobs -- cgit