Merge 555c474fea1a6bdf84ea4e53baa9909e082a2021 into d51ef24c205b6b05330b3c4d7ce79c402db44447

This commit is contained in:
Loof 2025-09-18 15:08:14 +00:00 committed by GitHub
commit 134c27b588
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 20 deletions

View File

@ -8,16 +8,17 @@ import com.unciv.ui.components.input.onClick
import com.unciv.ui.components.extensions.toTextButton import com.unciv.ui.components.extensions.toTextButton
import com.unciv.ui.screens.basescreen.BaseScreen import com.unciv.ui.screens.basescreen.BaseScreen
class AuthPopup(stage: Stage, authSuccessful: ((Boolean) -> Unit)? = null) class AuthPopup(stage: Stage, private val authSuccessful: ((Boolean) -> Unit)? = null)
: Popup(stage) { : Popup(stage) {
constructor(screen: BaseScreen, authSuccessful: ((Boolean) -> Unit)? = null) : this(screen.stage, authSuccessful) constructor(screen: BaseScreen, authSuccessful: ((Boolean) -> Unit)? = null) : this(screen.stage, authSuccessful)
init { private val passwordField: UncivTextField = UncivTextField("Password")
val passwordField = UncivTextField("Password") private val button: TextButton = "Authenticate".toTextButton()
val button = "Authenticate".toTextButton() private val negativeButtonStyle: TextButton.TextButtonStyle =
val negativeButtonStyle = BaseScreen.skin.get("negative", TextButton.TextButtonStyle::class.java) BaseScreen.skin.get("negative", TextButton.TextButtonStyle::class.java)
init {
button.onClick { button.onClick {
try { try {
UncivGame.Current.onlineMultiplayer.multiplayerServer.authenticate(passwordField.text) UncivGame.Current.onlineMultiplayer.multiplayerServer.authenticate(passwordField.text)
@ -25,17 +26,18 @@ class AuthPopup(stage: Stage, authSuccessful: ((Boolean) -> Unit)? = null)
close() close()
} catch (_: Exception) { } catch (_: Exception) {
clear() clear()
addGoodSizedLabel("Authentication failed").colspan(2).row() addComponents("Authentication failed")
add(passwordField).colspan(2).growX().pad(16f, 0f, 16f, 0f).row()
addCloseButton(style = negativeButtonStyle) { authSuccessful?.invoke(false) }.growX().padRight(8f)
add(button).growX().padLeft(8f)
return@onClick
} }
} }
addComponents("Please enter your server password")
addGoodSizedLabel("Please enter your server password").colspan(2).row() }
private fun addComponents(headerLabelText: String) {
addGoodSizedLabel(headerLabelText).colspan(2).row()
add(passwordField).colspan(2).growX().pad(16f, 0f, 16f, 0f).row() add(passwordField).colspan(2).growX().pad(16f, 0f, 16f, 0f).row()
addCloseButton(style = negativeButtonStyle) { authSuccessful?.invoke(false) }.growX().padRight(8f) addCloseButton(style = negativeButtonStyle) {
authSuccessful?.invoke(false)
}.growX().padRight(8f)
add(button).growX().padLeft(8f) add(button).growX().padLeft(8f)
} }
} }

View File

@ -70,6 +70,7 @@ import com.unciv.utils.debug
import com.unciv.utils.launchOnGLThread import com.unciv.utils.launchOnGLThread
import com.unciv.utils.launchOnThreadPool import com.unciv.utils.launchOnThreadPool
import com.unciv.utils.withGLContext import com.unciv.utils.withGLContext
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import yairm210.purity.annotations.Readonly import yairm210.purity.annotations.Readonly
@ -595,17 +596,34 @@ class WorldScreen(
gameInfoClone.nextTurn(progressBar) gameInfoClone.nextTurn(progressBar)
if (originalGameInfo.gameParameters.isOnlineMultiplayer) { if (originalGameInfo.gameParameters.isOnlineMultiplayer) {
// outer try-catch for non-auth exceptions
try { try {
game.onlineMultiplayer.updateGame(gameInfoClone) // keep retrying if upload fails AND reauthentication succeeds
}catch (ex: Exception) { var retryUpload: Boolean
when (ex) { do {
is MultiplayerAuthException -> { try {
game.onlineMultiplayer.updateGame(gameInfoClone)
// upload succeeded
retryUpload = false
} catch (_: MultiplayerAuthException) {
// true only if authentication succeeds (the popup permits retries)
// false only if user closes the auth popup or the popup init crashes
val authResult = CompletableDeferred<Boolean>()
launchOnGLThread { launchOnGLThread {
AuthPopup(this@WorldScreen) { try {
success -> if (success) nextTurn() AuthPopup(this@WorldScreen, authResult::complete).open(true)
}.open(true) } catch (ex: Exception) {
// GL thread crashed during AuthPopup init, let's wrap up
authResult.complete(false)
// ensure exception is passed to crash handler
throw ex
}
} }
retryUpload = authResult.await()
} }
} while (retryUpload)
} catch (ex: Exception) { // non-auth exceptions
when (ex) {
is FileStorageRateLimitReached -> { is FileStorageRateLimitReached -> {
val message = "Server limit reached! Please wait for [${ex.limitRemainingSeconds}] seconds" val message = "Server limit reached! Please wait for [${ex.limitRemainingSeconds}] seconds"
launchOnGLThread { launchOnGLThread {