diff options
author | joffrey-bion <joffrey.bion@gmail.com> | 2021-02-12 01:40:01 +0100 |
---|---|---|
committer | joffrey-bion <joffrey.bion@gmail.com> | 2021-02-12 01:59:12 +0100 |
commit | faec8b33c0366d65848bdca264c9a3f5f5d102a6 (patch) | |
tree | c193fef242036f4d35a8dfcf4a86aff2638b49b4 | |
parent | Fix pulsing red (remove incorrect preparedMove field) (diff) | |
download | seven-wonders-faec8b33c0366d65848bdca264c9a3f5f5d102a6.tar.gz seven-wonders-faec8b33c0366d65848bdca264c9a3f5f5d102a6.tar.bz2 seven-wonders-faec8b33c0366d65848bdca264c9a3f5f5d102a6.zip |
Fix race when bots leave game
3 files changed, 38 insertions, 30 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 86ade852..611c6369 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 @@ -93,7 +93,7 @@ class SevenWondersBot( } val lastTurn = endGameTurnInfo.await() logger.info("BOT $player: leaving the game") - session.leaveGame() + session.leaveGameAndAwaitEnd() session.disconnect() logger.info("BOT $player: disconnected") lastTurn diff --git a/sw-client/build.gradle.kts b/sw-client/build.gradle.kts index 68953bc4..f29fcbf8 100644 --- a/sw-client/build.gradle.kts +++ b/sw-client/build.gradle.kts @@ -8,6 +8,9 @@ kotlin { browser() // necessary for local dependency from JS UI module } sourceSets { + all { + languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn") + } val commonMain by getting { dependencies { api(project(":sw-common-model")) 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 fc097d86..bf5778ad 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,7 +1,6 @@ package org.luxons.sevenwonders.client -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -150,30 +149,36 @@ class SevenWondersSession(private val stompSession: StompSessionWithKxSerializat } } -suspend fun SevenWondersSession.createGameAndWaitLobby(gameName: String): LobbyDTO = coroutineScope { - val lobbies = watchLobbyJoined() - val joinedLobby = async { lobbies.first() } - createGame(gameName) - joinedLobby.await() -} - -suspend fun SevenWondersSession.joinGameAndWaitLobby(gameId: Long): LobbyDTO = coroutineScope { - val lobbies = watchLobbyJoined() - val joinedLobby = async { lobbies.first() } - joinGame(gameId) - joinedLobby.await() -} - -suspend fun SevenWondersSession.startGameAndAwaitFirstTurn(): PlayerTurnInfo = coroutineScope { - val gameStartedEvents = watchGameStarted() - val deferredFirstTurn = async { gameStartedEvents.first() } - startGame() - deferredFirstTurn.await() -} - -suspend fun SevenWondersSession.joinGameAndWaitFirstTurn(gameId: Long): PlayerTurnInfo = coroutineScope { - val gameStartedEvents = watchGameStarted() - val deferredFirstTurn = async { gameStartedEvents.first() } - joinGame(gameId) - deferredFirstTurn.await() -} +suspend fun SevenWondersSession.createGameAndWaitLobby(gameName: String): LobbyDTO = doAndWaitForEvent( + send = { createGame(gameName) }, + subscribe = { watchLobbyJoined() }, +) + +suspend fun SevenWondersSession.joinGameAndWaitLobby(gameId: Long): LobbyDTO = doAndWaitForEvent( + send = { joinGame(gameId) }, + subscribe = { watchLobbyJoined() }, +) + +suspend fun SevenWondersSession.startGameAndAwaitFirstTurn(): PlayerTurnInfo = doAndWaitForEvent( + send = { startGame() }, + subscribe = { watchGameStarted() }, +) + +suspend fun SevenWondersSession.joinGameAndWaitFirstTurn(gameId: Long): PlayerTurnInfo = doAndWaitForEvent( + send = { joinGame(gameId) }, + subscribe = { watchGameStarted() }, +) + +suspend fun SevenWondersSession.leaveGameAndAwaitEnd() = doAndWaitForEvent( + send = { leaveGame() }, + subscribe = { watchLobbyLeft() }, +) + +@OptIn(ExperimentalCoroutinesApi::class) +private suspend fun <T> doAndWaitForEvent(send: suspend () -> Unit, subscribe: suspend () -> Flow<T>): T = + coroutineScope { + val eventsFlow = subscribe() + val deferredFirstEvent = async(start = CoroutineStart.UNDISPATCHED) { eventsFlow.first() } + send() + deferredFirstEvent.await() + } |