summaryrefslogtreecommitdiff
path: root/sw-ui-kt/src
diff options
context:
space:
mode:
Diffstat (limited to 'sw-ui-kt/src')
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt72
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt3
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt25
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameSagas.kt3
4 files changed, 70 insertions, 33 deletions
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<PlayerDTO>
var turnInfo: PlayerTurnInfo?
}
@@ -55,45 +65,76 @@ private class GameScene(props: GameSceneProps) : RComponent<GameSceneProps, RSta
}
val turnInfo = props.turnInfo
if (turnInfo == null) {
- gamePreStart(props.sayReady)
+ gamePreStart()
} else {
turnInfoScene(turnInfo)
}
}
}
- private fun RBuilder.gamePreStart(onReadyClicked: () -> Unit) {
+ private fun RBuilder.gamePreStart() {
bpNonIdealState(
description = createElement {
p { +"Click 'ready' when you are"}
},
action = createElement {
+ sayReadyButton()
+ }
+ )
+ }
+
+ private fun RBuilder.sayReadyButton(block: StyledDOMBuilder<DIV>.() -> 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<GameSceneProps> = connectStateAndDispatch<GameScen
sayReady = { dispatch(RequestSayReady()) }
},
mapStateToProps = { state, _ ->
+ 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<Long, LobbyDTO> = emptyMap(),
val currentPlayerUsername: String? = null,
val currentLobbyId: Long? = null,
- val currentTurnInfo: PlayerTurnInfo? = null,
- val currentTable: GameState? = null
+ val currentTurnInfo: PlayerTurnInfo? = null
) {
val games: List<LobbyDTO> = 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<String, PlayerDTO>, action: RAction): Map<String, PlayerDTO> = 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<Long, LobbyDTO>, action: RAction): Map<Long,
is UpdateGameListAction -> 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<RequestSayReady> { session.sayReady() } }
val prepareMoveJob = launch { onEach<RequestPrepareMove> { 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
bgstack15