Skip to content

Commit

Permalink
Merge pull request #2614 from BentoBoxWorld/tag_serialization
Browse files Browse the repository at this point in the history
Added GSON serialization for Tags
  • Loading branch information
tastybento authored Feb 4, 2025
2 parents 3c8c1d4 + 1d76fe7 commit c18e848
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 16 deletions.
32 changes: 16 additions & 16 deletions src/main/java/world/bentobox/bentobox/api/user/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -643,22 +643,22 @@ public void sendRawMessage(String message) {

// Apply the first valid click event or hover event encountered
switch (actionType) {
case "RUN_COMMAND":
case "SUGGEST_COMMAND":
case "COPY_TO_CLIPBOARD":
case "OPEN_URL":
if (clickEvent == null) {
clickEvent = new ClickEvent(ClickEvent.Action.valueOf(actionType), actionValue);
}
break;
case "HOVER":
if (hoverEvent == null) {
hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(actionValue));
}
break;
default:
// Unrecognized command; preserve it in the output text
baseComponent.addExtra(TextComponent.fromLegacy(matcher.group(0)));
case "RUN_COMMAND":
case "SUGGEST_COMMAND":
case "COPY_TO_CLIPBOARD":
case "OPEN_URL":
if (clickEvent == null) {
clickEvent = new ClickEvent(ClickEvent.Action.valueOf(actionType), actionValue);
}
break;
case "HOVER":
if (hoverEvent == null) {
hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(actionValue));
}
break;
default:
// Unrecognized command; preserve it in the output text
baseComponent.addExtra(TextComponent.fromLegacy(matcher.group(0)));
}

} else if (matcher.group(3) != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseConnector;
import world.bentobox.bentobox.database.json.adapters.TagTypeAdapterFactory;

/**
* Abstract class that handles insert/select-operations into/from a database.
Expand Down Expand Up @@ -37,6 +38,7 @@ protected AbstractJSONDatabaseHandler(BentoBox plugin, Class<T> type, DatabaseCo
GsonBuilder builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().enableComplexMapKeySerialization().setPrettyPrinting();
// Register adapter factory
builder.registerTypeAdapterFactory(new BentoboxTypeAdapterFactory(plugin));
builder.registerTypeAdapterFactory(new TagTypeAdapterFactory());
// Allow characters like < or > without escaping them
builder.disableHtmlEscaping();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Registry;
import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
Expand All @@ -32,6 +34,7 @@
import world.bentobox.bentobox.database.json.adapters.PairTypeAdapter;
import world.bentobox.bentobox.database.json.adapters.PotionEffectTypeAdapter;
import world.bentobox.bentobox.database.json.adapters.ProfessionTypeAdapter;
import world.bentobox.bentobox.database.json.adapters.TagTypeAdapter;
import world.bentobox.bentobox.database.json.adapters.VectorTypeAdapter;
import world.bentobox.bentobox.database.json.adapters.VillagerTypeAdapter;
import world.bentobox.bentobox.database.json.adapters.WorldTypeAdapter;
Expand Down Expand Up @@ -62,6 +65,7 @@ public BentoboxTypeAdapterFactory(BentoBox plugin) {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class<?> rawType = type.getRawType();

if (Location.class.isAssignableFrom(rawType)) {
// Use our current location adapter for backward compatibility
return (TypeAdapter<T>) new LocationTypeAdapter();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package world.bentobox.bentobox.database.json.adapters;

import java.io.IOException;

import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Tag;

import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;


/**
* @author tastybento
*
* @param <T> Tag class to be serialized
*/
public final class TagTypeAdapter<E extends Keyed> extends TypeAdapter<Tag<E>> {
private final TypeAdapter<String> stringAdapter;
private final String registry;
private final Class<E> elementType;

public TagTypeAdapter(Gson gson, String registry, Class<E> elementType) {
this.stringAdapter = gson.getAdapter(String.class);
this.registry = registry;
this.elementType = elementType;
}

@Override
public void write(JsonWriter out, Tag<E> value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
stringAdapter.write(out, value.getKey().toString());
}

@Override
public Tag<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}

String key = stringAdapter.read(in);
NamespacedKey namespacedKey = NamespacedKey.fromString(key);
if (namespacedKey == null) {
throw new JsonParseException("Invalid tag key format: " + key);
}

Tag<E> tag = Bukkit.getTag(registry, namespacedKey, elementType);
if (tag == null) {
throw new JsonParseException("Unknown tag: " + key);
}

return tag;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package world.bentobox.bentobox.database.json.adapters;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.bukkit.Fluid;
import org.bukkit.Keyed;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.entity.EntityType;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;

public class TagTypeAdapterFactory implements TypeAdapterFactory {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class<?> rawType = type.getRawType();
if (Tag.class.isAssignableFrom(rawType)) {
// Get the generic type parameter of Tag<T>
Type[] typeArguments = ((ParameterizedType) type.getType()).getActualTypeArguments();
if (typeArguments.length > 0) {
Class<? extends Keyed> tagType = (Class<? extends Keyed>) typeArguments[0];

// Determine the correct registry based on the tag type
String registry;
if (Material.class.equals(tagType)) {
registry = Tag.REGISTRY_BLOCKS;
} else if (EntityType.class.equals(tagType)) {
registry = Tag.REGISTRY_ENTITY_TYPES;
} else if (Fluid.class.equals(tagType)) {
registry = Tag.REGISTRY_FLUIDS;
} else {
throw new IllegalArgumentException("Unsupported Tag type: " + tagType);
}

return (TypeAdapter<T>) new TagTypeAdapter(gson, registry, tagType);
}
}
return null;
}
}

0 comments on commit c18e848

Please sign in to comment.