Switch Impl types to Holderable

This commit is contained in:
Jake Potrebic
2024-11-24 15:08:19 -08:00
parent d300c94ec2
commit ca5499c7fa
8 changed files with 223 additions and 93 deletions

View File

@@ -1,8 +1,21 @@
package io.papermc.paper.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import net.kyori.adventure.key.Key;
import net.minecraft.core.Holder;
import net.minecraft.resources.RegistryOps;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.intellij.lang.annotations.Subst;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
public interface Holderable<M> extends Handleable<M> {
Holder<M> getHolder();
@@ -11,4 +24,55 @@ public interface Holderable<M> extends Handleable<M> {
default M getHandle() {
return this.getHolder().value();
}
static <T extends Keyed, M> @Nullable T fromBukkitSerializationObject(final Object deserialized, final Codec<? extends Holder<M>> codec, final Registry<T> registry) { // TODO remove Keyed
return switch (deserialized) {
case @Subst("key:value") final String string -> {
if (!(Key.parseable(string))) {
yield null;
}
yield registry.get(Key.key(string));
}
case JsonObjectWrapper(final JsonObject element) -> {
if (!(registry instanceof final CraftRegistry<?, ?> craftRegistry) || !craftRegistry.supportsDirectHolders()) {
throw new IllegalArgumentException("Cannot deserialize direct holders for " + registry);
}
final RegistryOps<JsonElement> ops = CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE);
final Holder<M> holder = codec.decode(ops, element).getOrThrow().getFirst();
yield ((CraftRegistry<T, M>) registry).convertDirectHolder(holder);
}
default -> throw new IllegalArgumentException("Cannot deserialize " + deserialized);
};
}
default Object toBukkitSerializationObject(final Codec<? super Holder<M>> codec) {
return switch (this.getHolder()) {
case final Holder.Direct<M> direct -> {
final RegistryOps<JsonElement> ops = CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE);
yield new JsonObjectWrapper(codec.encodeStart(ops, direct).getOrThrow().getAsJsonObject());
}
case final Holder.Reference<M> reference -> reference.key().location().toString();
default -> throw new IllegalArgumentException("Cannot serialize " + this.getHolder());
};
}
/**
* All implementations should use this as their hashCode implementation
*/
default int implHashCode() {
return this.getHolder().hashCode();
}
/**
* All implementations should use this as their equals implementation
*/
default boolean implEquals(final @Nullable Object o) {
if (o == null || this.getClass() != o.getClass()) return false;
final Holderable<?> that = (Holderable<?>) o;
return this.getHolder().equals(that.getHolder());
}
default String implToString() {
return "%s{holder=%s}".formatted(this.getClass().getSimpleName(), this.getHolder().toString());
}
}

View File

@@ -0,0 +1,34 @@
package io.papermc.paper.util;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.Map;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.jspecify.annotations.NullMarked;
@NullMarked
public record JsonObjectWrapper(JsonObject element) implements ConfigurationSerializable {
private static final String KEY = "value";
private static final Gson GSON = new Gson();
static {
ConfigurationSerialization.registerClass(JsonObjectWrapper.class);
}
public JsonObjectWrapper(final JsonElement element) {
this(element.getAsJsonObject());
}
public JsonObjectWrapper(final Map<String, Object> input) {
this(JsonParser.parseString((String) input.get(KEY)).getAsJsonObject());
}
@Override
public Map<String, Object> serialize() {
return Map.of(KEY, GSON.toJson(this.element));
}
}