diff options
author | Joffrey Bion <joffrey.bion@gmail.com> | 2021-02-23 00:01:00 +0100 |
---|---|---|
committer | Joffrey Bion <joffrey.bion@gmail.com> | 2021-02-23 18:38:24 +0100 |
commit | e2957be6c0f2dea09d0633cd7ee7549311b9b923 (patch) | |
tree | 97b3dcbf09501ac2bd00d9ac8e0a1f1f280ecf0a | |
parent | Fix player re-order animation (diff) | |
download | seven-wonders-e2957be6c0f2dea09d0633cd7ee7549311b9b923.tar.gz seven-wonders-e2957be6c0f2dea09d0633cd7ee7549311b9b923.tar.bz2 seven-wonders-e2957be6c0f2dea09d0633cd7ee7549311b9b923.zip |
Funnel game events into a single client subscription
4 files changed, 69 insertions, 24 deletions
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 50b9b70c..d14b07b7 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 @@ -1,9 +1,10 @@ package org.luxons.sevenwonders.client -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.* import kotlinx.serialization.builtins.serializer import org.hildan.krossbow.stomp.StompClient import org.hildan.krossbow.stomp.config.HeartBeat @@ -19,7 +20,8 @@ import org.luxons.sevenwonders.model.Settings import org.luxons.sevenwonders.model.api.* import org.luxons.sevenwonders.model.api.actions.* import org.luxons.sevenwonders.model.api.errors.ErrorDTO -import org.luxons.sevenwonders.model.cards.PreparedCard +import org.luxons.sevenwonders.model.api.events.GameEvent +import org.luxons.sevenwonders.model.api.events.GameEventWrapper import org.luxons.sevenwonders.model.wonders.AssignedWonder class SevenWondersClient { @@ -121,22 +123,23 @@ class SevenWondersSession(private val stompSession: StompSessionWithKxSerializat stompSession.sendEmptyMsg("/app/lobby/startGame") } - suspend fun watchPlayerReady(gameId: Long): Flow<String> = - stompSession.subscribe("/topic/game/$gameId/playerReady", String.serializer()) + @OptIn(ExperimentalCoroutinesApi::class) + suspend fun watchGameEvents(gameId: Long): Flow<GameEvent> { + val private = watchPublicGameEvents() + val public = watchPrivateGameEvents(gameId) + return merge(private, public) + } - suspend fun watchPreparedCards(gameId: Long): Flow<PreparedCard> = - stompSession.subscribe("/topic/game/$gameId/prepared", PreparedCard.serializer()) + private suspend fun watchPrivateGameEvents(gameId: Long) = + stompSession.subscribe("/topic/game/$gameId/events", GameEventWrapper.serializer()).map { it.event } - suspend fun watchTurns(): Flow<PlayerTurnInfo> = - stompSession.subscribe("/user/queue/game/turn", PlayerTurnInfo.serializer()) + suspend fun watchPublicGameEvents() = + stompSession.subscribe("/user/queue/game/events", GameEventWrapper.serializer()).map { it.event } suspend fun sayReady() { stompSession.sendEmptyMsg("/app/game/sayReady") } - suspend fun watchOwnMoves(): Flow<PlayerMove> = - stompSession.subscribe("/user/queue/game/preparedMove", PlayerMove.serializer()) - suspend fun prepareMove(move: PlayerMove) { stompSession.convertAndSend( destination = "/app/game/prepareMove", @@ -187,3 +190,6 @@ private suspend fun <T> doAndWaitForEvent(send: suspend () -> Unit, subscribe: s send() deferredFirstEvent.await() } + +suspend fun SevenWondersSession.watchTurns() = + watchPublicGameEvents().filterIsInstance<GameEvent.NewTurnStarted>().map { it.turnInfo } diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/events/Events.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/events/Events.kt new file mode 100644 index 00000000..d8c05e91 --- /dev/null +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/api/events/Events.kt @@ -0,0 +1,30 @@ +package org.luxons.sevenwonders.model.api.events + +import kotlinx.serialization.Serializable +import org.luxons.sevenwonders.model.PlayerMove +import org.luxons.sevenwonders.model.PlayerTurnInfo +import org.luxons.sevenwonders.model.cards.PreparedCard + +// workaround for https://github.com/Kotlin/kotlinx.serialization/issues/1194 +@Serializable +data class GameEventWrapper( + val event: GameEvent +) + +fun GameEvent.wrap() = GameEventWrapper(this) + +@Serializable +sealed class GameEvent { + + @Serializable + data class NewTurnStarted(val turnInfo: PlayerTurnInfo) : GameEvent() + + @Serializable + data class MovePrepared(val move: PlayerMove) : GameEvent() + + @Serializable + data class CardPrepared(val preparedCard: PreparedCard) : GameEvent() + + @Serializable + data class PlayerIsReady(val username: String) : GameEvent() +} diff --git a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameController.kt b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameController.kt index e4c1b39a..70fb3220 100644 --- a/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameController.kt +++ b/sw-server/src/main/kotlin/org/luxons/sevenwonders/server/controllers/GameController.kt @@ -4,6 +4,8 @@ import io.micrometer.core.instrument.MeterRegistry import org.luxons.sevenwonders.engine.Game import org.luxons.sevenwonders.model.api.GameListEvent import org.luxons.sevenwonders.model.api.actions.PrepareMoveAction +import org.luxons.sevenwonders.model.api.events.GameEvent +import org.luxons.sevenwonders.model.api.events.wrap import org.luxons.sevenwonders.model.api.wrap import org.luxons.sevenwonders.model.cards.PreparedCard import org.luxons.sevenwonders.model.hideHandsAndWaitForReadiness @@ -102,7 +104,7 @@ class GameController( handleEndOfGame(game, player, lobby) } } else { - template.convertAndSendToUser(player.username, "/queue/game/preparedMove", action.move) + template.convertAndSendToUser(player.username, "/queue/game/events", GameEvent.MovePrepared(action.move).wrap()) } } } @@ -130,18 +132,20 @@ class GameController( } } - private fun sendPlayerReady(gameId: Long, player: Player) = - template.convertAndSend("/topic/game/$gameId/playerReady", player.username) + private fun sendPlayerReady(gameId: Long, player: Player) { + template.convertAndSend("/topic/game/$gameId/events", GameEvent.PlayerIsReady(player.username).wrap()) + } - private fun sendPreparedCard(gameId: Long, preparedCard: PreparedCard) = - template.convertAndSend("/topic/game/$gameId/prepared", preparedCard) + private fun sendPreparedCard(gameId: Long, preparedCard: PreparedCard) { + template.convertAndSend("/topic/game/$gameId/events", GameEvent.CardPrepared(preparedCard).wrap()) + } private fun sendTurnInfo(players: List<Player>, game: Game, hideHands: Boolean) { val turns = game.getCurrentTurnInfo() val turnsToSend = if (hideHands) turns.hideHandsAndWaitForReadiness() else turns for (turnInfo in turnsToSend) { val player = players[turnInfo.playerIndex] - template.convertAndSendToUser(player.username, "/queue/game/turn", turnInfo) + template.convertAndSendToUser(player.username, "/queue/game/events", GameEvent.NewTurnStarted(turnInfo).wrap()) } } diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/RouteBasedSagas.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/RouteBasedSagas.kt index 06b33e13..af2624ec 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/RouteBasedSagas.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/RouteBasedSagas.kt @@ -3,6 +3,7 @@ package org.luxons.sevenwonders.ui.redux.sagas import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.map import org.luxons.sevenwonders.client.SevenWondersSession +import org.luxons.sevenwonders.model.api.events.GameEvent import org.luxons.sevenwonders.ui.redux.* import org.luxons.sevenwonders.ui.router.Navigate import org.luxons.sevenwonders.ui.router.Route @@ -49,10 +50,14 @@ suspend fun SwSagaContext.lobbySaga(session: SevenWondersSession) { suspend fun SwSagaContext.gameSaga(session: SevenWondersSession) { val game = reduxState.gameState ?: error("Game saga run without a current game") coroutineScope { - session.watchPlayerReady(game.id).map { PlayerReadyEvent(it) }.dispatchAllIn(this) - session.watchPreparedCards(game.id).map { PreparedCardEvent(it) }.dispatchAllIn(this) - session.watchOwnMoves().map { PreparedMoveEvent(it) }.dispatchAllIn(this) - session.watchTurns().map { TurnInfoEvent(it) }.dispatchAllIn(this) + session.watchGameEvents(game.id).map { + when (it) { + is GameEvent.NewTurnStarted -> TurnInfoEvent(it.turnInfo) + is GameEvent.MovePrepared -> PreparedMoveEvent(it.move) + is GameEvent.CardPrepared -> PreparedCardEvent(it.preparedCard) + is GameEvent.PlayerIsReady -> PlayerReadyEvent(it.username) + } + }.dispatchAllIn(this) session.sayReady() } console.log("End of game saga") |