From 213f71def3ced93f75225ee5026e4b7842b0aa63 Mon Sep 17 00:00:00 2001 From: soggerr <64605293+soggerr@users.noreply.github.com> Date: Wed, 24 Jun 2020 14:13:04 -0600 Subject: [PATCH] Improve performance of multiplayer load poll (#2758) * Switch to schedule instead of schedulefixedrate to prevent floodgate of requests after long delays * Move everything possible off of main thread so user can have smoother interaction with game during poll --- .../com/unciv/ui/worldscreen/WorldScreen.kt | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index fd35b1c840..2d1c2b1611 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -132,8 +132,8 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() { stopMultiPlayerRefresher() // isDaemon = true, in order to not block the app closing multiPlayerRefresher = Timer("multiPlayerRefresh", true).apply { - scheduleAtFixedRate(object : TimerTask() { - override fun run() { Gdx.app.postRunnable{ loadLatestMultiplayerState() } } + schedule(object : TimerTask() { //todo maybe not use timer for web request, from timer docs "Timer tasks should complete quickly." + override fun run() { loadLatestMultiplayerState() } }, 0, 10000) // 10 seconds } } @@ -226,30 +226,35 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() { private fun loadLatestMultiplayerState(){ val loadingGamePopup = Popup(this) loadingGamePopup.add("Loading latest game state...".tr()) - loadingGamePopup.open() - thread(name="MultiplayerLoad") { - try { - val latestGame = OnlineMultiplayer().tryDownloadGame(gameInfo.gameId) - if(gameInfo.isUpToDate && gameInfo.currentPlayer==latestGame.currentPlayer) { // we were trying to download this to see when it's our turn...nothing changed - Gdx.app.postRunnable { loadingGamePopup.close() } - return@thread - } - latestGame.isUpToDate=true - // Since we're making a screen this needs to run from the main thread which has a GL context - Gdx.app.postRunnable { - stopMultiPlayerRefresher() - game.loadGame(latestGame) - } - } catch (ex: Exception) { - Gdx.app.postRunnable { // otherwise the popups of the screen could be concurrently modified, and we'll get an unhappy thread - loadingGamePopup.close() - val couldntDownloadLatestGame = Popup(this) - couldntDownloadLatestGame.addGoodSizedLabel("Couldn't download the latest game state!").row() - couldntDownloadLatestGame.addCloseButton() - couldntDownloadLatestGame.addAction(Actions.delay(5f, Actions.run { couldntDownloadLatestGame.close() })) - couldntDownloadLatestGame.open() - } + // Since we're on a background thread, all the UI calls in this func need to run from the + // main thread which has a GL context + Gdx.app.postRunnable { loadingGamePopup.open() } + + try { + val latestGame = OnlineMultiplayer().tryDownloadGame(gameInfo.gameId) + + // if we find it still isn't player's turn...nothing changed + if(gameInfo.isUpToDate && gameInfo.currentPlayer==latestGame.currentPlayer) { + Gdx.app.postRunnable { loadingGamePopup.close() } + return + } + else{ //else we found it is the player's turn again, turn off polling and load turn + stopMultiPlayerRefresher() + + latestGame.isUpToDate=true + Gdx.app.postRunnable { game.loadGame(latestGame) } + } + + } catch (ex: Exception) { + val couldntDownloadLatestGame = Popup(this) + couldntDownloadLatestGame.addGoodSizedLabel("Couldn't download the latest game state!").row() + couldntDownloadLatestGame.addCloseButton() + couldntDownloadLatestGame.addAction(Actions.delay(5f, Actions.run { couldntDownloadLatestGame.close() })) + + Gdx.app.postRunnable { + loadingGamePopup.close() + couldntDownloadLatestGame.open() } } }