mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-16 02:40:41 +07:00
Multi-server preparations: Save server info in game, save server functionality in specific class (#9379)
* Save server info in game * Moved server functionality into server class * Fix Android multiplayer update
This commit is contained in:
@ -29,7 +29,7 @@ import com.badlogic.gdx.backends.android.DefaultAndroidFiles
|
|||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
import com.unciv.logic.files.UncivFiles
|
import com.unciv.logic.files.UncivFiles
|
||||||
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
||||||
import com.unciv.logic.multiplayer.storage.OnlineMultiplayerFiles
|
import com.unciv.logic.multiplayer.storage.OnlineMultiplayerServer
|
||||||
import com.unciv.models.metadata.GameSettingsMultiplayer
|
import com.unciv.models.metadata.GameSettingsMultiplayer
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
@ -307,7 +307,7 @@ class MultiplayerTurnCheckWorker(appContext: Context, workerParams: WorkerParame
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Log.d(LOG_TAG, "doWork download $gameId")
|
Log.d(LOG_TAG, "doWork download $gameId")
|
||||||
val gamePreview = OnlineMultiplayerFiles(fileStorage, mapOf("Authorization" to authHeader)).tryDownloadGamePreview(gameId)
|
val gamePreview = OnlineMultiplayerServer(fileStorage, mapOf("Authorization" to authHeader)).tryDownloadGamePreview(gameId)
|
||||||
Log.d(LOG_TAG, "doWork download $gameId done")
|
Log.d(LOG_TAG, "doWork download $gameId done")
|
||||||
val currentTurnPlayer = gamePreview.getCivilization(gamePreview.currentPlayer)
|
val currentTurnPlayer = gamePreview.getCivilization(gamePreview.currentPlayer)
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ open class UncivGame(val isConsoleMode: Boolean = false) : Game(), PlatformSpeci
|
|||||||
Concurrency.run {
|
Concurrency.run {
|
||||||
// Check if the server is available in case the feature set has changed
|
// Check if the server is available in case the feature set has changed
|
||||||
try {
|
try {
|
||||||
onlineMultiplayer.checkServerStatus()
|
onlineMultiplayer.multiplayerServer.checkServerStatus()
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
debug("Couldn't connect to server: " + ex.message)
|
debug("Couldn't connect to server: " + ex.message)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package com.unciv.logic.multiplayer
|
|||||||
import com.badlogic.gdx.files.FileHandle
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.json.json
|
|
||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
import com.unciv.logic.GameInfoPreview
|
import com.unciv.logic.GameInfoPreview
|
||||||
import com.unciv.logic.civilization.NotificationCategory
|
import com.unciv.logic.civilization.NotificationCategory
|
||||||
@ -12,15 +11,13 @@ import com.unciv.logic.event.EventBus
|
|||||||
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
||||||
import com.unciv.logic.multiplayer.storage.MultiplayerAuthException
|
import com.unciv.logic.multiplayer.storage.MultiplayerAuthException
|
||||||
import com.unciv.logic.multiplayer.storage.MultiplayerFileNotFoundException
|
import com.unciv.logic.multiplayer.storage.MultiplayerFileNotFoundException
|
||||||
import com.unciv.logic.multiplayer.storage.OnlineMultiplayerFiles
|
import com.unciv.logic.multiplayer.storage.OnlineMultiplayerServer
|
||||||
import com.unciv.ui.components.extensions.isLargerThan
|
import com.unciv.ui.components.extensions.isLargerThan
|
||||||
import com.unciv.logic.multiplayer.storage.SimpleHttp
|
|
||||||
import com.unciv.utils.Log
|
|
||||||
import com.unciv.utils.Concurrency
|
import com.unciv.utils.Concurrency
|
||||||
import com.unciv.utils.Dispatcher
|
import com.unciv.utils.Dispatcher
|
||||||
|
import com.unciv.utils.debug
|
||||||
import com.unciv.utils.launchOnThreadPool
|
import com.unciv.utils.launchOnThreadPool
|
||||||
import com.unciv.utils.withGLContext
|
import com.unciv.utils.withGLContext
|
||||||
import com.unciv.utils.debug
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@ -45,8 +42,7 @@ private val FILE_UPDATE_THROTTLE_PERIOD = Duration.ofSeconds(60)
|
|||||||
*/
|
*/
|
||||||
class OnlineMultiplayer {
|
class OnlineMultiplayer {
|
||||||
private val files = UncivGame.Current.files
|
private val files = UncivGame.Current.files
|
||||||
private val multiplayerFiles = OnlineMultiplayerFiles()
|
val multiplayerServer = OnlineMultiplayerServer()
|
||||||
private var featureSet = ServerFeatureSet()
|
|
||||||
|
|
||||||
private val savedGames: MutableMap<FileHandle, OnlineMultiplayerGame> = Collections.synchronizedMap(mutableMapOf())
|
private val savedGames: MutableMap<FileHandle, OnlineMultiplayerGame> = Collections.synchronizedMap(mutableMapOf())
|
||||||
|
|
||||||
@ -55,7 +51,6 @@ class OnlineMultiplayer {
|
|||||||
private val lastCurGameRefresh: AtomicReference<Instant?> = AtomicReference()
|
private val lastCurGameRefresh: AtomicReference<Instant?> = AtomicReference()
|
||||||
|
|
||||||
val games: Set<OnlineMultiplayerGame> get() = savedGames.values.toSet()
|
val games: Set<OnlineMultiplayerGame> get() = savedGames.values.toSet()
|
||||||
val serverFeatureSet: ServerFeatureSet get() = featureSet
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
flow<Unit> {
|
flow<Unit> {
|
||||||
@ -125,7 +120,7 @@ class OnlineMultiplayer {
|
|||||||
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
||||||
*/
|
*/
|
||||||
suspend fun createGame(newGame: GameInfo) {
|
suspend fun createGame(newGame: GameInfo) {
|
||||||
multiplayerFiles.tryUploadGame(newGame, withPreview = true)
|
multiplayerServer.tryUploadGame(newGame, withPreview = true)
|
||||||
addGame(newGame)
|
addGame(newGame)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,11 +134,12 @@ class OnlineMultiplayer {
|
|||||||
*/
|
*/
|
||||||
suspend fun addGame(gameId: String, gameName: String? = null) {
|
suspend fun addGame(gameId: String, gameName: String? = null) {
|
||||||
val saveFileName = if (gameName.isNullOrBlank()) gameId else gameName
|
val saveFileName = if (gameName.isNullOrBlank()) gameId else gameName
|
||||||
val gamePreview: GameInfoPreview = try {
|
var gamePreview: GameInfoPreview
|
||||||
multiplayerFiles.tryDownloadGamePreview(gameId)
|
try {
|
||||||
|
gamePreview = multiplayerServer.tryDownloadGamePreview(gameId)
|
||||||
} catch (ex: MultiplayerFileNotFoundException) {
|
} catch (ex: MultiplayerFileNotFoundException) {
|
||||||
// Game is so old that a preview could not be found on dropbox lets try the real gameInfo instead
|
// Game is so old that a preview could not be found on dropbox lets try the real gameInfo instead
|
||||||
multiplayerFiles.tryDownloadGame(gameId).asPreview()
|
gamePreview = multiplayerServer.tryDownloadGame(gameId).asPreview()
|
||||||
}
|
}
|
||||||
addGame(gamePreview, saveFileName)
|
addGame(gamePreview, saveFileName)
|
||||||
}
|
}
|
||||||
@ -189,7 +185,7 @@ class OnlineMultiplayer {
|
|||||||
suspend fun resign(game: OnlineMultiplayerGame): Boolean {
|
suspend fun resign(game: OnlineMultiplayerGame): Boolean {
|
||||||
val preview = game.preview ?: throw game.error!!
|
val preview = game.preview ?: throw game.error!!
|
||||||
// download to work with the latest game state
|
// download to work with the latest game state
|
||||||
val gameInfo = multiplayerFiles.tryDownloadGame(preview.gameId)
|
val gameInfo = multiplayerServer.tryDownloadGame(preview.gameId)
|
||||||
val playerCiv = gameInfo.getCurrentPlayerCivilization()
|
val playerCiv = gameInfo.getCurrentPlayerCivilization()
|
||||||
|
|
||||||
if (!gameInfo.isUsersTurn()) {
|
if (!gameInfo.isUsersTurn()) {
|
||||||
@ -212,7 +208,7 @@ class OnlineMultiplayer {
|
|||||||
|
|
||||||
val newPreview = gameInfo.asPreview()
|
val newPreview = gameInfo.asPreview()
|
||||||
files.saveGame(newPreview, game.fileHandle)
|
files.saveGame(newPreview, game.fileHandle)
|
||||||
multiplayerFiles.tryUploadGame(gameInfo, withPreview = true)
|
multiplayerServer.tryUploadGame(gameInfo, withPreview = true)
|
||||||
game.doManualUpdate(newPreview)
|
game.doManualUpdate(newPreview)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -248,7 +244,7 @@ class OnlineMultiplayer {
|
|||||||
*/
|
*/
|
||||||
suspend fun loadGame(gameInfo: GameInfo) = coroutineScope {
|
suspend fun loadGame(gameInfo: GameInfo) = coroutineScope {
|
||||||
val gameId = gameInfo.gameId
|
val gameId = gameInfo.gameId
|
||||||
val preview = multiplayerFiles.tryDownloadGamePreview(gameId)
|
val preview = multiplayerServer.tryDownloadGamePreview(gameId)
|
||||||
if (hasLatestGameState(gameInfo, preview)) {
|
if (hasLatestGameState(gameInfo, preview)) {
|
||||||
gameInfo.isUpToDate = true
|
gameInfo.isUpToDate = true
|
||||||
UncivGame.Current.loadGame(gameInfo)
|
UncivGame.Current.loadGame(gameInfo)
|
||||||
@ -262,7 +258,7 @@ class OnlineMultiplayer {
|
|||||||
* @throws MultiplayerFileNotFoundException if the file can't be found
|
* @throws MultiplayerFileNotFoundException if the file can't be found
|
||||||
*/
|
*/
|
||||||
suspend fun downloadGame(gameId: String): GameInfo {
|
suspend fun downloadGame(gameId: String): GameInfo {
|
||||||
val latestGame = multiplayerFiles.tryDownloadGame(gameId)
|
val latestGame = multiplayerServer.tryDownloadGame(gameId)
|
||||||
latestGame.isUpToDate = true
|
latestGame.isUpToDate = true
|
||||||
return latestGame
|
return latestGame
|
||||||
}
|
}
|
||||||
@ -311,7 +307,7 @@ class OnlineMultiplayer {
|
|||||||
*/
|
*/
|
||||||
suspend fun updateGame(gameInfo: GameInfo) {
|
suspend fun updateGame(gameInfo: GameInfo) {
|
||||||
debug("Updating remote game %s", gameInfo.gameId)
|
debug("Updating remote game %s", gameInfo.gameId)
|
||||||
multiplayerFiles.tryUploadGame(gameInfo, withPreview = true)
|
multiplayerServer.tryUploadGame(gameInfo, withPreview = true)
|
||||||
val game = getGameByGameId(gameInfo.gameId)
|
val game = getGameByGameId(gameInfo.gameId)
|
||||||
debug("Existing OnlineMultiplayerGame: %s", game)
|
debug("Existing OnlineMultiplayerGame: %s", game)
|
||||||
if (game == null) {
|
if (game == null) {
|
||||||
@ -330,66 +326,6 @@ class OnlineMultiplayer {
|
|||||||
&& gameInfo.turns == preview.turns
|
&& gameInfo.turns == preview.turns
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the server is alive and sets the [serverFeatureSet] accordingly.
|
|
||||||
* @return true if the server is alive, false otherwise
|
|
||||||
*/
|
|
||||||
fun checkServerStatus(): Boolean {
|
|
||||||
var statusOk = false
|
|
||||||
SimpleHttp.sendGetRequest("${UncivGame.Current.settings.multiplayer.server}/isalive") { success, result, _ ->
|
|
||||||
statusOk = success
|
|
||||||
if (result.isNotEmpty()) {
|
|
||||||
featureSet = try {
|
|
||||||
json().fromJson(ServerFeatureSet::class.java, result)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
Log.error("${UncivGame.Current.settings.multiplayer.server} does not support server feature set", ex)
|
|
||||||
ServerFeatureSet()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return statusOk
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the authentication was successful or the server does not support authentication.
|
|
||||||
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
|
||||||
* @throws MultiplayerAuthException if the authentication failed
|
|
||||||
*/
|
|
||||||
fun authenticate(password: String?): Boolean {
|
|
||||||
if (featureSet.authVersion == 0) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val settings = UncivGame.Current.settings.multiplayer
|
|
||||||
|
|
||||||
val success = multiplayerFiles.fileStorage().authenticate(
|
|
||||||
userId=settings.userId,
|
|
||||||
password=password ?: settings.passwords[settings.server] ?: ""
|
|
||||||
)
|
|
||||||
if (password != null && success) {
|
|
||||||
settings.passwords[settings.server] = password
|
|
||||||
}
|
|
||||||
return success
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if setting the password was successful, false otherwise.
|
|
||||||
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
|
||||||
* @throws MultiplayerAuthException if the authentication failed
|
|
||||||
*/
|
|
||||||
fun setPassword(password: String): Boolean {
|
|
||||||
if (
|
|
||||||
featureSet.authVersion > 0 &&
|
|
||||||
multiplayerFiles.fileStorage().setPassword(newPassword = password)
|
|
||||||
) {
|
|
||||||
val settings = UncivGame.Current.settings.multiplayer
|
|
||||||
settings.passwords[settings.server] = password
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if [preview1] has a more recent game state than [preview2]
|
* Checks if [preview1] has a more recent game state than [preview2]
|
||||||
|
@ -8,11 +8,11 @@ import com.unciv.logic.multiplayer.GameUpdateResult.Type.CHANGED
|
|||||||
import com.unciv.logic.multiplayer.GameUpdateResult.Type.FAILURE
|
import com.unciv.logic.multiplayer.GameUpdateResult.Type.FAILURE
|
||||||
import com.unciv.logic.multiplayer.GameUpdateResult.Type.UNCHANGED
|
import com.unciv.logic.multiplayer.GameUpdateResult.Type.UNCHANGED
|
||||||
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
import com.unciv.logic.multiplayer.storage.FileStorageRateLimitReached
|
||||||
import com.unciv.logic.multiplayer.storage.OnlineMultiplayerFiles
|
import com.unciv.logic.multiplayer.storage.OnlineMultiplayerServer
|
||||||
import com.unciv.ui.components.extensions.isLargerThan
|
import com.unciv.ui.components.extensions.isLargerThan
|
||||||
|
import com.unciv.utils.debug
|
||||||
import com.unciv.utils.launchOnGLThread
|
import com.unciv.utils.launchOnGLThread
|
||||||
import com.unciv.utils.withGLContext
|
import com.unciv.utils.withGLContext
|
||||||
import com.unciv.utils.debug
|
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -65,7 +65,7 @@ class OnlineMultiplayerGame(
|
|||||||
* Fires: [MultiplayerGameUpdateStarted], [MultiplayerGameUpdated], [MultiplayerGameUpdateUnchanged], [MultiplayerGameUpdateFailed]
|
* Fires: [MultiplayerGameUpdateStarted], [MultiplayerGameUpdated], [MultiplayerGameUpdateUnchanged], [MultiplayerGameUpdateFailed]
|
||||||
*
|
*
|
||||||
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
||||||
* @throws MultiplayerFileNotFoundException if the file can't be found
|
* @throws MultiplayerFileNotFoundException if the file can't be found
|
||||||
*/
|
*/
|
||||||
suspend fun requestUpdate(forceUpdate: Boolean = false) = coroutineScope {
|
suspend fun requestUpdate(forceUpdate: Boolean = false) = coroutineScope {
|
||||||
val onUnchanged = { GameUpdateResult(UNCHANGED, preview!!) }
|
val onUnchanged = { GameUpdateResult(UNCHANGED, preview!!) }
|
||||||
@ -106,7 +106,8 @@ class OnlineMultiplayerGame(
|
|||||||
|
|
||||||
private suspend fun update(): GameUpdateResult {
|
private suspend fun update(): GameUpdateResult {
|
||||||
val curPreview = if (preview != null) preview!! else loadPreviewFromFile()
|
val curPreview = if (preview != null) preview!! else loadPreviewFromFile()
|
||||||
val newPreview = OnlineMultiplayerFiles().tryDownloadGamePreview(curPreview.gameId)
|
val serverIdentifier = curPreview.gameParameters.multiplayerServerUrl
|
||||||
|
val newPreview = OnlineMultiplayerServer(serverIdentifier).tryDownloadGamePreview(curPreview.gameId)
|
||||||
if (newPreview.turns == curPreview.turns && newPreview.currentPlayer == curPreview.currentPlayer) return GameUpdateResult(UNCHANGED, newPreview)
|
if (newPreview.turns == curPreview.turns && newPreview.currentPlayer == curPreview.currentPlayer) return GameUpdateResult(UNCHANGED, newPreview)
|
||||||
UncivGame.Current.files.saveGame(newPreview, fileHandle)
|
UncivGame.Current.files.saveGame(newPreview, fileHandle)
|
||||||
preview = newPreview
|
preview = newPreview
|
||||||
|
@ -2,9 +2,12 @@ package com.unciv.logic.multiplayer.storage
|
|||||||
|
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
|
import com.unciv.json.json
|
||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
import com.unciv.logic.GameInfoPreview
|
import com.unciv.logic.GameInfoPreview
|
||||||
import com.unciv.logic.files.UncivFiles
|
import com.unciv.logic.files.UncivFiles
|
||||||
|
import com.unciv.logic.multiplayer.ServerFeatureSet
|
||||||
|
import com.unciv.utils.Log
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows access to games stored on a server for multiplayer purposes.
|
* Allows access to games stored on a server for multiplayer purposes.
|
||||||
@ -17,12 +20,14 @@ import com.unciv.logic.files.UncivFiles
|
|||||||
* @see UncivGame.Current.settings.multiplayerServer
|
* @see UncivGame.Current.settings.multiplayerServer
|
||||||
*/
|
*/
|
||||||
@Suppress("RedundantSuspendModifier") // Methods can take a long time, so force users to use them in a coroutine to not get ANRs on Android
|
@Suppress("RedundantSuspendModifier") // Methods can take a long time, so force users to use them in a coroutine to not get ANRs on Android
|
||||||
class OnlineMultiplayerFiles(
|
class OnlineMultiplayerServer(
|
||||||
private var fileStorageIdentifier: String? = null,
|
fileStorageIdentifier: String? = null,
|
||||||
private var authenticationHeader: Map<String, String>? = null
|
private var authenticationHeader: Map<String, String>? = null
|
||||||
) {
|
) {
|
||||||
|
internal var featureSet = ServerFeatureSet()
|
||||||
|
val serverUrl = fileStorageIdentifier ?: UncivGame.Current.settings.multiplayer.server
|
||||||
|
|
||||||
fun fileStorage(): FileStorage {
|
fun fileStorage(): FileStorage {
|
||||||
val identifier = if (fileStorageIdentifier == null) UncivGame.Current.settings.multiplayer.server else fileStorageIdentifier
|
|
||||||
val authHeader = if (authenticationHeader == null) {
|
val authHeader = if (authenticationHeader == null) {
|
||||||
val settings = UncivGame.Current.settings.multiplayer
|
val settings = UncivGame.Current.settings.multiplayer
|
||||||
mapOf("Authorization" to settings.getAuthHeader())
|
mapOf("Authorization" to settings.getAuthHeader())
|
||||||
@ -30,16 +35,73 @@ class OnlineMultiplayerFiles(
|
|||||||
authenticationHeader
|
authenticationHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (identifier == Constants.dropboxMultiplayerServer) {
|
return if (serverUrl == Constants.dropboxMultiplayerServer) {
|
||||||
DropBox
|
DropBox
|
||||||
} else {
|
} else {
|
||||||
UncivServerFileStorage.apply {
|
UncivServerFileStorage.apply {
|
||||||
serverUrl = identifier!!
|
serverUrl = this@OnlineMultiplayerServer.serverUrl
|
||||||
this.authHeader = authHeader
|
this.authHeader = authHeader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the server is alive and sets the [serverFeatureSet] accordingly.
|
||||||
|
* @return true if the server is alive, false otherwise
|
||||||
|
*/
|
||||||
|
fun checkServerStatus(): Boolean {
|
||||||
|
var statusOk = false
|
||||||
|
SimpleHttp.sendGetRequest("${serverUrl}/isalive") { success, result, _ ->
|
||||||
|
statusOk = success
|
||||||
|
if (result.isNotEmpty()) {
|
||||||
|
featureSet = try {
|
||||||
|
json().fromJson(ServerFeatureSet::class.java, result)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Log.error("${UncivGame.Current.settings.multiplayer.server} does not support server feature set", ex)
|
||||||
|
ServerFeatureSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return statusOk
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the authentication was successful or the server does not support authentication.
|
||||||
|
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
||||||
|
* @throws MultiplayerAuthException if the authentication failed
|
||||||
|
*/
|
||||||
|
fun authenticate(password: String?): Boolean {
|
||||||
|
if (featureSet.authVersion == 0) return true
|
||||||
|
|
||||||
|
val settings = UncivGame.Current.settings.multiplayer
|
||||||
|
|
||||||
|
val success = fileStorage().authenticate(
|
||||||
|
userId=settings.userId,
|
||||||
|
password=password ?: settings.passwords[settings.server] ?: ""
|
||||||
|
)
|
||||||
|
if (password != null && success) {
|
||||||
|
settings.passwords[settings.server] = password
|
||||||
|
}
|
||||||
|
return success
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if setting the password was successful, false otherwise.
|
||||||
|
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
||||||
|
* @throws MultiplayerAuthException if the authentication failed
|
||||||
|
*/
|
||||||
|
fun setPassword(password: String): Boolean {
|
||||||
|
if (featureSet.authVersion > 0 && fileStorage().setPassword(newPassword = password)) {
|
||||||
|
val settings = UncivGame.Current.settings.multiplayer
|
||||||
|
settings.passwords[settings.server] = password
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
* @throws FileStorageRateLimitReached if the file storage backend can't handle any additional actions for a time
|
||||||
* @throws MultiplayerAuthException if the authentication failed
|
* @throws MultiplayerAuthException if the authentication failed
|
||||||
@ -81,7 +143,9 @@ class OnlineMultiplayerFiles(
|
|||||||
*/
|
*/
|
||||||
suspend fun tryDownloadGame(gameId: String): GameInfo {
|
suspend fun tryDownloadGame(gameId: String): GameInfo {
|
||||||
val zippedGameInfo = fileStorage().loadFileData(gameId)
|
val zippedGameInfo = fileStorage().loadFileData(gameId)
|
||||||
return UncivFiles.gameInfoFromString(zippedGameInfo)
|
val gameInfo = UncivFiles.gameInfoFromString(zippedGameInfo)
|
||||||
|
gameInfo.gameParameters.multiplayerServerUrl = UncivGame.Current.settings.multiplayer.server
|
||||||
|
return gameInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@ -43,6 +43,7 @@ class GameParameters : IsPartOfGameInfoSerialization { // Default values are the
|
|||||||
var startingEra = "Ancient era"
|
var startingEra = "Ancient era"
|
||||||
|
|
||||||
var isOnlineMultiplayer = false
|
var isOnlineMultiplayer = false
|
||||||
|
var multiplayerServerUrl: String? = null
|
||||||
var anyoneCanSpectate = true
|
var anyoneCanSpectate = true
|
||||||
var baseRuleset: String = BaseRuleset.Civ_V_GnK.fullName
|
var baseRuleset: String = BaseRuleset.Civ_V_GnK.fullName
|
||||||
var mods = LinkedHashSet<String>()
|
var mods = LinkedHashSet<String>()
|
||||||
@ -74,6 +75,7 @@ class GameParameters : IsPartOfGameInfoSerialization { // Default values are the
|
|||||||
parameters.victoryTypes = ArrayList(victoryTypes)
|
parameters.victoryTypes = ArrayList(victoryTypes)
|
||||||
parameters.startingEra = startingEra
|
parameters.startingEra = startingEra
|
||||||
parameters.isOnlineMultiplayer = isOnlineMultiplayer
|
parameters.isOnlineMultiplayer = isOnlineMultiplayer
|
||||||
|
parameters.multiplayerServerUrl = multiplayerServerUrl
|
||||||
parameters.anyoneCanSpectate = anyoneCanSpectate
|
parameters.anyoneCanSpectate = anyoneCanSpectate
|
||||||
parameters.baseRuleset = baseRuleset
|
parameters.baseRuleset = baseRuleset
|
||||||
parameters.mods = LinkedHashSet(mods)
|
parameters.mods = LinkedHashSet(mods)
|
||||||
|
@ -20,7 +20,7 @@ class AuthPopup(stage: Stage, authSuccessful: ((Boolean) -> Unit)? = null)
|
|||||||
|
|
||||||
button.onClick {
|
button.onClick {
|
||||||
try {
|
try {
|
||||||
UncivGame.Current.onlineMultiplayer.authenticate(passwordField.text)
|
UncivGame.Current.onlineMultiplayer.multiplayerServer.authenticate(passwordField.text)
|
||||||
authSuccessful?.invoke(true)
|
authSuccessful?.invoke(true)
|
||||||
close()
|
close()
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
|
@ -192,7 +192,7 @@ private fun addMultiplayerServerOptions(
|
|||||||
}
|
}
|
||||||
}).row()
|
}).row()
|
||||||
|
|
||||||
if (UncivGame.Current.onlineMultiplayer.serverFeatureSet.authVersion > 0) {
|
if (UncivGame.Current.onlineMultiplayer.multiplayerServer.featureSet.authVersion > 0) {
|
||||||
val passwordTextField = UncivTextField.create(
|
val passwordTextField = UncivTextField.create(
|
||||||
settings.multiplayer.passwords[settings.multiplayer.server] ?: "Password"
|
settings.multiplayer.passwords[settings.multiplayer.server] ?: "Password"
|
||||||
)
|
)
|
||||||
@ -255,11 +255,11 @@ private fun addTurnCheckerOptions(
|
|||||||
private fun successfullyConnectedToServer(action: (Boolean, Boolean) -> Unit) {
|
private fun successfullyConnectedToServer(action: (Boolean, Boolean) -> Unit) {
|
||||||
Concurrency.run("TestIsAlive") {
|
Concurrency.run("TestIsAlive") {
|
||||||
try {
|
try {
|
||||||
val connectionSuccess = UncivGame.Current.onlineMultiplayer.checkServerStatus()
|
val connectionSuccess = UncivGame.Current.onlineMultiplayer.multiplayerServer.checkServerStatus()
|
||||||
var authSuccess = false
|
var authSuccess = false
|
||||||
if (connectionSuccess) {
|
if (connectionSuccess) {
|
||||||
try {
|
try {
|
||||||
authSuccess = UncivGame.Current.onlineMultiplayer.authenticate(null)
|
authSuccess = UncivGame.Current.onlineMultiplayer.multiplayerServer.authenticate(null)
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
// We ignore the exception here, because we handle the failed auth onGLThread
|
// We ignore the exception here, because we handle the failed auth onGLThread
|
||||||
}
|
}
|
||||||
@ -289,7 +289,7 @@ private fun setPassword(password: String, optionsPopup: OptionsPopup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UncivGame.Current.onlineMultiplayer.serverFeatureSet.authVersion == 0) {
|
if (UncivGame.Current.onlineMultiplayer.multiplayerServer.featureSet.authVersion == 0) {
|
||||||
popup.reuseWith("This server does not support authentication", true)
|
popup.reuseWith("This server does not support authentication", true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -327,7 +327,7 @@ private fun setPassword(password: String, optionsPopup: OptionsPopup) {
|
|||||||
private fun successfullySetPassword(password: String, action: (Boolean, Exception?) -> Unit) {
|
private fun successfullySetPassword(password: String, action: (Boolean, Exception?) -> Unit) {
|
||||||
Concurrency.run("SetPassword") {
|
Concurrency.run("SetPassword") {
|
||||||
try {
|
try {
|
||||||
val setSuccess = UncivGame.Current.onlineMultiplayer.setPassword(password)
|
val setSuccess = UncivGame.Current.onlineMultiplayer.multiplayerServer.setPassword(password)
|
||||||
launchOnGLThread {
|
launchOnGLThread {
|
||||||
action(setSuccess, null)
|
action(setSuccess, null)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user