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
This commit is contained in:
soggerr 2020-06-24 14:13:04 -06:00 committed by GitHub
parent 0f09ed2800
commit 213f71def3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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,33 +226,38 @@ 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") {
// 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(gameInfo.isUpToDate && gameInfo.currentPlayer==latestGame.currentPlayer) { // we were trying to download this to see when it's our turn...nothing changed
// 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@thread
return
}
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 {
else{ //else we found it is the player's turn again, turn off polling and load turn
stopMultiPlayerRefresher()
game.loadGame(latestGame)
latestGame.isUpToDate=true
Gdx.app.postRunnable { 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() }))
Gdx.app.postRunnable {
loadingGamePopup.close()
couldntDownloadLatestGame.open()
}
}
}
}
// This is private so that we will set the shouldUpdate to true instead.
// That way, not only do we save a lot of unnecessary updates, we also ensure that all updates are called from the main GL thread