mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-11 11:28:03 +07:00
* Fix old barbarian camps not being properly loaded after 86d5011
* Fix first load resulting in error
This commit is contained in:
parent
d00b72806b
commit
7c24b0b6af
@ -9,15 +9,19 @@ import java.util.HashMap
|
||||
*/
|
||||
class HashMapVector2<T> : HashMap<Vector2, T>() {
|
||||
companion object {
|
||||
init {
|
||||
fun createSerializer(): NonStringKeyMapSerializer<MutableMap<Vector2, Any>, Vector2> {
|
||||
@Suppress("UNCHECKED_CAST") // kotlin can't tell that HashMapVector2 is also a MutableMap within generics
|
||||
val mapClass = HashMapVector2::class.java as Class<MutableMap<Vector2, Any>>
|
||||
val serializer = NonStringKeyMapSerializer(
|
||||
return NonStringKeyMapSerializer(
|
||||
mapClass,
|
||||
Vector2::class.java,
|
||||
{ HashMapVector2<Any>() }
|
||||
{ HashMapVector2() }
|
||||
)
|
||||
jsonSerializers.add(Pair(mapClass, serializer))
|
||||
}
|
||||
|
||||
fun getSerializerClass(): Class<MutableMap<Vector2, Any>> {
|
||||
@Suppress("UNCHECKED_CAST") // kotlin can't tell that HashMapVector2 is also a MutableMap within generics
|
||||
return HashMapVector2::class.java as Class<MutableMap<Vector2, Any>>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,14 +40,36 @@ class NonStringKeyMapSerializer<MT: MutableMap<KT, Any>, KT>(
|
||||
override fun read(json: Json, jsonData: JsonValue, type: Class<*>?): MT {
|
||||
val result = mutableMapFactory()
|
||||
val entries = jsonData.get("entries")
|
||||
var entry = entries!!.child
|
||||
while (entry != null) {
|
||||
val key = json.readValue(keyClass, entry.child)
|
||||
val value = json.readValue<Any>(null, entry.child.next)
|
||||
result[key!!] = value!! as Any
|
||||
|
||||
entry = entry.next
|
||||
if (entries == null) {
|
||||
readOldFormat(jsonData, json, result)
|
||||
} else {
|
||||
readNewFormat(entries!!, json, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@Deprecated("This is only here temporarily until all users migrate the old properties to the new ones")
|
||||
private fun readOldFormat(jsonData: JsonValue, json: Json, result: MT) {
|
||||
val map = result as MutableMap<String, Any>
|
||||
var child: JsonValue? = jsonData.child
|
||||
while (child != null) {
|
||||
if (child.name == "class") {
|
||||
child = child.next
|
||||
continue
|
||||
}
|
||||
map[child.name] = json.readValue(null, child)
|
||||
child = child.next
|
||||
}
|
||||
}
|
||||
|
||||
private fun readNewFormat(entries: JsonValue, json: Json, result: MT) {
|
||||
var entry = entries.child
|
||||
while (entry != null) {
|
||||
val key = json.readValue(keyClass, entry.child)
|
||||
val value = json.readValue<Any>(null, entry.child.next)
|
||||
result[key!!] = value!!
|
||||
|
||||
entry = entry.next
|
||||
}
|
||||
}
|
||||
}
|
@ -2,21 +2,19 @@ package com.unciv.json
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.badlogic.gdx.utils.Json
|
||||
import com.badlogic.gdx.utils.Json.Serializer
|
||||
|
||||
internal val jsonSerializers = ArrayList<Pair<Class<*>, Serializer<*>>>()
|
||||
|
||||
/**
|
||||
* [Json] is not thread-safe.
|
||||
* [Json] is not thread-safe. Use a new one for each parse.
|
||||
*/
|
||||
fun json() = Json().apply {
|
||||
setIgnoreDeprecated(true)
|
||||
ignoreUnknownFields = true
|
||||
for ((clazz, serializer) in jsonSerializers) {
|
||||
@Suppress("UNCHECKED_CAST") // we used * to accept all types, so kotlin can't know if the class & serializer parameters are actually the same
|
||||
setSerializer(clazz as Class<Any>, serializer as Serializer<Any>)
|
||||
}
|
||||
|
||||
setSerializer(HashMapVector2.getSerializerClass(), HashMapVector2.createSerializer())
|
||||
}
|
||||
|
||||
fun <T> Json.fromJsonFile(tClass: Class<T>, filePath: String): T = fromJsonFile(tClass, Gdx.files.internal(filePath))
|
||||
|
@ -1,6 +1,9 @@
|
||||
package com.unciv.logic
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.badlogic.gdx.utils.JsonValue
|
||||
import com.unciv.json.HashMapVector2
|
||||
import com.unciv.json.json
|
||||
import com.unciv.logic.city.CityConstructions
|
||||
import com.unciv.logic.city.PerpetualConstruction
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
@ -159,4 +162,38 @@ object BackwardCompatibility {
|
||||
lastSeenImprovement.putAll(lastSeenImprovementSaved.mapKeys { Vector2().fromString(it.key) })
|
||||
lastSeenImprovementSaved.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes barbarian manager camps not being correctly serialized. Previously we had a [HashMap<Vector2, Encampment] but it was being
|
||||
* serialized as [HashMap<String, Encampment>]. We need to fix that each time an old save is loaded.
|
||||
*
|
||||
* When removing this, also remove [com.unciv.json.NonStringKeyMapSerializer.readOldFormat]
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
fun BarbarianManager.migrateBarbarianCamps() {
|
||||
if (isOldFormat(this)) {
|
||||
val newFormat = HashMapVector2<Encampment>()
|
||||
@Suppress("UNCHECKED_CAST") // The old format is deserialized to a <String, JsonValue> map
|
||||
for ((key, value) in camps as MutableMap<String, JsonValue>) {
|
||||
val newKey = Vector2().fromString(key)
|
||||
val newValue = json().readValue(Encampment::class.java, value)
|
||||
newFormat[newKey] = newValue
|
||||
}
|
||||
|
||||
camps.clear()
|
||||
camps.putAll(newFormat)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isOldFormat(manager: BarbarianManager): Boolean {
|
||||
val keys = manager.camps.keys as Set<Any>
|
||||
val iterator = keys.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val key = iterator.next()
|
||||
if (key is String) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.unciv.logic
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.BackwardCompatibility.guaranteeUnitPromotions
|
||||
import com.unciv.logic.BackwardCompatibility.migrateBarbarianCamps
|
||||
import com.unciv.logic.BackwardCompatibility.migrateSeenImprovements
|
||||
import com.unciv.logic.BackwardCompatibility.removeMissingModReferences
|
||||
import com.unciv.logic.automation.NextTurnAutomation
|
||||
@ -398,6 +399,7 @@ class GameInfo {
|
||||
}
|
||||
// [TEMPORARY] Convert old saves to remove json workaround
|
||||
for (civInfo in civilizations) civInfo.migrateSeenImprovements()
|
||||
barbarians.migrateBarbarianCamps()
|
||||
|
||||
ruleSet = RulesetCache.getComplexRuleset(gameParameters)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user