diff options
10 files changed, 305 insertions, 93 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 8ceae2c2..e3d54314 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 @@ -73,7 +73,9 @@ private fun createPlayCardMove(turnInfo: PlayerTurnInfo): PlayerMove { val transactions = wonderBuildability.cheapestTransactions.random() return PlayerMove(MoveType.UPGRADE_WONDER, hand.random().name, transactions) } - val playableCard = hand.filter { it.playability.isPlayable }.randomOrNull() + val playableCard = hand + .filter { it.playability.isPlayable } + .randomOrNull() return if (playableCard != null) { PlayerMove(MoveType.PLAY, playableCard.name, playableCard.playability.cheapestTransactions.random()) } else { diff --git a/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt index b74e984d..0bd126fd 100644 --- a/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt +++ b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt @@ -1,13 +1,12 @@ package com.palantir.blueprintjs -import kotlinext.js.js import org.w3c.dom.events.Event import org.w3c.dom.events.MouseEvent import react.RBuilder import react.RHandler import react.ReactElement import react.buildElement -import react.dom.* +import react.dom.h2 typealias IconName = String diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt index fbd6d8c5..bab6fe81 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt @@ -1,38 +1,18 @@ package org.luxons.sevenwonders.ui.components.game -import com.palantir.blueprintjs.Elevation -import com.palantir.blueprintjs.Intent -import com.palantir.blueprintjs.bpButton -import com.palantir.blueprintjs.bpButtonGroup -import com.palantir.blueprintjs.bpCallout -import com.palantir.blueprintjs.bpCard -import com.palantir.blueprintjs.bpNonIdealState -import com.palantir.blueprintjs.bpOverlay +import com.palantir.blueprintjs.* import kotlinx.css.* -import kotlinx.css.properties.* +import kotlinx.css.properties.transform +import kotlinx.css.properties.translate 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.* import org.luxons.sevenwonders.model.api.PlayerDTO import org.luxons.sevenwonders.model.boards.Board import org.luxons.sevenwonders.model.boards.RelativeBoardPosition import org.luxons.sevenwonders.model.cards.HandCard -import org.luxons.sevenwonders.model.getBoard -import org.luxons.sevenwonders.model.getOwnBoard import org.luxons.sevenwonders.ui.components.GlobalStyles -import org.luxons.sevenwonders.ui.redux.GameState -import org.luxons.sevenwonders.ui.redux.RequestLeaveGame -import org.luxons.sevenwonders.ui.redux.RequestPrepareMove -import org.luxons.sevenwonders.ui.redux.RequestSayReady -import org.luxons.sevenwonders.ui.redux.RequestUnprepareMove -import org.luxons.sevenwonders.ui.redux.connectStateAndDispatch -import react.RBuilder -import react.RClass -import react.RComponent -import react.RProps -import react.RState -import react.ReactElement +import org.luxons.sevenwonders.ui.redux.* +import react.* import styled.StyledDOMBuilder import styled.css import styled.getClassName @@ -50,6 +30,8 @@ interface GameSceneDispatchProps : RProps { var sayReady: () -> Unit var prepareMove: (move: PlayerMove) -> Unit var unprepareMove: () -> Unit + var startTransactionsSelection: (TransactionSelectorState) -> Unit + var cancelTransactionsSelection: () -> Unit var leaveGame: () -> Unit } @@ -92,9 +74,14 @@ private class GameScene(props: GameSceneProps) : RComponent<GameSceneProps, RSta height = 100.pct } } + transactionsSelectorDialog( + state = props.gameState?.transactionSelector, + prepareMove = props.prepareMove, + cancelTransactionSelection = props.cancelTransactionsSelection, + ) boardSummaries(leftBoard, rightBoard, topBoards) handRotationIndicator(turnInfo.table.handRotationDirection) - handCards(turnInfo, props.preparedMove, props.prepareMove) + handCards(turnInfo, props.preparedMove, props.prepareMove, props.startTransactionsSelection) val card = props.preparedCard val move = props.preparedMove if (card != null && move != null) { @@ -235,6 +222,8 @@ private val gameScene: RClass<GameSceneProps> = mapDispatchToProps = { dispatch, _ -> prepareMove = { move -> dispatch(RequestPrepareMove(move)) } unprepareMove = { dispatch(RequestUnprepareMove()) } + startTransactionsSelection = { selector -> dispatch(StartTransactionSelection(selector)) } + cancelTransactionsSelection = { dispatch(CancelTransactionSelection) } sayReady = { dispatch(RequestSayReady()) } leaveGame = { dispatch(RequestLeaveGame()) } }, diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt index b2e12dab..e69bc671 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt @@ -6,8 +6,10 @@ import styled.StyleSheet object GameStyles : StyleSheet("GameStyles", isStatic = true) { + private val sandColor = Color.paleGoldenrod.withAlpha(0.7) + val fullBoardPreviewPopover by css { - val bgColor = Color.paleGoldenrod.withAlpha(0.7) + val bgColor = sandColor backgroundColor = bgColor borderRadius = 0.5.rem padding(all = 0.5.rem) @@ -35,6 +37,14 @@ object GameStyles : StyleSheet("GameStyles", isStatic = true) { filter = "brightness(60%) grayscale(50%)" } + val transactionsSelector by css { + backgroundColor = sandColor + + children(".bp3-dialog-header") { + background = "none" // overrides default white background + } + } + val discardMoveText by css { display = Display.flex alignItems = Align.center diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt index c8fb8d61..373ad0f1 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt @@ -1,28 +1,16 @@ package org.luxons.sevenwonders.ui.components.game -import com.palantir.blueprintjs.IButtonGroupProps -import com.palantir.blueprintjs.IButtonProps -import com.palantir.blueprintjs.IconName -import com.palantir.blueprintjs.Intent -import com.palantir.blueprintjs.bpButton -import com.palantir.blueprintjs.bpButtonGroup -import com.palantir.blueprintjs.bpIcon +import com.palantir.blueprintjs.* import kotlinx.css.* import kotlinx.css.properties.* import kotlinx.html.DIV -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.* import org.luxons.sevenwonders.model.cards.CardPlayability import org.luxons.sevenwonders.model.cards.HandCard -import org.luxons.sevenwonders.model.getOwnBoard +import org.luxons.sevenwonders.model.resources.PricedResourceTransactions import org.luxons.sevenwonders.model.wonders.WonderBuildability -import react.RBuilder -import react.RComponent -import react.RElementBuilder -import react.RProps -import react.RState +import org.luxons.sevenwonders.ui.redux.TransactionSelectorState +import react.* import styled.StyledDOMBuilder import styled.css import styled.styledDiv @@ -43,6 +31,7 @@ interface HandProps : RProps { var turnInfo: PlayerTurnInfo var preparedMove: PlayerMove? var prepareMove: (PlayerMove) -> Unit + var startTransactionsSelection: (TransactionSelectorState) -> Unit } class HandComponent(props: HandProps) : RComponent<HandProps, RState>(props) { @@ -131,10 +120,7 @@ class HandComponent(props: HandProps) : RComponent<HandProps, RState>(props) { large = true, intent = Intent.SUCCESS, disabled = !card.playability.isPlayable, - onClick = { - val transactions = card.playability.cheapestTransactions.first() - props.prepareMove(PlayerMove(handAction.moveType, card.name, transactions)) - }, + onClick = { prepareMove(handAction.moveType, card, card.playability.cheapestTransactions) }, ) { bpIcon(handAction.icon) if (card.playability.isPlayable && !card.playability.isFree) { @@ -150,10 +136,7 @@ class HandComponent(props: HandProps) : RComponent<HandProps, RState>(props) { large = true, intent = Intent.PRIMARY, disabled = !wonderBuildability.isBuildable, - onClick = { - val transactions = wonderBuildability.cheapestTransactions.first() - props.prepareMove(PlayerMove(MoveType.UPGRADE_WONDER, card.name, transactions)) - }, + onClick = { prepareMove(MoveType.UPGRADE_WONDER, card, wonderBuildability.cheapestTransactions) }, ) { bpIcon("key-shift") if (wonderBuildability.isBuildable && !wonderBuildability.isFree) { @@ -162,6 +145,13 @@ class HandComponent(props: HandProps) : RComponent<HandProps, RState>(props) { } } + private fun prepareMove(moveType: MoveType, card: HandCard, transactions: Set<PricedResourceTransactions>) { + when (transactions.size) { + 1 -> props.prepareMove(PlayerMove(moveType, card.name, transactions.first())) + else -> props.startTransactionsSelection(TransactionSelectorState(moveType, card, transactions)) + } + } + private fun RElementBuilder<IButtonGroupProps>.discardButton(card: HandCard) { bpButton( title = "DISCARD (+3 coins)", // TODO remove hardcoded value @@ -266,12 +256,14 @@ fun RBuilder.handCards( turnInfo: PlayerTurnInfo, preparedMove: PlayerMove?, prepareMove: (PlayerMove) -> Unit, + startTransactionsSelection: (TransactionSelectorState) -> Unit, ) { child(HandComponent::class) { attrs { this.turnInfo = turnInfo this.preparedMove = preparedMove this.prepareMove = prepareMove + this.startTransactionsSelection = startTransactionsSelection } } } diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ProductionBar.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ProductionBar.kt index 507883e7..c3cd9911 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ProductionBar.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ProductionBar.kt @@ -1,35 +1,14 @@ package org.luxons.sevenwonders.ui.components.game -import kotlinx.css.Align -import kotlinx.css.BorderStyle -import kotlinx.css.CSSBuilder -import kotlinx.css.Color -import kotlinx.css.Display -import kotlinx.css.Position -import kotlinx.css.VerticalAlign -import kotlinx.css.alignItems -import kotlinx.css.background -import kotlinx.css.bottom -import kotlinx.css.color -import kotlinx.css.display -import kotlinx.css.fontSize -import kotlinx.css.height -import kotlinx.css.margin -import kotlinx.css.marginLeft -import kotlinx.css.position -import kotlinx.css.properties.* -import kotlinx.css.px -import kotlinx.css.rem -import kotlinx.css.verticalAlign -import kotlinx.css.vw -import kotlinx.css.width -import kotlinx.css.zIndex +import kotlinx.css.* +import kotlinx.css.properties.borderTop +import kotlinx.css.properties.boxShadow import kotlinx.html.DIV import org.luxons.sevenwonders.model.boards.Production import org.luxons.sevenwonders.model.resources.CountedResource import org.luxons.sevenwonders.model.resources.ResourceType import react.RBuilder -import react.dom.* +import react.dom.key import styled.StyledDOMBuilder import styled.css import styled.styledDiv @@ -53,7 +32,7 @@ private fun RBuilder.fixedResources(resources: List<CountedResource>) { display = Display.flex } resources.forEach { - tokenWithCount(tokenName = getResourceTokenName(it.type), count = it.count, imgSize = 3.rem) { + resourceWithCount(resourceType = it.type, count = it.count, imgSize = 3.rem) { attrs { key = it.type.toString() } css { marginLeft = 1.rem } } @@ -84,7 +63,7 @@ private fun RBuilder.resourceChoice(types: Set<ResourceType>, block: StyledDOMBu } block() for ((i, t) in types.withIndex()) { - tokenImage(tokenName = getResourceTokenName(t), size = 3.rem) { + resourceImage(resourceType = t, size = 3.rem) { attrs { this.key = t.toString() } } if (i < types.indices.last) { @@ -97,8 +76,6 @@ private fun RBuilder.resourceChoice(types: Set<ResourceType>, block: StyledDOMBu } } -private fun getResourceTokenName(resourceType: ResourceType) = "resources/${resourceType.toString().toLowerCase()}" - private fun CSSBuilder.productionBarStyle() { alignItems = Align.center background = "linear-gradient(#eaeaea, #888 7%)" diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Tokens.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Tokens.kt index 74dc232e..846a9f07 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Tokens.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Tokens.kt @@ -4,13 +4,14 @@ import kotlinx.css.* import kotlinx.html.DIV import kotlinx.html.IMG import kotlinx.html.title +import org.luxons.sevenwonders.model.resources.ResourceType import org.luxons.sevenwonders.ui.components.GlobalStyles import react.RBuilder -import styled.StyledDOMBuilder -import styled.css -import styled.styledDiv -import styled.styledImg -import styled.styledSpan +import styled.* + +private fun getResourceTokenName(resourceType: ResourceType) = "resources/${resourceType.toString().toLowerCase()}" + +private fun getTokenImagePath(tokenName: String) = "/images/tokens/$tokenName.png" enum class TokenCountPosition { LEFT, @@ -36,6 +37,37 @@ fun RBuilder.goldIndicator( ) } +fun RBuilder.resourceWithCount( + resourceType: ResourceType, + count: Int, + title: String = resourceType.toString(), + imgSize: LinearDimension? = null, + countPosition: TokenCountPosition = TokenCountPosition.RIGHT, + brightText: Boolean = false, + customCountStyle: CSSBuilder.() -> Unit = {}, + block: StyledDOMBuilder<DIV>.() -> Unit = {}, +) { + tokenWithCount( + tokenName = getResourceTokenName(resourceType), + count = count, + title = title, + imgSize = imgSize, + countPosition = countPosition, + brightText = brightText, + customCountStyle = customCountStyle, + block = block + ) +} + +fun RBuilder.resourceImage( + resourceType: ResourceType, + title: String = resourceType.toString(), + size: LinearDimension?, + block: StyledDOMBuilder<IMG>.() -> Unit = {}, +) { + tokenImage(getResourceTokenName(resourceType), title, size, block) +} + fun RBuilder.tokenWithCount( tokenName: String, count: Int, @@ -72,7 +104,11 @@ fun RBuilder.tokenWithCount( } TokenCountPosition.OVER -> { styledDiv { - css { position = Position.relative } + css { + position = Position.relative + // if container becomes large, this one stays small so that children stay on top of each other + width = LinearDimension.fitContent + } tokenImage(tokenName, title = title, size = imgSize) styledSpan { css { @@ -109,8 +145,6 @@ fun RBuilder.tokenImage( } } -private fun getTokenImagePath(tokenName: String) = "/images/tokens/$tokenName.png" - private fun CSSBuilder.tokenCountStyle( size: LinearDimension, brightText: Boolean, diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/TransactionsSelector.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/TransactionsSelector.kt new file mode 100644 index 00000000..e8b6cf8c --- /dev/null +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/TransactionsSelector.kt @@ -0,0 +1,193 @@ +package org.luxons.sevenwonders.ui.components.game + +import com.palantir.blueprintjs.* +import kotlinx.css.* +import kotlinx.html.DIV +import kotlinx.html.TD +import kotlinx.html.classes +import kotlinx.html.js.onClickFunction +import org.luxons.sevenwonders.model.PlayerMove +import org.luxons.sevenwonders.model.resources.CountedResource +import org.luxons.sevenwonders.model.resources.Provider +import org.luxons.sevenwonders.model.resources.ResourceType +import org.luxons.sevenwonders.ui.redux.TransactionSelectorState +import react.RBuilder +import react.dom.div +import react.dom.p +import react.dom.tbody +import styled.* + +fun RBuilder.transactionsSelectorDialog( + state: TransactionSelectorState?, + prepareMove: (PlayerMove) -> Unit, + cancelTransactionSelection: () -> Unit, +) { + bpDialog( + isOpen = state != null, + title = "Time to foot the bill!", + canEscapeKeyClose = true, + canOutsideClickClose = true, + isCloseButtonShown = true, + onClose = cancelTransactionSelection, + ) { + attrs { + className = GameStyles.getClassName { it::transactionsSelector } + } + div { + attrs { + classes += Classes.DIALOG_BODY + } + p { + +"You don't have enough resources to perform this move, but you can buy them from neighbours. " + +"Please pick an option:" + } + if (state != null) { // should always be true when the dialog is rendered + styledDiv { + css { + margin(all = LinearDimension.auto) + display = Display.flex + alignItems = Align.center + } + bpIcon("user", size = 50) + styledDiv { + css { + grow(Grow.GROW) + margin(horizontal = 0.5.rem) + } + optionsTable(state, prepareMove) + } + bpIcon("user", size = 50) + } + } + } + } +} + +private fun RBuilder.optionsTable( + state: TransactionSelectorState, + prepareMove: (PlayerMove) -> Unit, +) { + bpHtmlTable(interactive = true) { + tbody { + state.transactionsOptions.forEach { transactions -> + styledTr { + css { + cursor = Cursor.pointer + alignItems = Align.center + } + attrs { + onClickFunction = { prepareMove(PlayerMove(state.moveType, state.card.name, transactions)) } + } + // there should be at most one of each + val left = transactions.firstOrNull { it.provider == Provider.LEFT_PLAYER } + val right = transactions.firstOrNull { it.provider == Provider.RIGHT_PLAYER } + styledTd { + transactionCellCss() + if (left != null) { + styledDiv { + transactionCellInnerCss() + bpIcon(name = left.provider.arrowIcon(), size = Icon.SIZE_LARGE) + goldIndicator(left.totalPrice, imgSize = 2.rem) + } + } + } + styledTd { + transactionCellCss() + if (left != null) { + styledDiv { + transactionCellInnerCss() + resourceList(left.resources) + } + } + } + styledTd { + transactionCellCss() + css { + // make this cell fill the space + width = 100.pct + } +// goldIndicator(-transactions.sumBy { it.totalPrice }) { +// css { +// width = LinearDimension.fitContent +// margin(horizontal = LinearDimension.auto) +// } +// } + } + styledTd { + transactionCellCss() + if (right != null) { + styledDiv { + transactionCellInnerCss() + resourceList(right.resources) + } + } + } + styledTd { + transactionCellCss() + if (right != null) { + styledDiv { + transactionCellInnerCss() + goldIndicator(right.totalPrice, imgSize = 2.rem) + bpIcon(name = right.provider.arrowIcon(), size = Icon.SIZE_LARGE) + } + } + } + } + } + } + } +} + +private fun StyledDOMBuilder<TD>.transactionCellCss() { + // we need inline styles to win over blueprintjs's styles (which are more specific than .class) + inlineStyles { + verticalAlign = VerticalAlign.middle + } +} + +private fun StyledDOMBuilder<DIV>.transactionCellInnerCss() { + css { + display = Display.flex + flexDirection = FlexDirection.row + alignItems = Align.center + } +} + +private fun Provider.arrowIcon() = when (this) { + Provider.LEFT_PLAYER -> "caret-left" + Provider.RIGHT_PLAYER -> "caret-right" +} + +private fun RBuilder.resourceList(resources: List<CountedResource>) { + // The biggest card is the Palace and requires 7 resources (1 of each). + // We always have at least 1 resource on our wonder, so we'll never need to buy more than 6. + // Therefore, 3 by row seems decent. + val rows = resources.toRepeatedTypesList().chunked(3) + styledDiv { + css { + display = Display.flex + flexDirection = FlexDirection.column + alignItems = Align.center + grow(Grow.GROW) + } + rows.forEach { row -> + styledDiv { + resourceRowCss() + row.forEach { + resourceImage(it, size = 1.5.rem) + } + } + } + } +} + +private fun StyledDOMBuilder<DIV>.resourceRowCss() { + css { + display = Display.flex + flexDirection = FlexDirection.row + alignItems = Align.center + margin(horizontal = LinearDimension.auto) + } +} + +private fun List<CountedResource>.toRepeatedTypesList(): List<ResourceType> = flatMap { cr -> List(cr.count) { cr.type } } diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt index bacf6795..951f4f2a 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt @@ -19,6 +19,10 @@ data class EnterGameAction(val lobby: LobbyDTO, val turnInfo: PlayerTurnInfo) : data class TurnInfoEvent(val turnInfo: PlayerTurnInfo) : RAction +data class StartTransactionSelection(val transactionSelector: TransactionSelectorState) : RAction + +object CancelTransactionSelection : RAction + data class PreparedMoveEvent(val move: PlayerMove) : RAction data class PreparedCardEvent(val card: PreparedCard) : RAction diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt index 97d00ab7..ef1f0362 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt @@ -1,5 +1,6 @@ package org.luxons.sevenwonders.ui.redux +import org.luxons.sevenwonders.model.MoveType import org.luxons.sevenwonders.model.PlayerMove import org.luxons.sevenwonders.model.PlayerTurnInfo import org.luxons.sevenwonders.model.api.ConnectedPlayer @@ -8,6 +9,7 @@ import org.luxons.sevenwonders.model.api.PlayerDTO import org.luxons.sevenwonders.model.api.State import org.luxons.sevenwonders.model.cards.CardBack import org.luxons.sevenwonders.model.cards.HandCard +import org.luxons.sevenwonders.model.resources.PricedResourceTransactions import redux.RAction data class SwState( @@ -29,11 +31,18 @@ data class GameState( val turnInfo: PlayerTurnInfo?, val preparedCardsByUsername: Map<String, CardBack?> = emptyMap(), val currentPreparedMove: PlayerMove? = null, + val transactionSelector: TransactionSelectorState? = null, ) { val currentPreparedCard: HandCard? get() = turnInfo?.hand?.firstOrNull { it.name == currentPreparedMove?.cardName } } +data class TransactionSelectorState( + val moveType: MoveType, + val card: HandCard, + val transactionsOptions: Set<PricedResourceTransactions>, +) + fun rootReducer(state: SwState, action: RAction): SwState = state.copy( gamesById = gamesReducer(state.gamesById, action), connectedPlayer = currentPlayerReducer(state.connectedPlayer, action), @@ -81,5 +90,8 @@ private fun gameStateReducer(gameState: GameState?, action: RAction): GameState? turnInfo = action.turnInfo, currentPreparedMove = null, ) + is StartTransactionSelection -> gameState?.copy(transactionSelector = action.transactionSelector) + is CancelTransactionSelection -> gameState?.copy(transactionSelector = null) + is RequestPrepareMove -> gameState?.copy(transactionSelector = null) else -> gameState } |