diff options
author | CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> | 2024-06-05 22:06:54 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-05 14:06:54 +0200 |
commit | e61f260fa2a094a43ebe1ab3d3305874dee6b716 (patch) | |
tree | b94d2f328d07a6adecfcd9bdc011cc3b7168a3c4 | |
parent | a5687208788bf54491e1341dbd5b2e99ee408221 (diff) | |
download | skyhanni-e61f260fa2a094a43ebe1ab3d3305874dee6b716.tar.gz skyhanni-e61f260fa2a094a43ebe1ab3d3305874dee6b716.tar.bz2 skyhanni-e61f260fa2a094a43ebe1ab3d3305874dee6b716.zip |
Fix: Config reset on unknown enum values (#1990)
4 files changed, 63 insertions, 1 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index b7fd4838b..4f5f0aa50 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt @@ -111,6 +111,7 @@ object ConfigUpdaterMigrator { val lastVersion = (config["lastVersion"] as? JsonPrimitive)?.asIntOrNull ?: -1 if (lastVersion > CONFIG_VERSION) { logger.log("Attempted to downgrade config version") + config.add("lastVersion", JsonPrimitive(CONFIG_VERSION)) return config } if (lastVersion == CONFIG_VERSION) return config diff --git a/src/main/java/at/hannibal2/skyhanni/utils/json/BaseGsonBuilder.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/BaseGsonBuilder.kt index d73edc0b0..bc9f706f8 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/json/BaseGsonBuilder.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/json/BaseGsonBuilder.kt @@ -33,5 +33,7 @@ object BaseGsonBuilder { .registerTypeAdapter(SimpleTimeMark::class.java, SkyHanniTypeAdapters.TIME_MARK.nullSafe()) .enableComplexMapKeySerialization() - fun lenientGson(): GsonBuilder = gson().registerTypeAdapterFactory(SkippingTypeAdapterFactory) + fun lenientGson(): GsonBuilder = gson() + .registerTypeAdapterFactory(SkippingTypeAdapterFactory) + .registerTypeAdapterFactory(ListEnumSkippingTypeAdapterFactory) } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/json/EnumSkippingTypeAdapterFactory.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/EnumSkippingTypeAdapterFactory.kt new file mode 100644 index 000000000..c17462472 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/json/EnumSkippingTypeAdapterFactory.kt @@ -0,0 +1,53 @@ +package at.hannibal2.skyhanni.utils.json + +import com.google.gson.Gson +import com.google.gson.TypeAdapter +import com.google.gson.TypeAdapterFactory +import com.google.gson.reflect.TypeToken +import com.google.gson.stream.JsonReader +import com.google.gson.stream.JsonToken +import com.google.gson.stream.JsonWriter +import java.lang.reflect.ParameterizedType + +object ListEnumSkippingTypeAdapterFactory : TypeAdapterFactory { + override fun <T> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? { + val rawType = type.rawType + if (rawType == List::class.java) { + val actualType = (type.type as ParameterizedType).actualTypeArguments[0] + if (actualType is Class<*> && actualType.isEnum) { + @Suppress("UNCHECKED_CAST") + return ListEnumSkippingTypeAdapter(actualType as Class<out Enum<*>>) as TypeAdapter<T> + } + } + return null + } +} + +/* + Instead of saving null to the config when the enum value is unknown we instead skip the value. + We also skip the value if it is null inside a list of enums. This ensures we don't crash later, + either in moulconfig or outside of it, as we assume lists of enums don't contain null values. + */ +class ListEnumSkippingTypeAdapter<T : Enum<T>>(private val enumClass: Class<T>) : TypeAdapter<List<T>>() { + override fun write(out: JsonWriter, value: List<T>?) { + value ?: return + out.beginArray() + value.forEach { out.value(it.name) } + out.endArray() + } + + override fun read(reader: JsonReader): List<T> { + val list = mutableListOf<T>() + reader.beginArray() + while (reader.hasNext()) { + if (reader.peek() == JsonToken.NULL) { + reader.skipValue() + continue + } + val name = reader.nextString() + enumClass.enumConstants.firstOrNull { it.name == name }?.let { list.add(it) } + } + reader.endArray() + return list + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/json/SkippingTypeAdapterFactory.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/SkippingTypeAdapterFactory.kt index 3a2505495..d99650f0c 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/json/SkippingTypeAdapterFactory.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/json/SkippingTypeAdapterFactory.kt @@ -8,6 +8,12 @@ import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonWriter +/* + Instead of crashing on a wrong value in the config we set the value to null and log a warning. + This prevents user's config from resetting to default values. + Which is especially important for when people downgrade their mod version, either on purpose or by accident. + This does not always work, and can cause a crash later on, but the full config reset is avoided. + */ object SkippingTypeAdapterFactory : TypeAdapterFactory { override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T> { |