aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalMWolfs <94038482+CalMWolfs@users.noreply.github.com>2024-06-04 04:16:22 +1000
committerGitHub <noreply@github.com>2024-06-03 20:16:22 +0200
commitaa66334dba2c2c086b94eab1767abd4765e006f7 (patch)
tree42c9cc1d76f1d331a42c0bee2e55830168e6f85a
parentfde5544ca7a49f8315318a249607769aee87661c (diff)
downloadskyhanni-aa66334dba2c2c086b94eab1767abd4765e006f7.tar.gz
skyhanni-aa66334dba2c2c086b94eab1767abd4765e006f7.tar.bz2
skyhanni-aa66334dba2c2c086b94eab1767abd4765e006f7.zip
Fix: Config resetting on wrong value (#1979)
Co-authored-by: Brady <brady@thatgravyboat.tech>
-rw-r--r--.idea/dictionaries/default_user.xml1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt134
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt26
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarDataHolder.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/BaseGsonBuilder.kt37
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/FeatureTogglesByDefaultAdapter.kt (renamed from src/main/java/at/hannibal2/skyhanni/utils/FeatureTogglesByDefaultAdapter.kt)2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/ItemStackTypeAdapter.kt (renamed from src/main/java/at/hannibal2/skyhanni/utils/ItemStackTypeAdapter.kt)2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/JsonUtils.kt (renamed from src/main/java/at/hannibal2/skyhanni/utils/JsonUtils.kt)2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/NBTTypeAdapter.kt (renamed from src/main/java/at/hannibal2/skyhanni/utils/NBTTypeAdapter.kt)2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/SimpleStringTypeAdapter.kt29
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/SkippingTypeAdapterFactory.kt32
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt79
21 files changed, 214 insertions, 166 deletions
diff --git a/.idea/dictionaries/default_user.xml b/.idea/dictionaries/default_user.xml
index 62935a97c..1cc3cc669 100644
--- a/.idea/dictionaries/default_user.xml
+++ b/.idea/dictionaries/default_user.xml
@@ -77,6 +77,7 @@
<w>inquis</w>
<w>inquistiors</w>
<w>interp</w>
+ <w>itemstack</w>
<w>jawbus</w>
<w>jerries</w>
<w>jerrypocalypse</w>
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
index 16b0fcfa3..fc654983c 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
@@ -2,42 +2,28 @@ package at.hannibal2.skyhanni.config
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.config.core.config.Position
-import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.data.jsonobjects.local.FriendsJson
import at.hannibal2.skyhanni.data.jsonobjects.local.JacobContestsJson
import at.hannibal2.skyhanni.data.jsonobjects.local.KnownFeaturesJson
import at.hannibal2.skyhanni.data.jsonobjects.local.VisualWordsJson
import at.hannibal2.skyhanni.events.LorenzEvent
-import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity
import at.hannibal2.skyhanni.features.misc.update.UpdateManager
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.DelayedRun
import at.hannibal2.skyhanni.utils.IdentityCharacteristics
-import at.hannibal2.skyhanni.utils.KotlinTypeAdapterFactory
import at.hannibal2.skyhanni.utils.LorenzLogger
-import at.hannibal2.skyhanni.utils.LorenzRarity
import at.hannibal2.skyhanni.utils.LorenzUtils
-import at.hannibal2.skyhanni.utils.LorenzVec
-import at.hannibal2.skyhanni.utils.NEUInternalName
-import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
-import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.SimpleTimeMark
-import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.asTimeMark
-import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker
+import at.hannibal2.skyhanni.utils.json.BaseGsonBuilder
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject
-import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
-import com.google.gson.stream.JsonReader
-import com.google.gson.stream.JsonWriter
import io.github.notenoughupdates.moulconfig.annotations.ConfigLink
-import io.github.notenoughupdates.moulconfig.observer.PropertyTypeAdapterFactory
import io.github.notenoughupdates.moulconfig.processor.BuiltinMoulConfigGuis
import io.github.notenoughupdates.moulconfig.processor.ConfigProcessorDriver
import io.github.notenoughupdates.moulconfig.processor.MoulConfigProcessor
-import net.minecraft.item.ItemStack
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.File
@@ -49,12 +35,9 @@ import java.io.OutputStreamWriter
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.StandardCopyOption
-import java.util.UUID
import kotlin.concurrent.fixedRateTimer
-typealias TrackerDisplayMode = SkyHanniTracker.DefaultDisplayMode
-
-private fun GsonBuilder.reigsterIfBeta(create: TypeAdapterFactory): GsonBuilder {
+private fun GsonBuilder.registerIfBeta(create: TypeAdapterFactory): GsonBuilder {
return if (LorenzUtils.isBetaVersion()) {
registerTypeAdapterFactory(create)
} else this
@@ -62,114 +45,12 @@ private fun GsonBuilder.reigsterIfBeta(create: TypeAdapterFactory): GsonBuilder
class ConfigManager {
companion object {
- fun createBaseGsonBuilder(): GsonBuilder {
- return GsonBuilder().setPrettyPrinting()
- .excludeFieldsWithoutExposeAnnotation()
- .serializeSpecialFloatingPointValues()
- .registerTypeAdapterFactory(PropertyTypeAdapterFactory())
- .registerTypeAdapterFactory(KotlinTypeAdapterFactory())
- .registerTypeAdapter(UUID::class.java, object : TypeAdapter<UUID>() {
- override fun write(out: JsonWriter, value: UUID) {
- out.value(value.toString())
- }
-
- override fun read(reader: JsonReader): UUID {
- return UUID.fromString(reader.nextString())
- }
- }.nullSafe())
- .registerTypeAdapter(LorenzVec::class.java, object : TypeAdapter<LorenzVec>() {
- override fun write(out: JsonWriter, value: LorenzVec) {
- value.run { out.value("$x:$y:$z") }
- }
-
- override fun read(reader: JsonReader): LorenzVec {
- return LorenzVec.decodeFromString(reader.nextString())
- }
- }.nullSafe())
- .registerTypeAdapter(TrophyRarity::class.java, object : TypeAdapter<TrophyRarity>() {
- override fun write(out: JsonWriter, value: TrophyRarity) {
- value.run { out.value(value.name) }
- }
- override fun read(reader: JsonReader): TrophyRarity {
- val text = reader.nextString()
- return TrophyRarity.getByName(text) ?: error("Could not parse TrophyRarity from '$text'")
- }
- }.nullSafe())
- .registerTypeAdapter(ItemStack::class.java, object : TypeAdapter<ItemStack>() {
- override fun write(out: JsonWriter, value: ItemStack) {
- out.value(NEUItems.saveNBTData(value))
- }
-
- override fun read(reader: JsonReader): ItemStack {
- return NEUItems.loadNBTData(reader.nextString())
- }
- }.nullSafe())
- .registerTypeAdapter(NEUInternalName::class.java, object : TypeAdapter<NEUInternalName>() {
- override fun write(out: JsonWriter, value: NEUInternalName) {
- out.value(value.asString())
- }
-
- override fun read(reader: JsonReader): NEUInternalName {
- return reader.nextString().asInternalName()
- }
- }.nullSafe())
- .registerTypeAdapter(LorenzRarity::class.java, object : TypeAdapter<LorenzRarity>() {
- override fun write(out: JsonWriter, value: LorenzRarity) {
- out.value(value.name)
- }
-
- override fun read(reader: JsonReader): LorenzRarity {
- return LorenzRarity.valueOf(reader.nextString().uppercase().replace(" ", "_"))
- }
- }.nullSafe())
- .registerTypeAdapter(IslandType::class.java, object : TypeAdapter<IslandType>() {
- override fun write(out: JsonWriter, value: IslandType) {
- out.value(value.name)
- }
-
- override fun read(reader: JsonReader): IslandType {
- return IslandType.valueOf(reader.nextString().uppercase())
- }
- }.nullSafe())
- .registerTypeAdapter(TrackerDisplayMode::class.java, object : TypeAdapter<TrackerDisplayMode>() {
- override fun write(out: JsonWriter, value: TrackerDisplayMode) {
- out.value(value.name)
- }
-
- override fun read(reader: JsonReader): TrackerDisplayMode {
- return TrackerDisplayMode.valueOf(reader.nextString())
- }
- }.nullSafe())
- .registerTypeAdapter(SimpleTimeMark::class.java, object : TypeAdapter<SimpleTimeMark>() {
- override fun write(out: JsonWriter, value: SimpleTimeMark) {
- out.value(value.toMillis())
- }
-
- override fun read(reader: JsonReader): SimpleTimeMark {
- return reader.nextString().toLong().asTimeMark()
- }
- }.nullSafe())
- .enableComplexMapKeySerialization()
- }
-
- val gson: Gson = createBaseGsonBuilder()
- // TODO reenable with toggle that is default disabled
-// .reigsterIfBeta(FeatureTogglesByDefaultAdapter)
+ val gson: Gson = BaseGsonBuilder.gson()
+// .registerIfBeta(FeatureTogglesByDefaultAdapter)
.create()
var configDirectory = File("config/skyhanni")
-
- inline fun <reified T> GsonBuilder.registerTypeAdapter(
- crossinline write: (JsonWriter, T) -> Unit,
- crossinline read: (JsonReader) -> T,
- ): GsonBuilder {
- this.registerTypeAdapter(T::class.java, object : TypeAdapter<T>() {
- override fun write(out: JsonWriter, value: T) = write(out, value)
- override fun read(reader: JsonReader) = read(reader)
- }.nullSafe())
- return this
- }
}
val features get() = jsonHolder[ConfigFileType.FEATURES] as Features
@@ -281,13 +162,14 @@ class ConfigManager {
try {
val inputStreamReader = InputStreamReader(FileInputStream(file), StandardCharsets.UTF_8)
val bufferedReader = BufferedReader(inputStreamReader)
+ val lenientGson = BaseGsonBuilder.lenientGson().create()
logger.log("load-$fileName-now")
output = if (fileType == ConfigFileType.FEATURES) {
- val jsonObject = gson.fromJson(bufferedReader.readText(), JsonObject::class.java)
+ val jsonObject = lenientGson.fromJson(bufferedReader.readText(), JsonObject::class.java)
val newJsonObject = ConfigUpdaterMigrator.fixConfig(jsonObject)
- val run = { gson.fromJson(newJsonObject, defaultValue.javaClass) }
+ val run = { lenientGson.fromJson(newJsonObject, defaultValue.javaClass) }
if (LorenzUtils.isInDevEnvironment()) {
try {
run()
@@ -299,7 +181,7 @@ class ConfigManager {
run()
}
} else {
- gson.fromJson(bufferedReader.readText(), defaultValue.javaClass)
+ lenientGson.fromJson(bufferedReader.readText(), defaultValue.javaClass)
}
logger.log("Loaded $fileName from file")
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
index 56118f4db..b7fd4838b 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt
@@ -4,7 +4,7 @@ import at.hannibal2.skyhanni.events.LorenzEvent
import at.hannibal2.skyhanni.features.misc.limbo.LimboTimeTracker
import at.hannibal2.skyhanni.utils.LorenzLogger
import at.hannibal2.skyhanni.utils.LorenzUtils.asIntOrNull
-import at.hannibal2.skyhanni.utils.shDeepCopy
+import at.hannibal2.skyhanni.utils.json.shDeepCopy
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
@@ -110,7 +110,8 @@ object ConfigUpdaterMigrator {
fun fixConfig(config: JsonObject): JsonObject {
val lastVersion = (config["lastVersion"] as? JsonPrimitive)?.asIntOrNull ?: -1
if (lastVersion > CONFIG_VERSION) {
- error("Cannot downgrade config")
+ logger.log("Attempted to downgrade config version")
+ return config
}
if (lastVersion == CONFIG_VERSION) return config
return (lastVersion until CONFIG_VERSION).fold(config) { accumulator, i ->
diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt
index 666713c70..584d2291f 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt
@@ -19,7 +19,7 @@ import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.asTimeMark
import at.hannibal2.skyhanni.utils.SkyBlockTime
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.fromJson
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
diff --git a/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt b/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt
index db39e98c5..6ed9b8e6a 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt
@@ -13,7 +13,7 @@ import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.NEUItems.getItemStackOrNull
import at.hannibal2.skyhanni.utils.SimpleTimeMark
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.fromJson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt
index b9fba9ca0..3c0118089 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/local/HotmTree.kt
@@ -1,6 +1,6 @@
package at.hannibal2.skyhanni.data.jsonobjects.local;
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.fromJson
import com.google.gson.Gson
import com.google.gson.annotations.Expose
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
index b6e6f7b8e..c25a567fb 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt
@@ -1,8 +1,8 @@
package at.hannibal2.skyhanni.data.model
-import at.hannibal2.skyhanni.config.ConfigManager.Companion.registerTypeAdapter
import at.hannibal2.skyhanni.utils.LorenzVec
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.SkyHanniTypeAdapters.registerTypeAdapter
+import at.hannibal2.skyhanni.utils.json.fromJson
import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import com.google.gson.annotations.Expose
@@ -36,8 +36,7 @@ value class Graph(
override fun lastIndexOf(element: GraphNode) = graph.lastIndexOf(element)
companion object {
- val gson = GsonBuilder().setPrettyPrinting()
- /* ConfigManager.createBaseGsonBuilder() */.registerTypeAdapter<Graph>({ out, value ->
+ val gson = GsonBuilder().setPrettyPrinting().registerTypeAdapter<Graph>({ out, value ->
out.beginObject()
value.forEach {
out.name(it.id.toString()).beginObject()
diff --git a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
index bb741ae80..a02cb308f 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
@@ -3,7 +3,7 @@ package at.hannibal2.skyhanni.events
import at.hannibal2.skyhanni.config.ConfigManager
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.NEUItems.manager
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.fromJson
import com.google.gson.JsonObject
import com.google.gson.JsonSyntaxException
import java.io.File
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt
index 3025ae7d1..6f8523c34 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt
@@ -1,7 +1,6 @@
package at.hannibal2.skyhanni.features.garden.farming
import at.hannibal2.skyhanni.SkyHanniMod
-import at.hannibal2.skyhanni.config.ConfigManager
import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.config.enums.OutsideSbFeature
import at.hannibal2.skyhanni.data.HypixelData
@@ -30,12 +29,11 @@ import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.StringUtils
import at.hannibal2.skyhanni.utils.TimeUtils
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.BaseGsonBuilder
+import at.hannibal2.skyhanni.utils.json.SkyHanniTypeAdapters
+import at.hannibal2.skyhanni.utils.json.fromJson
import at.hannibal2.skyhanni.utils.renderables.Renderable
import com.google.gson.JsonObject
-import com.google.gson.TypeAdapter
-import com.google.gson.stream.JsonReader
-import com.google.gson.stream.JsonWriter
import kotlinx.coroutines.launch
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.time.Duration.Companion.minutes
@@ -132,21 +130,9 @@ class FarmingWeightDisplay {
}
private val eliteWeightApiGson by lazy {
- ConfigManager.createBaseGsonBuilder()
- .registerTypeAdapter(CropType::class.java, object : TypeAdapter<CropType>() {
- override fun write(out: JsonWriter, value: CropType) {}
-
- override fun read(reader: JsonReader): CropType {
- return CropType.getByName(reader.nextString())
- }
- }.nullSafe())
- .registerTypeAdapter(PestType::class.java, object : TypeAdapter<PestType>() {
- override fun write(out: JsonWriter, value: PestType) {}
-
- override fun read(reader: JsonReader): PestType {
- return PestType.getByName(reader.nextString())
- }
- }.nullSafe())
+ BaseGsonBuilder.gson()
+ .registerTypeAdapter(CropType::class.java, SkyHanniTypeAdapters.CROP_TYPE.nullSafe())
+ .registerTypeAdapter(PestType::class.java, SkyHanniTypeAdapters.PEST_TYPE.nullSafe())
.create()
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarDataHolder.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarDataHolder.kt
index 8911e1e2b..3d7867ad9 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarDataHolder.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarDataHolder.kt
@@ -8,7 +8,7 @@ import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.APIUtil
import at.hannibal2.skyhanni.utils.NEUInternalName
import at.hannibal2.skyhanni.utils.NEUItems
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.fromJson
import kotlinx.coroutines.launch
class BazaarDataHolder {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt
index 6fa28a83b..698335f27 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt
@@ -19,7 +19,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.TimeUtils
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.fromJson
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import com.google.gson.JsonPrimitive
import kotlinx.coroutines.launch
diff --git a/src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt b/src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt
index 44a147c07..303c41bbe 100644
--- a/src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt
+++ b/src/main/java/at/hannibal2/skyhanni/test/TestExportTools.kt
@@ -5,13 +5,13 @@ import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.events.GuiKeyPressEvent
import at.hannibal2.skyhanni.test.command.CopyItemCommand.copyItemToClipboard
import at.hannibal2.skyhanni.utils.ChatUtils
-import at.hannibal2.skyhanni.utils.ItemStackTypeAdapterFactory
import at.hannibal2.skyhanni.utils.KSerializable
import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld
import at.hannibal2.skyhanni.utils.KotlinTypeAdapterFactory
-import at.hannibal2.skyhanni.utils.NBTTypeAdapter
import at.hannibal2.skyhanni.utils.OSUtils
-import at.hannibal2.skyhanni.utils.fromJson
+import at.hannibal2.skyhanni.utils.json.ItemStackTypeAdapterFactory
+import at.hannibal2.skyhanni.utils.json.NBTTypeAdapter
+import at.hannibal2.skyhanni.utils.json.fromJson
import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import net.minecraft.item.ItemStack
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
index b3d92e68f..297a40585 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
@@ -15,6 +15,8 @@ import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
import at.hannibal2.skyhanni.utils.NumberUtil.isInt
import at.hannibal2.skyhanni.utils.PrimitiveItemStack.Companion.makePrimitiveStack
+import at.hannibal2.skyhanni.utils.json.BaseGsonBuilder
+import at.hannibal2.skyhanni.utils.json.fromJson
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.TypeAdapter
@@ -51,7 +53,7 @@ object NEUItems {
private val ingredientsCache = mutableMapOf<NeuRecipe, Set<Ingredient>>()
private val hypixelApiGson by lazy {
- ConfigManager.createBaseGsonBuilder()
+ BaseGsonBuilder.gson()
.registerTypeAdapter(HypixelApiTrophyFish::class.java, object : TypeAdapter<HypixelApiTrophyFish>() {
override fun write(out: JsonWriter, value: HypixelApiTrophyFish) {}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/json/BaseGsonBuilder.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/BaseGsonBuilder.kt
new file mode 100644
index 000000000..d73edc0b0
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/BaseGsonBuilder.kt
@@ -0,0 +1,37 @@
+package at.hannibal2.skyhanni.utils.json
+
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity
+import at.hannibal2.skyhanni.utils.KotlinTypeAdapterFactory
+import at.hannibal2.skyhanni.utils.LorenzRarity
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker
+import com.google.gson.GsonBuilder
+import io.github.notenoughupdates.moulconfig.observer.PropertyTypeAdapterFactory
+import net.minecraft.item.ItemStack
+import java.util.UUID
+
+object BaseGsonBuilder {
+ fun gson(): GsonBuilder = GsonBuilder().setPrettyPrinting()
+ .excludeFieldsWithoutExposeAnnotation()
+ .serializeSpecialFloatingPointValues()
+ .registerTypeAdapterFactory(PropertyTypeAdapterFactory())
+ .registerTypeAdapterFactory(KotlinTypeAdapterFactory())
+ .registerTypeAdapter(UUID::class.java, SkyHanniTypeAdapters.UUID.nullSafe())
+ .registerTypeAdapter(LorenzVec::class.java, SkyHanniTypeAdapters.VEC_STRING.nullSafe())
+ .registerTypeAdapter(TrophyRarity::class.java, SkyHanniTypeAdapters.TROPHY_RARITY.nullSafe())
+ .registerTypeAdapter(ItemStack::class.java, SkyHanniTypeAdapters.NEU_ITEMSTACK.nullSafe())
+ .registerTypeAdapter(NEUInternalName::class.java, SkyHanniTypeAdapters.INTERNAL_NAME.nullSafe())
+ .registerTypeAdapter(LorenzRarity::class.java, SkyHanniTypeAdapters.RARITY.nullSafe())
+ .registerTypeAdapter(IslandType::class.java, SkyHanniTypeAdapters.ISLAND_TYPE.nullSafe())
+ .registerTypeAdapter(
+ SkyHanniTracker.DefaultDisplayMode::class.java,
+ SkyHanniTypeAdapters.TRACKER_DISPLAY_MODE.nullSafe()
+ )
+ .registerTypeAdapter(SimpleTimeMark::class.java, SkyHanniTypeAdapters.TIME_MARK.nullSafe())
+ .enableComplexMapKeySerialization()
+
+ fun lenientGson(): GsonBuilder = gson().registerTypeAdapterFactory(SkippingTypeAdapterFactory)
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/FeatureTogglesByDefaultAdapter.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/FeatureTogglesByDefaultAdapter.kt
index f78a0c4dc..bcc9c2edf 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/FeatureTogglesByDefaultAdapter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/FeatureTogglesByDefaultAdapter.kt
@@ -1,4 +1,4 @@
-package at.hannibal2.skyhanni.utils
+package at.hannibal2.skyhanni.utils.json
import at.hannibal2.skyhanni.config.FeatureToggle
import at.hannibal2.skyhanni.utils.ReflectionUtils.getDeclaredFieldOrNull
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ItemStackTypeAdapter.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/ItemStackTypeAdapter.kt
index 602bffa2d..1940b03c0 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/ItemStackTypeAdapter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/ItemStackTypeAdapter.kt
@@ -1,4 +1,4 @@
-package at.hannibal2.skyhanni.utils
+package at.hannibal2.skyhanni.utils.json
import com.google.gson.Gson
import com.google.gson.TypeAdapter
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/JsonUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/JsonUtils.kt
index cc3dda044..750bd96aa 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/JsonUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/JsonUtils.kt
@@ -1,4 +1,4 @@
-package at.hannibal2.skyhanni.utils
+package at.hannibal2.skyhanni.utils.json
import com.google.gson.Gson
import com.google.gson.JsonArray
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NBTTypeAdapter.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/NBTTypeAdapter.kt
index 4e0762895..e2e782636 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/NBTTypeAdapter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/NBTTypeAdapter.kt
@@ -1,4 +1,4 @@
-package at.hannibal2.skyhanni.utils
+package at.hannibal2.skyhanni.utils.json
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/json/SimpleStringTypeAdapter.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/SimpleStringTypeAdapter.kt
new file mode 100644
index 000000000..21f601932
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/SimpleStringTypeAdapter.kt
@@ -0,0 +1,29 @@
+package at.hannibal2.skyhanni.utils.json
+
+import com.google.gson.TypeAdapter
+import com.google.gson.stream.JsonReader
+import com.google.gson.stream.JsonWriter
+
+class SimpleStringTypeAdapter<T>(
+ val serializer: T.() -> String,
+ val deserializer: String.() -> T
+) : TypeAdapter<T>() {
+
+ override fun write(writer: JsonWriter, value: T) {
+ writer.value(serializer(value))
+ }
+
+ override fun read(reader: JsonReader): T {
+ return deserializer(reader.nextString())
+ }
+
+ companion object {
+
+ inline fun <reified T : Enum<T>> forEnum(): SimpleStringTypeAdapter<T> {
+ return SimpleStringTypeAdapter(
+ { name },
+ { enumValueOf(this.replace(" ", "_").uppercase()) }
+ )
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/json/SkippingTypeAdapterFactory.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/SkippingTypeAdapterFactory.kt
new file mode 100644
index 000000000..a926976ca
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/SkippingTypeAdapterFactory.kt
@@ -0,0 +1,32 @@
+package at.hannibal2.skyhanni.utils.json
+
+import at.hannibal2.skyhanni.SkyHanniMod
+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.JsonWriter
+
+object SkippingTypeAdapterFactory : TypeAdapterFactory {
+
+ override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T> {
+ return SafeTypeAdapter(gson.getDelegateAdapter(this, type))
+ }
+
+ private class SafeTypeAdapter<T>(val parent: TypeAdapter<T>) : TypeAdapter<T>() {
+ override fun write(writer: JsonWriter, value: T) {
+ parent.write(writer, value)
+ }
+
+ override fun read(reader: JsonReader): T? {
+ return try {
+ parent.read(reader)
+ } catch (e: Exception) {
+ SkyHanniMod.logger.warn("Failed to read value from JSON, skipping", e)
+ reader.skipValue()
+ null
+ }
+ }
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt
new file mode 100644
index 000000000..dc50eef74
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt
@@ -0,0 +1,79 @@
+package at.hannibal2.skyhanni.utils.json
+
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity
+import at.hannibal2.skyhanni.features.garden.CropType
+import at.hannibal2.skyhanni.features.garden.pests.PestType
+import at.hannibal2.skyhanni.utils.LorenzRarity
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+import at.hannibal2.skyhanni.utils.NEUItems
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.asTimeMark
+import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker
+import com.google.gson.GsonBuilder
+import com.google.gson.TypeAdapter
+import com.google.gson.stream.JsonReader
+import com.google.gson.stream.JsonWriter
+import net.minecraft.item.ItemStack
+import java.util.UUID
+
+object SkyHanniTypeAdapters {
+ val NEU_ITEMSTACK: TypeAdapter<ItemStack> = SimpleStringTypeAdapter(NEUItems::saveNBTData, NEUItems::loadNBTData)
+
+ val UUID: TypeAdapter<UUID> = SimpleStringTypeAdapter(
+ { this.toString() },
+ { java.util.UUID.fromString(this) }
+ )
+
+ val INTERNAL_NAME: TypeAdapter<NEUInternalName> = SimpleStringTypeAdapter(
+ { this.asString() },
+ { this.asInternalName() }
+ )
+
+ val VEC_STRING: TypeAdapter<LorenzVec> = SimpleStringTypeAdapter(
+ { "$x:$y:$z" },
+ { LorenzVec.decodeFromString(this) }
+ )
+
+ val TROPHY_RARITY: TypeAdapter<TrophyRarity> = SimpleStringTypeAdapter(
+ { name },
+ { TrophyRarity.getByName(this) ?: error("Could not parse TrophyRarity from '$this'") }
+ )
+
+ val TIME_MARK: TypeAdapter<SimpleTimeMark> = object : TypeAdapter<SimpleTimeMark>() {
+ override fun write(out: JsonWriter, value: SimpleTimeMark) {
+ out.value(value.toMillis())
+ }
+
+ override fun read(reader: JsonReader): SimpleTimeMark {
+ return reader.nextString().toLong().asTimeMark()
+ }
+ }
+
+ val CROP_TYPE: TypeAdapter<CropType> = SimpleStringTypeAdapter(
+ { name },
+ { CropType.getByName(this) }
+ )
+
+ val PEST_TYPE: TypeAdapter<PestType> = SimpleStringTypeAdapter(
+ { name },
+ { PestType.getByName(this) }
+ )
+
+ val TRACKER_DISPLAY_MODE = SimpleStringTypeAdapter.forEnum<SkyHanniTracker.DefaultDisplayMode>()
+ val ISLAND_TYPE = SimpleStringTypeAdapter.forEnum<IslandType>()
+ val RARITY = SimpleStringTypeAdapter.forEnum<LorenzRarity>()
+
+ inline fun <reified T> GsonBuilder.registerTypeAdapter(
+ crossinline write: (JsonWriter, T) -> Unit,
+ crossinline read: (JsonReader) -> T,
+ ): GsonBuilder {
+ this.registerTypeAdapter(T::class.java, object : TypeAdapter<T>() {
+ override fun write(out: JsonWriter, value: T) = write(out, value)
+ override fun read(reader: JsonReader) = read(reader)
+ }.nullSafe())
+ return this
+ }
+}