Added checksum to be added to uploaded multiplayer games (#9483)

* Added checksum to be added to uploaded multiplayer games

* Policy adoption triggers resource recalculation
This commit is contained in:
Yair Morgenstern 2023-05-31 14:58:00 +03:00 committed by GitHub
parent de09eda043
commit ce6d3394bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 25 additions and 7 deletions

View File

@ -3,6 +3,7 @@ package com.unciv.logic
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.UncivGame.Version import com.unciv.UncivGame.Version
import com.unciv.json.json
import com.unciv.logic.BackwardCompatibility.convertEncampmentData import com.unciv.logic.BackwardCompatibility.convertEncampmentData
import com.unciv.logic.BackwardCompatibility.convertFortify import com.unciv.logic.BackwardCompatibility.convertFortify
import com.unciv.logic.BackwardCompatibility.guaranteeUnitPromotions import com.unciv.logic.BackwardCompatibility.guaranteeUnitPromotions
@ -35,9 +36,11 @@ import com.unciv.models.ruleset.nation.Difficulty
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.audio.MusicMood import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.screens.savescreens.Gzip
import com.unciv.ui.screens.worldscreen.status.NextTurnProgress import com.unciv.ui.screens.worldscreen.status.NextTurnProgress
import com.unciv.utils.DebugUtils import com.unciv.utils.DebugUtils
import com.unciv.utils.debug import com.unciv.utils.debug
import java.security.MessageDigest
import java.util.UUID import java.util.UUID
@ -100,6 +103,7 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
var currentPlayer = "" var currentPlayer = ""
var currentTurnStartTime = 0L var currentTurnStartTime = 0L
var gameId = UUID.randomUUID().toString() // random string var gameId = UUID.randomUUID().toString() // random string
var checksum = ""
var victoryData:VictoryData? = null var victoryData:VictoryData? = null
@ -272,6 +276,16 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
return year.toInt() return year.toInt()
} }
fun calculateChecksum():String {
val oldChecksum = checksum
checksum = "" // Checksum calculation cannot include old checksum, obvs
val bytes = MessageDigest
.getInstance("SHA-1")
.digest(json().toJson(this).toByteArray())
checksum = oldChecksum
return Gzip.encode(bytes)
}
//endregion //endregion
//region State changing functions //region State changing functions

View File

@ -211,6 +211,8 @@ class PolicyManager : IsPartOfGameInfoSerialization {
if (unique.conditionals.any {it.type == UniqueType.TriggerUponAdoptingPolicyOrBelief && it.params[0] == policy.name}) if (unique.conditionals.any {it.type == UniqueType.TriggerUponAdoptingPolicyOrBelief && it.params[0] == policy.name})
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, triggerNotificationText = triggerNotificationText) UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, triggerNotificationText = triggerNotificationText)
civInfo.cache.updateCivResources()
// This ALSO has the side-effect of updating the CivInfo statForNextTurn so we don't need to call it explicitly // This ALSO has the side-effect of updating the CivInfo statForNextTurn so we don't need to call it explicitly
for (cityInfo in civInfo.cities) cityInfo.cityStats.update() for (cityInfo in civInfo.cities) cityInfo.cityStats.update()

View File

@ -18,8 +18,8 @@ import com.unciv.models.metadata.GameSettings
import com.unciv.models.metadata.doMigrations import com.unciv.models.metadata.doMigrations
import com.unciv.models.metadata.isMigrationNecessary import com.unciv.models.metadata.isMigrationNecessary
import com.unciv.ui.screens.savescreens.Gzip import com.unciv.ui.screens.savescreens.Gzip
import com.unciv.utils.Log
import com.unciv.utils.Concurrency import com.unciv.utils.Concurrency
import com.unciv.utils.Log
import com.unciv.utils.debug import com.unciv.utils.debug
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import java.io.File import java.io.File
@ -371,8 +371,10 @@ class UncivFiles(
} }
/** Returns gzipped serialization of [game], optionally gzipped ([forceZip] overrides [saveZipped]) */ /** Returns gzipped serialization of [game], optionally gzipped ([forceZip] overrides [saveZipped]) */
fun gameInfoToString(game: GameInfo, forceZip: Boolean? = null): String { fun gameInfoToString(game: GameInfo, forceZip: Boolean? = null, updateChecksum:Boolean=true): String {
game.version = GameInfo.CURRENT_COMPATIBILITY_VERSION game.version = GameInfo.CURRENT_COMPATIBILITY_VERSION
if (updateChecksum) game.checksum = game.calculateChecksum()
val plainJson = json().toJson(game) val plainJson = json().toJson(game)
return if (forceZip ?: saveZipped) Gzip.zip(plainJson) else plainJson return if (forceZip ?: saveZipped) Gzip.zip(plainJson) else plainJson
} }

View File

@ -102,7 +102,7 @@ class OnlineMultiplayerServer(
* @throws MultiplayerAuthException if the authentication failed * @throws MultiplayerAuthException if the authentication failed
*/ */
suspend fun tryUploadGame(gameInfo: GameInfo, withPreview: Boolean) { suspend fun tryUploadGame(gameInfo: GameInfo, withPreview: Boolean) {
val zippedGameInfo = UncivFiles.gameInfoToString(gameInfo, forceZip = true) val zippedGameInfo = UncivFiles.gameInfoToString(gameInfo, forceZip = true, updateChecksum = true)
fileStorage().saveFileData(gameInfo.gameId, zippedGameInfo) fileStorage().saveFileData(gameInfo.gameId, zippedGameInfo)
// We upload the preview after the game because otherwise the following race condition will happen: // We upload the preview after the game because otherwise the following race condition will happen:

View File

@ -10,8 +10,8 @@ import java.util.zip.GZIPOutputStream
object Gzip { object Gzip {
fun zip(data:String):String = encoder(compress(data)) fun zip(data:String):String = encode(compress(data))
fun unzip(data:String):String = decompress(decoder(data)) fun unzip(data:String):String = decompress(decode(data))
private fun compress(data: String): ByteArray { private fun compress(data: String): ByteArray {
val bos = ByteArrayOutputStream(data.length) val bos = ByteArrayOutputStream(data.length)
@ -40,11 +40,11 @@ object Gzip {
} }
private fun encoder(bytes:ByteArray): String{ fun encode(bytes:ByteArray): String{
return String(Base64Coder.encode(bytes)) return String(Base64Coder.encode(bytes))
} }
private fun decoder(base64Str: String): ByteArray{ private fun decode(base64Str: String): ByteArray{
return Base64Coder.decode(base64Str) return Base64Coder.decode(base64Str)
} }
} }