From faec8b33c0366d65848bdca264c9a3f5f5d102a6 Mon Sep 17 00:00:00 2001 From: joffrey-bion Date: Fri, 12 Feb 2021 01:40:01 +0100 Subject: Fix race when bots leave game --- sw-client/build.gradle.kts | 3 ++ .../sevenwonders/client/SevenWondersClient.kt | 63 ++++++++++++---------- 2 files changed, 37 insertions(+), 29 deletions(-) (limited to 'sw-client') 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 doAndWaitForEvent(send: suspend () -> Unit, subscribe: suspend () -> Flow): T = + coroutineScope { + val eventsFlow = subscribe() + val deferredFirstEvent = async(start = CoroutineStart.UNDISPATCHED) { eventsFlow.first() } + send() + deferredFirstEvent.await() + } -- cgit