mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2025-02-26 01:12:29 +01:00
parent
087913ab3a
commit
144723af18
@ -25,7 +25,6 @@ import net.md_5.bungee.chat.ComponentSerializer;
|
|||||||
* Note: The BungeeCord Chat API is not included in CraftBukkit.
|
* Note: The BungeeCord Chat API is not included in CraftBukkit.
|
||||||
* @author dmulloy2
|
* @author dmulloy2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class ComponentConverter {
|
public final class ComponentConverter {
|
||||||
|
|
||||||
private ComponentConverter() {
|
private ComponentConverter() {
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||||
|
* Copyright (C) 2016 dmulloy2
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program;
|
||||||
|
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
* 02111-1307 USA
|
||||||
|
*/
|
||||||
|
package com.comphenix.protocol.wrappers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles component parsing in 1.8
|
||||||
|
* @author dmulloy2
|
||||||
|
*/
|
||||||
|
public class ComponentParser {
|
||||||
|
|
||||||
|
private ComponentParser() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object deserialize(Object gson, Class<?> component, StringReader str) {
|
||||||
|
try {
|
||||||
|
com.google.gson.stream.JsonReader reader = new com.google.gson.stream.JsonReader(str);
|
||||||
|
reader.setLenient(true);
|
||||||
|
return ((com.google.gson.Gson) gson).getAdapter(component).read(reader);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException("Failed to read JSON", ex);
|
||||||
|
} catch (LinkageError er) {
|
||||||
|
return deserializeLegacy(gson, component, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should only be needed on 1.8.
|
||||||
|
private static Object deserializeLegacy(Object gson, Class<?> component, StringReader str) {
|
||||||
|
try {
|
||||||
|
Class<?> readerClass = Class.forName("org.bukkit.craftbukkit.libs.com.google.gson.stream.JsonReader");
|
||||||
|
Object reader = readerClass.getConstructor(StringReader.class).newInstance(str);
|
||||||
|
Method setLenient = readerClass.getMethod("setLenienent", boolean.class);
|
||||||
|
setLenient.invoke(reader, true);
|
||||||
|
Method getAdapter = gson.getClass().getMethod("getAdapter", Class.class);
|
||||||
|
Object adapter = getAdapter.invoke(gson, component);
|
||||||
|
Method read = adapter.getClass().getMethod("read", readerClass);
|
||||||
|
return read.invoke(adapter, reader);
|
||||||
|
} catch (ReflectiveOperationException ex) {
|
||||||
|
throw new RuntimeException("Failed to read JSON", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
package com.comphenix.protocol.wrappers;
|
package com.comphenix.protocol.wrappers;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.io.StringReader;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.reflect.FieldUtils;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||||
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
||||||
@ -19,18 +19,35 @@ import com.google.common.base.Preconditions;
|
|||||||
public class WrappedChatComponent extends AbstractWrapper {
|
public class WrappedChatComponent extends AbstractWrapper {
|
||||||
private static final Class<?> SERIALIZER = MinecraftReflection.getChatSerializerClass();
|
private static final Class<?> SERIALIZER = MinecraftReflection.getChatSerializerClass();
|
||||||
private static final Class<?> COMPONENT = MinecraftReflection.getIChatBaseComponentClass();
|
private static final Class<?> COMPONENT = MinecraftReflection.getIChatBaseComponentClass();
|
||||||
|
private static final Class<?> GSON_CLASS = MinecraftReflection.getMinecraftGsonClass();
|
||||||
|
|
||||||
|
private static Object GSON = null;
|
||||||
|
private static MethodAccessor DESERIALIZE = null;
|
||||||
|
|
||||||
private static MethodAccessor SERIALIZE_COMPONENT = null;
|
private static MethodAccessor SERIALIZE_COMPONENT = null;
|
||||||
private static MethodAccessor DESERIALIZE_COMPONENT = null;
|
|
||||||
private static MethodAccessor CONSTRUCT_COMPONENT = null;
|
private static MethodAccessor CONSTRUCT_COMPONENT = null;
|
||||||
private static ConstructorAccessor CONSTRUCT_TEXT_COMPONENT = null;
|
private static ConstructorAccessor CONSTRUCT_TEXT_COMPONENT = null;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
FuzzyReflection fuzzy = FuzzyReflection.fromClass(SERIALIZER);
|
FuzzyReflection fuzzy = FuzzyReflection.fromClass(SERIALIZER, true);
|
||||||
|
|
||||||
// Retrieve the correct methods
|
// Retrieve the correct methods
|
||||||
SERIALIZE_COMPONENT = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("serialize", /* a */
|
SERIALIZE_COMPONENT = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("serialize", /* a */
|
||||||
String.class, new Class<?>[] { COMPONENT }));
|
String.class, new Class<?>[] { COMPONENT }));
|
||||||
DESERIALIZE_COMPONENT = findDeserialize(fuzzy);
|
|
||||||
|
try {
|
||||||
|
GSON = FieldUtils.readStaticField(fuzzy.getFieldByType("gson", GSON_CLASS), true);
|
||||||
|
} catch (IllegalAccessException ex) {
|
||||||
|
throw new RuntimeException("Failed to obtain GSON field", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
DESERIALIZE = Accessors.getMethodAccessor(FuzzyReflection.fromClass(MinecraftReflection.getMinecraftClass("ChatDeserializer"), true)
|
||||||
|
.getMethodByParameters("deserialize", Object.class, new Class<?>[] { GSON_CLASS, String.class, Class.class, boolean.class }));
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
// We'll handle it in the ComponentParser
|
||||||
|
DESERIALIZE = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Get a component from a standard Minecraft message
|
// Get a component from a standard Minecraft message
|
||||||
CONSTRUCT_COMPONENT = Accessors.getMethodAccessor(MinecraftReflection.getCraftChatMessage(), "fromString", String.class);
|
CONSTRUCT_COMPONENT = Accessors.getMethodAccessor(MinecraftReflection.getCraftChatMessage(), "fromString", String.class);
|
||||||
@ -39,21 +56,15 @@ public class WrappedChatComponent extends AbstractWrapper {
|
|||||||
CONSTRUCT_TEXT_COMPONENT = Accessors.getConstructorAccessor(MinecraftReflection.getChatComponentTextClass(), String.class);
|
CONSTRUCT_TEXT_COMPONENT = Accessors.getConstructorAccessor(MinecraftReflection.getChatComponentTextClass(), String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodAccessor findDeserialize(FuzzyReflection fuzzy) {
|
private static Object deserialize(String json) {
|
||||||
List<Method> methods = fuzzy.getMethodListByParameters(COMPONENT, new Class<?>[] { String.class });
|
// Should be non-null on 1.9 and up
|
||||||
if (methods.isEmpty()) {
|
if (DESERIALIZE != null) {
|
||||||
throw new IllegalArgumentException("Unable to find deserialize method in " + fuzzy.getSource().getName());
|
return DESERIALIZE.invoke(null, GSON, json, COMPONENT, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find b, we want leniency
|
// Mock leniency behavior in 1.8
|
||||||
for (Method method : methods) {
|
StringReader str = new StringReader(json);
|
||||||
if (method.getName().equals("b")) {
|
return ComponentParser.deserialize(GSON, COMPONENT, str);
|
||||||
return Accessors.getMethodAccessor(method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Oh well
|
|
||||||
return Accessors.getMethodAccessor(methods.get(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private transient String cache;
|
private transient String cache;
|
||||||
@ -79,7 +90,7 @@ public class WrappedChatComponent extends AbstractWrapper {
|
|||||||
* @return The chat component wrapper.
|
* @return The chat component wrapper.
|
||||||
*/
|
*/
|
||||||
public static WrappedChatComponent fromJson(String json) {
|
public static WrappedChatComponent fromJson(String json) {
|
||||||
return new WrappedChatComponent(DESERIALIZE_COMPONENT.invoke(null, json), json);
|
return new WrappedChatComponent(deserialize(json), json);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,7 +138,7 @@ public class WrappedChatComponent extends AbstractWrapper {
|
|||||||
* @param obj - the JSON that represents the new component.
|
* @param obj - the JSON that represents the new component.
|
||||||
*/
|
*/
|
||||||
public void setJson(String obj) {
|
public void setJson(String obj) {
|
||||||
this.handle = DESERIALIZE_COMPONENT.invoke(null, obj);
|
this.handle = deserialize(obj);
|
||||||
this.cache = obj;
|
this.cache = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user