aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-04-06 01:12:24 +0200
committerGitHub <noreply@github.com>2024-04-06 01:12:24 +0200
commit6c088c46709a84cf6ae6ec0b35be9d25278784c7 (patch)
treeabc3f00e07976b0072c3895333707eed4aee7435
parentaff767bb841f5e2d502c8ac0cf69e9a3c0d5781f (diff)
downloadskyhanni-6c088c46709a84cf6ae6ec0b35be9d25278784c7.tar.gz
skyhanni-6c088c46709a84cf6ae6ec0b35be9d25278784c7.tar.bz2
skyhanni-6c088c46709a84cf6ae6ec0b35be9d25278784c7.zip
Backend: Add feature toggle adapter to automatically turn on features (#581)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/FeatureTogglesByDefaultAdapter.kt79
2 files changed, 89 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
index 51ed30ff4..b81e1efb8 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt
@@ -9,6 +9,7 @@ import at.hannibal2.skyhanni.data.jsonobjects.local.VisualWordsJson
import at.hannibal2.skyhanni.data.jsonobjects.other.HypixelApiTrophyFish
import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity
import at.hannibal2.skyhanni.features.misc.update.UpdateManager
+import at.hannibal2.skyhanni.utils.FeatureTogglesByDefaultAdapter
import at.hannibal2.skyhanni.utils.KotlinTypeAdapterFactory
import at.hannibal2.skyhanni.utils.LorenzLogger
import at.hannibal2.skyhanni.utils.LorenzRarity
@@ -24,6 +25,7 @@ import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker
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.JsonToken
import com.google.gson.stream.JsonWriter
@@ -48,12 +50,20 @@ import kotlin.concurrent.fixedRateTimer
typealias TrackerDisplayMode = SkyHanniTracker.DefaultDisplayMode
+private fun GsonBuilder.reigsterIfBeta(create: TypeAdapterFactory): GsonBuilder {
+ val isBeta = SkyHanniMod.version.contains("beta", ignoreCase = true)
+ return if (isBeta) {
+ registerTypeAdapterFactory(create)
+ } else this
+}
+
class ConfigManager {
companion object {
val gson = GsonBuilder().setPrettyPrinting()
.excludeFieldsWithoutExposeAnnotation()
.serializeSpecialFloatingPointValues()
+ .reigsterIfBeta(FeatureTogglesByDefaultAdapter)
.registerTypeAdapterFactory(PropertyTypeAdapterFactory())
.registerTypeAdapterFactory(KotlinTypeAdapterFactory())
.registerTypeAdapter(UUID::class.java, object : TypeAdapter<UUID>() {
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/FeatureTogglesByDefaultAdapter.kt b/src/main/java/at/hannibal2/skyhanni/utils/FeatureTogglesByDefaultAdapter.kt
new file mode 100644
index 000000000..011dcc10c
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/FeatureTogglesByDefaultAdapter.kt
@@ -0,0 +1,79 @@
+package at.hannibal2.skyhanni.utils
+
+import at.hannibal2.skyhanni.config.FeatureToggle
+import com.google.gson.Gson
+import com.google.gson.JsonObject
+import com.google.gson.JsonPrimitive
+import com.google.gson.TypeAdapter
+import com.google.gson.TypeAdapterFactory
+import com.google.gson.internal.bind.JsonTreeReader
+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.Field
+import java.lang.reflect.Type
+import com.google.gson.internal.`$Gson$Types` as InternalGsonTypes
+
+object FeatureTogglesByDefaultAdapter : TypeAdapterFactory {
+ fun <T> getType(typeToken: TypeToken<T>, field: Field): Type {
+ return InternalGsonTypes.resolve(typeToken.type, typeToken.rawType, field.genericType)
+ }
+
+ class Adapter<T>(
+ val originalWrite: TypeAdapter<T>,
+ val clazz: Class<T>,
+ val gson: Gson,
+ val type: TypeToken<T>,
+ ) : TypeAdapter<T>() {
+ override fun write(out: JsonWriter, value: T) {
+ // Delegate the original config write, since that one is unchanged
+ originalWrite.write(out, value)
+ }
+
+ override fun read(reader: JsonReader): T {
+ reader.beginObject()
+ // Create a default initialized instance
+ val obj = clazz.newInstance()
+
+ // Overwrite the default with true (or false) for feature toggles
+ clazz.fields.forEach {
+ val featureToggle = it.getAnnotation(FeatureToggle::class.java)
+ val adapt = gson.getAdapter(TypeToken.get(getType(type, it)))
+ if (featureToggle != null)
+ it.set(obj, adapt.read(JsonTreeReader(JsonPrimitive(featureToggle.trueIsEnabled))))
+ if (adapt is Adapter) {
+ it.set(obj, adapt.read(JsonTreeReader(JsonObject())))
+ }
+ }
+
+ // Read the actual JSON Object
+ while (reader.peek() != JsonToken.END_OBJECT) {
+ val name = reader.nextName()
+ val field = clazz.getDeclaredField(name)
+ val fieldType = gson.getAdapter(TypeToken.get(getType(type, field)))
+ // Read the field data
+ val data = fieldType.read(reader)
+ // Set the field or override the feature toggle with the saved data, leaving only the unset feature toggles to deviate from their defaults
+ field.set(obj, data)
+ }
+
+ reader.endObject()
+ return obj
+ }
+ }
+
+ override fun <T : Any?> create(gson: Gson?, type: TypeToken<T>): TypeAdapter<T>? {
+ gson!!
+ val t = type.rawType
+
+ // Check if this object has any feature toggles present
+ if (t.fields.none {
+ it.isAnnotationPresent(FeatureToggle::class.java) ||
+ gson.getAdapter(TypeToken.get(getType(type, it))) is Adapter
+ }) return null
+
+ val originalWrite = gson.getDelegateAdapter(this, type)
+ return Adapter(originalWrite, t as Class<T>, gson, type)
+ }
+} \ No newline at end of file