Skip to content

Commit 999a255

Browse files
committed
Add Bukkit 1.21.6 support
1 parent 7ece7ac commit 999a255

File tree

1 file changed

+69
-1
lines changed

1 file changed

+69
-1
lines changed

platform-bukkit/src/main/java/net/kyori/adventure/platform/bukkit/MinecraftComponentSerializer.java

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.lang.reflect.Field;
3030
import java.lang.reflect.Method;
3131
import java.lang.reflect.Modifier;
32+
import java.lang.reflect.ParameterizedType;
33+
import java.lang.reflect.Type;
3234
import java.util.ArrayList;
3335
import java.util.Arrays;
3436
import java.util.Comparator;
@@ -95,7 +97,9 @@ public static boolean isSupported() {
9597
findMcClassName("network.chat.IChatBaseComponent"),
9698
findMcClassName("network.chat.Component")
9799
);
100+
private static final @Nullable Class<?> CLASS_COMPONENT_SERIALIZATION = findClass(findMcClassName("network.chat.ComponentSerialization"));
98101
private static final @Nullable Class<?> CLASS_CRAFT_REGISTRY = findCraftClass("CraftRegistry");
102+
private static final @Nullable Class<?> CLASS_HOLDERLOOKUP_PROVIDER = findClass(findMcClassName("core.HolderLookup$Provider"));
99103
private static final @Nullable Class<?> CLASS_REGISTRY_ACCESS = findClass(
100104
findMcClassName("core.IRegistryCustom"),
101105
findMcClassName("core.RegistryAccess")
@@ -109,6 +113,10 @@ public static boolean isSupported() {
109113
private static final MethodHandle TEXT_SERIALIZER_SERIALIZE;
110114
private static final MethodHandle TEXT_SERIALIZER_DESERIALIZE_TREE;
111115
private static final MethodHandle TEXT_SERIALIZER_SERIALIZE_TREE;
116+
private static final MethodHandle COMPONENTSERIALIZATION_CODEC_ENCODE;
117+
private static final MethodHandle COMPONENTSERIALIZATION_CODEC_DECODE;
118+
private static final Object REGISTRY_ACCESS_EMPTY;
119+
private static final MethodHandle CREATE_SERIALIZATION_CONTEXT;
112120

113121
static {
114122
Object gson = null;
@@ -117,6 +125,10 @@ public static boolean isSupported() {
117125
MethodHandle textSerializerSerialize = null;
118126
MethodHandle textSerializerDeserializeTree = null;
119127
MethodHandle textSerializerSerializeTree = null;
128+
MethodHandle codecEncode = null;
129+
MethodHandle codecDecode = null;
130+
Object registryAccessEmpty = null;
131+
MethodHandle createContext = null;
120132

121133
try {
122134
if (CLASS_JSON_PARSER != null) {
@@ -218,6 +230,42 @@ public static boolean isSupported() {
218230
}
219231
}
220232
}
233+
if (CLASS_REGISTRY_ACCESS != null) {
234+
for (Field field : CLASS_REGISTRY_ACCESS.getDeclaredFields()) {
235+
field.setAccessible(true);
236+
if (Modifier.isStatic(field.getModifiers()) && CLASS_REGISTRY_ACCESS.isAssignableFrom(field.getType())) {
237+
registryAccessEmpty = field.get(null);
238+
break;
239+
}
240+
}
241+
if (registryAccessEmpty != null && CLASS_HOLDERLOOKUP_PROVIDER != null) {
242+
for (Method m : CLASS_HOLDERLOOKUP_PROVIDER.getDeclaredMethods()) {
243+
m.setAccessible(true);
244+
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].getSimpleName().equals("DynamicOps") && m.getReturnType().getSimpleName().contains("RegistryOps")) {
245+
createContext = lookup().unreflect(m).bindTo(registryAccessEmpty);
246+
break;
247+
}
248+
}
249+
}
250+
}
251+
if (CLASS_COMPONENT_SERIALIZATION != null) {
252+
for (Field f : CLASS_COMPONENT_SERIALIZATION.getDeclaredFields()) {
253+
if (Modifier.isStatic(f.getModifiers()) && f.getType().getSimpleName().equals("Codec")) {
254+
f.setAccessible(true);
255+
Object codecInstance = f.get(null);
256+
Class<?> codecClass = codecInstance.getClass();
257+
for (Method m : codecClass.getDeclaredMethods()) {
258+
if (m.getName().equals("decode")) {
259+
codecDecode = lookup().unreflect(m).bindTo(codecInstance);
260+
} else if (m.getName().equals("encode")) {
261+
codecEncode = lookup().unreflect(m).bindTo(codecInstance);
262+
}
263+
}
264+
break;
265+
}
266+
}
267+
}
268+
221269
} catch (final Throwable error) {
222270
INITIALIZATION_ERROR.set(new UnsupportedOperationException("Error occurred during initialization", error));
223271
}
@@ -228,9 +276,13 @@ public static boolean isSupported() {
228276
TEXT_SERIALIZER_SERIALIZE = textSerializerSerialize;
229277
TEXT_SERIALIZER_DESERIALIZE_TREE = textSerializerDeserializeTree;
230278
TEXT_SERIALIZER_SERIALIZE_TREE = textSerializerSerializeTree;
279+
COMPONENTSERIALIZATION_CODEC_ENCODE = codecEncode;
280+
COMPONENTSERIALIZATION_CODEC_DECODE = codecDecode;
281+
REGISTRY_ACCESS_EMPTY = registryAccessEmpty;
282+
CREATE_SERIALIZATION_CONTEXT = createContext;
231283
}
232284

233-
private static final boolean SUPPORTED = MC_TEXT_GSON != null || (TEXT_SERIALIZER_DESERIALIZE != null && TEXT_SERIALIZER_SERIALIZE != null) || (TEXT_SERIALIZER_DESERIALIZE_TREE != null && TEXT_SERIALIZER_SERIALIZE_TREE != null);
285+
private static final boolean SUPPORTED = MC_TEXT_GSON != null || (TEXT_SERIALIZER_DESERIALIZE != null && TEXT_SERIALIZER_SERIALIZE != null) || (TEXT_SERIALIZER_DESERIALIZE_TREE != null && TEXT_SERIALIZER_SERIALIZE_TREE != null) || (COMPONENTSERIALIZATION_CODEC_ENCODE != null && COMPONENTSERIALIZATION_CODEC_DECODE != null && REGISTRY_ACCESS_EMPTY != null && CREATE_SERIALIZATION_CONTEXT != null);
234286

235287
@Override
236288
public @NotNull Component deserialize(final @NotNull Object input) {
@@ -242,6 +294,13 @@ public static boolean isSupported() {
242294
element = TEXT_SERIALIZER_SERIALIZE_TREE.invoke(input);
243295
} else if (MC_TEXT_GSON != null) {
244296
element = ((Gson) MC_TEXT_GSON).toJsonTree(input);
297+
} else if (COMPONENTSERIALIZATION_CODEC_ENCODE != null && REGISTRY_ACCESS_EMPTY != null && CREATE_SERIALIZATION_CONTEXT != null) {
298+
final Object jsonOps = Class.forName("com.mojang.serialization.JsonOps").getField("INSTANCE").get(null);
299+
final Object serializationContext = CREATE_SERIALIZATION_CONTEXT.invoke(REGISTRY_ACCESS_EMPTY, jsonOps);
300+
Object result = COMPONENTSERIALIZATION_CODEC_ENCODE.invoke(serializationContext, input, null);
301+
Method getOrThrow = result.getClass().getMethod("getOrThrow", java.util.function.Function.class);
302+
Object jsonElement = getOrThrow.invoke(result, (java.util.function.Function<Throwable, RuntimeException>) RuntimeException::new);
303+
return gson().serializer().fromJson(jsonElement.toString(), Component.class);
245304
} else {
246305
return gson().deserialize((String) TEXT_SERIALIZER_SERIALIZE.invoke(input));
247306
}
@@ -268,6 +327,15 @@ public static boolean isSupported() {
268327
}
269328
} else {
270329
try {
330+
if (COMPONENTSERIALIZATION_CODEC_DECODE != null && REGISTRY_ACCESS_EMPTY != null && CREATE_SERIALIZATION_CONTEXT != null) {
331+
final Object jsonOps = Class.forName("com.mojang.serialization.JsonOps").getField("INSTANCE").get(null);
332+
final Object serializationContext = CREATE_SERIALIZATION_CONTEXT.invoke(jsonOps);
333+
Object result = COMPONENTSERIALIZATION_CODEC_DECODE.invoke(serializationContext, gson().serializeToTree(component));
334+
Method getOrThrow = result.getClass().getMethod("getOrThrow", java.util.function.Function.class);
335+
Object pair = getOrThrow.invoke(result, (java.util.function.Function<Throwable, RuntimeException>) RuntimeException::new);
336+
Method getFirst = pair.getClass().getMethod("getFirst");
337+
return getFirst.invoke(pair);
338+
}
271339
return TEXT_SERIALIZER_DESERIALIZE.invoke(gson().serialize(component));
272340
} catch (final Throwable error) {
273341
throw new UnsupportedOperationException(error);

0 commit comments

Comments
 (0)