mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-13 01:08:25 +07:00
Improvements to TurnChecker data usage (#5789)
* Added necessary utils Added the FileNotFoundException which is also part of #5593 * Added preview download to MultiplayerScreen * Added preview download to TurnChecker * Fixed uncomplete commit * Removed debug print in MultiplayerScreen
This commit is contained in:
@ -16,6 +16,7 @@ import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.GameSaver
|
||||
import com.unciv.models.metadata.GameSettings
|
||||
import com.unciv.ui.worldscreen.mainmenu.OnlineMultiplayer
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.io.Writer
|
||||
@ -170,11 +171,14 @@ class MultiplayerTurnCheckWorker(appContext: Context, workerParams: WorkerParame
|
||||
var count = 0
|
||||
for (gameFile in gameFiles) {
|
||||
try {
|
||||
gameIds[count] = GameSaver.getGameIdFromFile(gameFile)
|
||||
gameNames[count] = gameFile.name()
|
||||
count++
|
||||
val gamePreview = GameSaver.loadGamePreviewFromFile(gameFile)
|
||||
if (gamePreview.turnNotification) {
|
||||
gameIds[count] = gamePreview.gameId
|
||||
gameNames[count] = gameFile.name()
|
||||
count++
|
||||
}
|
||||
} catch (ex: Throwable) {
|
||||
//only getGameIdFromFile can throw an exception
|
||||
//only loadGamePreviewFromFile can throw an exception
|
||||
//nothing will be added to the arrays if it fails
|
||||
//just skip one file
|
||||
}
|
||||
@ -231,35 +235,45 @@ class MultiplayerTurnCheckWorker(appContext: Context, workerParams: WorkerParame
|
||||
var arrayIndex = 0
|
||||
// We only want to notify the user or update persisted notification once but still want
|
||||
// to download all games to update the files hence this bool
|
||||
var foundGame = false
|
||||
var foundGame = ""
|
||||
|
||||
for (gameId in gameIds){
|
||||
//gameId could be an empty string if startTurnChecker fails to load all files
|
||||
if (gameId.isEmpty())
|
||||
continue
|
||||
|
||||
val game = OnlineMultiplayer().tryDownloadGameUninitialized(gameId)
|
||||
val currentTurnPlayer = game.getCivilization(game.currentPlayer)
|
||||
try {
|
||||
val gamePreview = OnlineMultiplayer().tryDownloadGamePreview(gameId)
|
||||
val currentTurnPlayer = gamePreview.getCivilization(gamePreview.currentPlayer)
|
||||
|
||||
//Save game so MultiplayerScreen gets updated
|
||||
/*
|
||||
I received multiple reports regarding broken save games.
|
||||
All of them where missing a few thousand chars at the end of the save game.
|
||||
I assume this happened because the TurnCheckerWorker gets canceled by the AndroidLauncher
|
||||
while saves are getting saved right here.
|
||||
*/
|
||||
//GameSaver.saveGame(game, gameNames[arrayIndex], true)
|
||||
//Save game so MultiplayerScreen gets updated
|
||||
/*
|
||||
I received multiple reports regarding broken save games.
|
||||
All of them where missing a few thousand chars at the end of the save game.
|
||||
I assume this happened because the TurnCheckerWorker gets canceled by the AndroidLauncher
|
||||
while saves are getting saved right here.
|
||||
Lets hope it works with gamePreview as they are a lot smaller and faster to save
|
||||
*/
|
||||
GameSaver.saveGame(gamePreview, gameNames[arrayIndex])
|
||||
|
||||
if (currentTurnPlayer.playerId == inputData.getString(USER_ID)!!) {
|
||||
foundGame = true
|
||||
//As we do not need to look any further we can just break here
|
||||
break
|
||||
if (currentTurnPlayer.playerId == inputData.getString(USER_ID)!! && foundGame.isEmpty()) {
|
||||
// We only save the first found game as the player will go into the
|
||||
// multiplayer screen anyway to join the game and see the other ones
|
||||
foundGame = gameNames[arrayIndex]
|
||||
}
|
||||
arrayIndex++
|
||||
} catch (ex: FileNotFoundException){
|
||||
// FileNotFoundException is thrown by OnlineMultiplayer().tryDownloadGamePreview(gameId)
|
||||
// and indicates that there is no game preview present for this game
|
||||
// in the dropbox so we should not check for this game in the future anymore
|
||||
val currentGamePreview = GameSaver.loadGamePreviewByName(gameNames[arrayIndex])
|
||||
currentGamePreview.turnNotification = false
|
||||
GameSaver.saveGame(currentGamePreview, gameNames[arrayIndex])
|
||||
}
|
||||
arrayIndex++
|
||||
}
|
||||
|
||||
if (foundGame){
|
||||
notifyUserAboutTurn(applicationContext, gameNames[arrayIndex])
|
||||
if (foundGame.isNotEmpty()){
|
||||
notifyUserAboutTurn(applicationContext, foundGame)
|
||||
with(NotificationManagerCompat.from(applicationContext)) {
|
||||
cancel(NOTIFICATION_ID_SERVICE)
|
||||
}
|
||||
|
@ -495,4 +495,18 @@ class GameInfoPreview() {
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current player and turn information in the GameInfoPreview object with the
|
||||
* help of another GameInfoPreview object.
|
||||
*/
|
||||
fun updateCurrentTurn(gameInfo: GameInfoPreview) : GameInfoPreview {
|
||||
currentPlayer = gameInfo.currentPlayer
|
||||
turns = gameInfo.turns
|
||||
currentTurnStartTime = gameInfo.currentTurnStartTime
|
||||
//We update the civilizations in case someone is removed from the game (resign/kick)
|
||||
civilizations = gameInfo.civilizations
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ object GameSaver {
|
||||
customSaveLocationHelper!!.saveGame(game, GameName, forcePrompt = true, saveCompleteCallback = saveCompletionCallback)
|
||||
}
|
||||
|
||||
fun loadGameByName(GameName: String, multiplayer: Boolean = false) =
|
||||
loadGameFromFile(getSave(GameName, multiplayer))
|
||||
fun loadGameByName(GameName: String) =
|
||||
loadGameFromFile(getSave(GameName))
|
||||
|
||||
fun loadGameFromFile(gameFile: FileHandle): GameInfo {
|
||||
val game = json().fromJson(GameInfo::class.java, gameFile)
|
||||
@ -72,6 +72,9 @@ object GameSaver {
|
||||
return game
|
||||
}
|
||||
|
||||
fun loadGamePreviewByName(GameName: String) =
|
||||
loadGamePreviewFromFile(getSave(GameName, true))
|
||||
|
||||
fun loadGamePreviewFromFile(gameFile: FileHandle): GameInfoPreview {
|
||||
return json().fromJson(GameInfoPreview::class.java, gameFile)
|
||||
}
|
||||
@ -168,13 +171,4 @@ object GameSaver {
|
||||
deleteSave(saveToDelete.name())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the gameId from a GameInfo which was saved as JSON for multiplayer
|
||||
* Does not initialize transitive GameInfo data.
|
||||
* It is therefore stateless and save to call for Multiplayer Turn Notifier.
|
||||
*/
|
||||
fun getGameIdFromFile(gameFile: FileHandle): String {
|
||||
return json().fromJson(GameInfo::class.java, gameFile).gameId
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.pickerscreens.PickerScreen
|
||||
import com.unciv.ui.utils.*
|
||||
import com.unciv.ui.worldscreen.mainmenu.OnlineMultiplayer
|
||||
import java.io.FileNotFoundException
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.concurrent.thread
|
||||
@ -144,13 +145,32 @@ class MultiplayerScreen(previousScreen: BaseScreen) : PickerScreen() {
|
||||
try {
|
||||
// The tryDownload can take more than 500ms. Therefore, to avoid ANRs,
|
||||
// we need to run it in a different thread.
|
||||
val gamePreview = OnlineMultiplayer().tryDownloadGame(gameId.trim()).asPreview()
|
||||
val gamePreview = OnlineMultiplayer().tryDownloadGamePreview(gameId.trim())
|
||||
if (gameName == "")
|
||||
GameSaver.saveGame(gamePreview, gamePreview.gameId)
|
||||
else
|
||||
GameSaver.saveGame(gamePreview, gameName)
|
||||
|
||||
Gdx.app.postRunnable { reloadGameListUI() }
|
||||
} catch (ex: FileNotFoundException) {
|
||||
// Game is so old that a preview could not be found on dropbox lets try the real gameInfo instead
|
||||
try {
|
||||
val gamePreview = OnlineMultiplayer().tryDownloadGame(gameId.trim()).asPreview()
|
||||
if (gameName == "")
|
||||
GameSaver.saveGame(gamePreview, gamePreview.gameId)
|
||||
else
|
||||
GameSaver.saveGame(gamePreview, gameName)
|
||||
|
||||
Gdx.app.postRunnable { reloadGameListUI() }
|
||||
} catch (ex: Exception) {
|
||||
Gdx.app.postRunnable {
|
||||
val errorPopup = Popup(this)
|
||||
errorPopup.addGoodSizedLabel("Could not download game!")
|
||||
errorPopup.row()
|
||||
errorPopup.addCloseButton()
|
||||
errorPopup.open()
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Gdx.app.postRunnable {
|
||||
val errorPopup = Popup(this)
|
||||
@ -313,16 +333,30 @@ class MultiplayerScreen(previousScreen: BaseScreen) : PickerScreen() {
|
||||
thread(name = "multiplayerGameDownload") {
|
||||
for ((fileHandle, gameInfo) in multiplayerGames) {
|
||||
try {
|
||||
val game = gameInfo.updateCurrentTurn(OnlineMultiplayer().tryDownloadGame(gameInfo.gameId))
|
||||
// Update game without overriding multiplayer settings
|
||||
val game = gameInfo.updateCurrentTurn(OnlineMultiplayer().tryDownloadGamePreview(gameInfo.gameId))
|
||||
GameSaver.saveGame(game, fileHandle.name())
|
||||
multiplayerGames[fileHandle] = game
|
||||
|
||||
} catch (ex: FileNotFoundException) {
|
||||
// Game is so old that a preview could not be found on dropbox lets try the real gameInfo instead
|
||||
try {
|
||||
// Update game without overriding multiplayer settings
|
||||
val game = gameInfo.updateCurrentTurn(OnlineMultiplayer().tryDownloadGame(gameInfo.gameId))
|
||||
GameSaver.saveGame(game, fileHandle.name())
|
||||
multiplayerGames[fileHandle] = game
|
||||
|
||||
} catch (ex: Exception) {
|
||||
Gdx.app.postRunnable {
|
||||
ToastPopup("Could not download game!" + " ${fileHandle.name()}", this)
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
//skipping one is not fatal
|
||||
//Trying to use as many prev. used strings as possible
|
||||
Gdx.app.postRunnable {
|
||||
ToastPopup("Could not download game!" + " ${fileHandle.name()}", this)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,12 @@ object DropBox {
|
||||
} catch (ex: Exception) {
|
||||
println(ex.message)
|
||||
val reader = BufferedReader(InputStreamReader(errorStream))
|
||||
println(reader.readText())
|
||||
val responseString = reader.readText()
|
||||
println(responseString)
|
||||
|
||||
// Throw Exceptions based on the HTTP response from dropbox
|
||||
if (responseString.contains("path/not_found/"))
|
||||
throw FileNotFoundException()
|
||||
return null
|
||||
} catch (error: Error) {
|
||||
println(error.message)
|
||||
@ -145,14 +150,4 @@ class OnlineMultiplayer {
|
||||
val zippedGameInfo = DropBox.downloadFileAsString("${getGameLocation(gameId)}_Preview")
|
||||
return GameSaver.gameInfoPreviewFromString(Gzip.unzip(zippedGameInfo))
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING!
|
||||
* Does not initialize transitive GameInfo data.
|
||||
* It is therefore stateless and safe to call for Multiplayer Turn Notifier, unlike tryDownloadGame().
|
||||
*/
|
||||
fun tryDownloadGameUninitialized(gameId: String): GameInfo {
|
||||
val zippedGameInfo = DropBox.downloadFileAsString(getGameLocation(gameId))
|
||||
return GameSaver.gameInfoFromStringWithoutTransients(Gzip.unzip(zippedGameInfo))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user