diff options
5 files changed, 53 insertions, 47 deletions
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 27c451be..e5c2b13e 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 @@ -13,7 +13,7 @@ data class UpdateGameListAction(val games: List<LobbyDTO>): RAction data class UpdateLobbyAction(val lobby: LobbyDTO): RAction -data class EnterLobbyAction(val gameId: Long): RAction +data class EnterLobbyAction(val lobby: LobbyDTO): RAction data class UpdatePlayers(val players: Map<String, PlayerDTO>): 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 69941c91..4c75bd66 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 @@ -27,13 +27,14 @@ private fun currentPlayerReducer(username: String?, action: RAction): String? = else -> username } -private fun currentLobbyReducer(currentLobby: Long?, action: RAction): Long? = when (action) { - is EnterLobbyAction -> action.gameId - else -> currentLobby +private fun currentLobbyReducer(currentLobbyId: Long?, action: RAction): Long? = when (action) { + is EnterLobbyAction -> action.lobby.id + else -> currentLobbyId } private fun gamesReducer(games: Map<Long, LobbyDTO>, action: RAction): Map<Long, LobbyDTO> = when (action) { 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) else -> games } diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt index f2dd4e0f..c5e3bdb8 100644 --- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt +++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt @@ -1,57 +1,47 @@ package org.luxons.sevenwonders.ui.redux.sagas +import com.palantir.blueprintjs.org.luxons.sevenwonders.ui.utils.awaitFirst import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import org.hildan.krossbow.stomp.StompSubscription import org.luxons.sevenwonders.client.SevenWondersSession import org.luxons.sevenwonders.model.api.LobbyDTO import org.luxons.sevenwonders.ui.redux.EnterLobbyAction import org.luxons.sevenwonders.ui.redux.RequestCreateGameAction import org.luxons.sevenwonders.ui.redux.RequestJoinGameAction import org.luxons.sevenwonders.ui.redux.UpdateGameListAction -import org.luxons.sevenwonders.ui.redux.UpdateLobbyAction -import org.luxons.sevenwonders.ui.router.Router -import kotlin.coroutines.coroutineContext suspend fun SwSagaContext.gameBrowserSaga(session: SevenWondersSession) { - coroutineScope { - launch { watchGames(session) } - launch { watchCreateGame(session) } - launch { watchJoinGame(session) } - } + GameBrowserSaga(session, this).run() } -private suspend fun SwSagaContext.watchGames(session: SevenWondersSession) { - val gamesSubscription = session.watchGames() - for (lobbies in gamesSubscription.messages) { - if (!coroutineContext.isActive) { +private class GameBrowserSaga( + private val session: SevenWondersSession, + private val sagaContext: SwSagaContext +) { + suspend fun run() { + coroutineScope { + val gamesSubscription = session.watchGames() + launch { dispatchGameUpdates(gamesSubscription) } + val lobby = awaitCreateOrJoinGame() gamesSubscription.unsubscribe() - break + sagaContext.dispatch(EnterLobbyAction(lobby)) } - dispatch(UpdateGameListAction(lobbies.toList())) } -} -private suspend fun SwSagaContext.watchCreateGame(session: SevenWondersSession) = - onEach<RequestCreateGameAction> { - val lobby = session.createGame(it.gameName) - handleGameJoined(session, lobby) - } + private suspend fun dispatchGameUpdates(gamesSubscription: StompSubscription<List<LobbyDTO>>) { + sagaContext.dispatchAll(gamesSubscription.messages) { UpdateGameListAction(it) } + } -private suspend fun SwSagaContext.watchJoinGame(session: SevenWondersSession) = - onEach<RequestJoinGameAction> { - val lobby = session.joinGame(it.gameId) - handleGameJoined(session, lobby) - } + private suspend fun awaitCreateOrJoinGame(): LobbyDTO = awaitFirst(this::awaitCreateGame, this::awaitJoinGame) -private suspend fun SwSagaContext.handleGameJoined( - session: SevenWondersSession, - lobby: LobbyDTO -) { - dispatch(UpdateLobbyAction(lobby)) - dispatch(EnterLobbyAction(lobby.id)) - coroutineScope { - launch { lobbySaga(session, lobby.id) } - Router.lobby() + private suspend fun awaitCreateGame(): LobbyDTO { + val action = sagaContext.next<RequestCreateGameAction>() + return session.createGame(action.gameName) + } + + private suspend fun awaitJoinGame(): LobbyDTO { + val action = sagaContext.next<RequestJoinGameAction>() + return session.joinGame(action.gameId) } } diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt index 1d15e8c4..ded0bc89 100644 --- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt +++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt @@ -1,7 +1,5 @@ package org.luxons.sevenwonders.ui.redux.sagas -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch import org.luxons.sevenwonders.client.SevenWondersClient import org.luxons.sevenwonders.ui.redux.RequestChooseName import org.luxons.sevenwonders.ui.redux.SetCurrentPlayerAction @@ -17,11 +15,11 @@ suspend fun SwSagaContext.rootSaga() { val session = SevenWondersClient().connect("localhost:8000") console.info("Connected to Seven Wonders web socket API") - coroutineScope { - launch { gameBrowserSaga(session) } + val player = session.chooseName(action.playerName) + dispatch(SetCurrentPlayerAction(player)) - val player = session.chooseName(action.playerName) - dispatch(SetCurrentPlayerAction(player)) - Router.games() - } + Router.games() + gameBrowserSaga(session) + Router.lobby() + lobbySaga(session) } diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/utils/CoroutinesUtils.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/utils/CoroutinesUtils.kt new file mode 100644 index 00000000..c7e950c8 --- /dev/null +++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/utils/CoroutinesUtils.kt @@ -0,0 +1,17 @@ +package com.palantir.blueprintjs.org.luxons.sevenwonders.ui.utils + +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.selects.select + +suspend inline fun <R> awaitFirst( + crossinline f1: suspend () -> R, + crossinline f2: suspend () -> R +): R = coroutineScope { + val deferred1 = async { f1() } + val deferred2 = async { f2() } + select<R> { + deferred1.onAwait { deferred2.cancel(); it } + deferred2.onAwait { deferred1.cancel(); it } + } +} |