diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/ConfigurationSerializableAdapter.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/ConfigurationSerializableAdapter.java new file mode 100644 index 0000000..35677c3 --- /dev/null +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/ConfigurationSerializableAdapter.java @@ -0,0 +1,49 @@ +package fr.pandacube.lib.paper.json; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.bind.TreeTypeAdapter; +import com.google.gson.reflect.TypeToken; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.configuration.serialization.ConfigurationSerialization; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +/* package */ class ConfigurationSerializableAdapter implements JsonSerializer, JsonDeserializer { + + public static final TypeAdapterFactory FACTORY = TreeTypeAdapter.newTypeHierarchyFactory(ConfigurationSerializable.class, new ConfigurationSerializableAdapter()); + + private static final TypeToken> MAP_STR_OBJ_TYPE = new TypeToken<>() { }; + + + private boolean isItemStack(Map deserializedMap) { + return deserializedMap.containsKey(ConfigurationSerialization.SERIALIZED_TYPE_KEY) + && deserializedMap.get(ConfigurationSerialization.SERIALIZED_TYPE_KEY) instanceof String serializedType + && ItemStack.class.equals(ConfigurationSerialization.getClassByAlias(serializedType)); + } + + @Override + public ConfigurationSerializable deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + Map deserializedMap = context.deserialize(json, MAP_STR_OBJ_TYPE.getType()); + if (isItemStack(deserializedMap)) { + ItemStackAdapter.fixDeserializationVersion(deserializedMap); + } + return ConfigurationSerialization.deserializeObject(deserializedMap); + } + + @Override + public JsonElement serialize(ConfigurationSerializable src, Type typeOfSrc, JsonSerializationContext context) { + Map values = new LinkedHashMap<>(); + values.put(ConfigurationSerialization.SERIALIZED_TYPE_KEY, ConfigurationSerialization.getAlias(src.getClass())); + values.putAll(src.serialize()); + return context.serialize(values, MAP_STR_OBJ_TYPE.getType()); + } +} diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/ItemStackAdapter.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/ItemStackAdapter.java index 3341b9e..fde3c24 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/ItemStackAdapter.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/ItemStackAdapter.java @@ -25,21 +25,7 @@ import java.util.Map; @Override public ItemStack deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { Map deserializedMap = context.deserialize(json, MAP_STR_OBJ_TYPE.getType()); - int itemStackVersion = deserializedMap.containsKey("v") ? ((Number)deserializedMap.get("v")).intValue() : -1; - if (itemStackVersion >= 0) { - @SuppressWarnings("deprecation") - int currentDataVersion = Bukkit.getUnsafe().getDataVersion(); - if (itemStackVersion > currentDataVersion) { - /* The itemStack we are deserializing is from a newer MC version, so Bukkit will refuse it. - * We decide to ignore the provided version and consider that the received item stack is from current - * version. We let Bukkit handles the deserialization with the data it can interpret, throwing an error - * only if it can't. - */ - deserializedMap.put("v", currentDataVersion); - return ItemStack.deserialize(deserializedMap); - } - } - + fixDeserializationVersion(deserializedMap); return ItemStack.deserialize(deserializedMap); } @@ -47,4 +33,24 @@ import java.util.Map; public JsonElement serialize(ItemStack src, Type typeOfSrc, JsonSerializationContext context) { return context.serialize(src.serialize(), MAP_STR_OBJ_TYPE.getType()); } + + + + /* package */ static void fixDeserializationVersion(Map deserializedMap) { + if (!deserializedMap.containsKey("v")) + return; + int itemStackVersion = ((Number)deserializedMap.get("v")).intValue(); + if (itemStackVersion >= 0) { + @SuppressWarnings("deprecation") + int currentDataVersion = Bukkit.getUnsafe().getDataVersion(); + if (itemStackVersion > currentDataVersion) { + /* Here, the itemStack we are deserializing is from a newer MC version, so Bukkit will refuse it. + * We decide to ignore the provided version and consider that the received item stack is from current + * version. We let Bukkit handles the deserialization with the data it can interpret, throwing an error + * only if it can't. + */ + deserializedMap.put("v", currentDataVersion); + } + } + } } diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/PaperJson.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/PaperJson.java index d1f1969..1d5d07a 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/PaperJson.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/json/PaperJson.java @@ -12,5 +12,6 @@ public class PaperJson { */ public static void init() { Json.registerTypeAdapterFactory(ItemStackAdapter.FACTORY); + Json.registerTypeAdapterFactory(ConfigurationSerializableAdapter.FACTORY); } }