Fix compatibility with JDK 13

This commit is contained in:
IzzelAliz 2020-02-01 17:04:36 +08:00
parent 8bb2987e57
commit 7563559fda
7 changed files with 95 additions and 25 deletions

View File

@ -4,6 +4,7 @@ import io.izzel.taboolib.module.ai.PathfinderExecutor;
import io.izzel.taboolib.module.ai.SimpleAi; import io.izzel.taboolib.module.ai.SimpleAi;
import io.izzel.taboolib.module.ai.SimpleAiSelector; import io.izzel.taboolib.module.ai.SimpleAiSelector;
import io.izzel.taboolib.module.lite.SimpleReflection; import io.izzel.taboolib.module.lite.SimpleReflection;
import io.izzel.taboolib.util.Ref;
import net.minecraft.server.v1_8_R3.*; import net.minecraft.server.v1_8_R3.*;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity;
@ -95,7 +96,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor {
@Override @Override
public void setPathEntity(LivingEntity entity, Object pathEntity) { public void setPathEntity(LivingEntity entity, Object pathEntity) {
try { try {
this.pathEntity.set(getNavigation(entity), pathEntity); Ref.putField(getNavigation(entity), this.pathEntity, pathEntity);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -152,7 +153,8 @@ public class InternalPathfinderExecutor extends PathfinderExecutor {
@Override @Override
public void setGoalAi(LivingEntity entity, Iterable ai) { public void setGoalAi(LivingEntity entity, Iterable ai) {
try { try {
pathfinderGoalSelectorSet.set(((EntityInsentient) getEntityInsentient(entity)).goalSelector, ai); Ref.putField(((EntityInsentient) getEntityInsentient(entity)).goalSelector,
this.pathfinderGoalSelectorSet, ai);
} catch (Throwable t) { } catch (Throwable t) {
t.printStackTrace(); t.printStackTrace();
} }
@ -161,7 +163,8 @@ public class InternalPathfinderExecutor extends PathfinderExecutor {
@Override @Override
public void setTargetAi(LivingEntity entity, Iterable ai) { public void setTargetAi(LivingEntity entity, Iterable ai) {
try { try {
pathfinderGoalSelectorSet.set(((EntityInsentient) getEntityInsentient(entity)).targetSelector, ai); Ref.putField(((EntityInsentient) getEntityInsentient(entity)).targetSelector,
this.pathfinderGoalSelectorSet, ai);
} catch (Throwable t) { } catch (Throwable t) {
t.printStackTrace(); t.printStackTrace();
} }

View File

@ -7,6 +7,7 @@ import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.Version; import io.izzel.taboolib.Version;
import io.izzel.taboolib.module.locale.TLocale; import io.izzel.taboolib.module.locale.TLocale;
import io.izzel.taboolib.util.ArrayUtil; import io.izzel.taboolib.util.ArrayUtil;
import io.izzel.taboolib.util.Ref;
import io.izzel.taboolib.util.Strings; import io.izzel.taboolib.util.Strings;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.*; import org.bukkit.command.*;
@ -249,8 +250,7 @@ public abstract class BaseMainCommand implements CommandExecutor, TabExecutor {
private void disguisedPlugin(Class<?> targetClass, Plugin plugin) { private void disguisedPlugin(Class<?> targetClass, Plugin plugin) {
try { try {
Field pluginField = targetClass.getClassLoader().getClass().getDeclaredField("plugin"); Field pluginField = targetClass.getClassLoader().getClass().getDeclaredField("plugin");
pluginField.setAccessible(true); Ref.putField(targetClass.newInstance(), pluginField, plugin);
pluginField.set(targetClass.newInstance(), plugin);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }

View File

@ -34,7 +34,7 @@ public class TInjectLoader implements TabooLibLoader.Loader {
// Instance Inject // Instance Inject
injectTypes.put(Plugin.class, (plugin, field, args, pluginClass, instance) -> { injectTypes.put(Plugin.class, (plugin, field, args, pluginClass, instance) -> {
try { try {
field.set(instance, plugin); Ref.putField(instance, field, plugin);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -42,7 +42,7 @@ public class TInjectLoader implements TabooLibLoader.Loader {
// TLogger Inject // TLogger Inject
injectTypes.put(TLogger.class, (plugin, field, args, pluginClass, instance) -> { injectTypes.put(TLogger.class, (plugin, field, args, pluginClass, instance) -> {
try { try {
field.set(instance, args.value().length == 0 ? TLogger.getUnformatted(plugin) : TLogger.getUnformatted(args.value()[0])); Ref.putField(instance, field, args.value().length == 0 ? TLogger.getUnformatted(plugin) : TLogger.getUnformatted(args.value()[0]));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -50,7 +50,7 @@ public class TInjectLoader implements TabooLibLoader.Loader {
// TPacketListener Inject // TPacketListener Inject
injectTypes.put(TPacketListener.class, (plugin, field, args, pluginClass, instance) -> { injectTypes.put(TPacketListener.class, (plugin, field, args, pluginClass, instance) -> {
try { try {
TPacketHandler.addListener(plugin, ((TPacketListener) field.get(instance))); TPacketHandler.addListener(plugin, ((TPacketListener) Ref.getField(instance, field)));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -59,7 +59,7 @@ public class TInjectLoader implements TabooLibLoader.Loader {
injectTypes.put(TConfig.class, (plugin, field, args, pluginClass, instance) -> { injectTypes.put(TConfig.class, (plugin, field, args, pluginClass, instance) -> {
try { try {
TConfig config = TConfig.create(plugin, args.value().length == 0 ? "config.yml" : args.value()[0]); TConfig config = TConfig.create(plugin, args.value().length == 0 ? "config.yml" : args.value()[0]);
field.set(instance, config); Ref.putField(instance, field, config);
if (Strings.nonEmpty(args.locale())) { if (Strings.nonEmpty(args.locale())) {
config.listener(() -> { config.listener(() -> {
List<String> localePriority = Lists.newArrayList(); List<String> localePriority = Lists.newArrayList();
@ -124,7 +124,7 @@ public class TInjectLoader implements TabooLibLoader.Loader {
injectTypes.put(Boolean.TYPE, (plugin, field, args, pluginClass, instance) -> { injectTypes.put(Boolean.TYPE, (plugin, field, args, pluginClass, instance) -> {
try { try {
if (args.value().length > 0) { if (args.value().length > 0) {
field.set(instance, Bukkit.getPluginManager().getPlugin(args.value()[0]) != null); Ref.putField(instance, field, Bukkit.getPluginManager().getPlugin(args.value()[0]) != null);
} }
} catch (Throwable t) { } catch (Throwable t) {
t.printStackTrace(); t.printStackTrace();
@ -134,7 +134,7 @@ public class TInjectLoader implements TabooLibLoader.Loader {
injectTypes.put(JavaPlugin.class, (plugin, field, args, pluginClass, instance) -> { injectTypes.put(JavaPlugin.class, (plugin, field, args, pluginClass, instance) -> {
try { try {
if (args.value().length > 0) { if (args.value().length > 0) {
field.set(instance, Bukkit.getPluginManager().getPlugin(args.value()[0])); Ref.putField(instance, field, Bukkit.getPluginManager().getPlugin(args.value()[0]));
} }
} catch (Throwable t) { } catch (Throwable t) {
t.printStackTrace(); t.printStackTrace();

View File

@ -56,7 +56,6 @@ public class SimpleReflection {
public static void saveField(Class<?> nmsClass, String fieldName) { public static void saveField(Class<?> nmsClass, String fieldName) {
try { try {
Field declaredField = nmsClass.getDeclaredField(fieldName); Field declaredField = nmsClass.getDeclaredField(fieldName);
Ref.forcedAccess(declaredField);
fieldCached.computeIfAbsent(nmsClass.getName(), name -> Maps.newHashMap()).put(fieldName, declaredField); fieldCached.computeIfAbsent(nmsClass.getName(), name -> Maps.newHashMap()).put(fieldName, declaredField);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -73,8 +72,8 @@ public class SimpleReflection {
return; return;
} }
try { try {
field.set(instance, value); Ref.putField(instance, field, value);
} catch (IllegalAccessException e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -89,13 +88,14 @@ public class SimpleReflection {
return null; return null;
} }
try { try {
return field.get(instance); return Ref.getField(instance, field);
} catch (IllegalAccessException e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
@SuppressWarnings("unchecked")
public static <T> T getFieldValue(Class<?> nmsClass, Object instance, String fieldName, T def) { public static <T> T getFieldValue(Class<?> nmsClass, Object instance, String fieldName, T def) {
Map<String, Field> fields = fieldCached.get(nmsClass.getName()); Map<String, Field> fields = fieldCached.get(nmsClass.getName());
if (fields == null) { if (fields == null) {
@ -106,8 +106,8 @@ public class SimpleReflection {
return null; return null;
} }
try { try {
return (T) field.get(instance); return (T) Ref.getField(instance, field);
} catch (IllegalAccessException e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return def; return def;

View File

@ -1,5 +1,6 @@
package io.izzel.taboolib.util; package io.izzel.taboolib.util;
import com.google.common.primitives.Primitives;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import io.izzel.taboolib.TabooLib; import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.TabooLibAPI; import io.izzel.taboolib.TabooLibAPI;
@ -35,7 +36,9 @@ public class Ref {
static { static {
try { try {
UNSAFE = (Unsafe) io.izzel.taboolib.util.Reflection.getValue(null, Unsafe.class, true, "theUnsafe"); Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
Field lookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); Field lookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
Object lookupBase = UNSAFE.staticFieldBase(lookupField); Object lookupBase = UNSAFE.staticFieldBase(lookupField);
long lookupOffset = UNSAFE.staticFieldOffset(lookupField); long lookupOffset = UNSAFE.staticFieldOffset(lookupField);
@ -57,10 +60,73 @@ public class Ref {
if (Modifier.isStatic(field.getModifiers())) { if (Modifier.isStatic(field.getModifiers())) {
Object base = getUnsafe().staticFieldBase(field); Object base = getUnsafe().staticFieldBase(field);
long offset = getUnsafe().staticFieldOffset(field); long offset = getUnsafe().staticFieldOffset(field);
getUnsafe().putObject(base, offset, value); put(field, base, offset, value);
} else { } else {
long offset = getUnsafe().objectFieldOffset(field); long offset = getUnsafe().objectFieldOffset(field);
getUnsafe().putObject(src, offset, value); put(field, src, offset, value);
}
}
private static void put(Field field, Object base, long offset, Object value) {
Class<?> type = field.getType();
if (type.isPrimitive()) {
if (type == boolean.class) {
getUnsafe().putBoolean(base, offset, (Boolean) value);
} else if (type == int.class) {
getUnsafe().putInt(base, offset, ((Number) value).intValue());
} else if (type == double.class) {
getUnsafe().putDouble(base, offset, ((Number) value).doubleValue());
} else if (type == long.class) {
getUnsafe().putLong(base, offset, ((Number) value).longValue());
} else if (type == float.class) {
getUnsafe().putFloat(base, offset, ((Number) value).floatValue());
} else if (type == short.class) {
getUnsafe().putShort(base, offset, ((Number) value).shortValue());
} else if (type == byte.class) {
getUnsafe().putByte(base, offset, ((Number) value).byteValue());
} else if (type == char.class) {
getUnsafe().putChar(base, offset, ((Character) value));
}
} else {
getUnsafe().putObject(base, offset, value);
}
}
public static Object getField(Object src, Field field) {
if (Modifier.isStatic(field.getModifiers())) {
Object base = getUnsafe().staticFieldBase(field);
long offset = getUnsafe().staticFieldOffset(field);
return get(field, base, offset);
} else {
long offset = getUnsafe().objectFieldOffset(field);
return get(field, src, offset);
}
}
private static Object get(Field field, Object base, long offset) {
Class<?> type = field.getType();
if (type.isPrimitive()) {
if (type == boolean.class) {
return getUnsafe().getBoolean(base, offset);
} else if (type == int.class) {
return getUnsafe().getInt(base, offset);
} else if (type == double.class) {
return getUnsafe().getDouble(base, offset);
} else if (type == long.class) {
return getUnsafe().getLong(base, offset);
} else if (type == float.class) {
return getUnsafe().getFloat(base, offset);
} else if (type == short.class) {
return getUnsafe().getShort(base, offset);
} else if (type == byte.class) {
return getUnsafe().getByte(base, offset);
} else if (type == char.class) {
return getUnsafe().getChar(base, offset);
} else {
return null;
}
} else {
return getUnsafe().getObject(base, offset);
} }
} }

View File

@ -247,7 +247,7 @@ public final class Reflection {
* @see #getField(Class, boolean, String) * @see #getField(Class, boolean, String)
*/ */
public static Object getValue(Object instance, Class<?> clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { public static Object getValue(Object instance, Class<?> clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
return getField(clazz, declared, fieldName).get(instance); return Ref.getField(instance, getField(clazz, declared, fieldName));
} }
/** /**
@ -302,7 +302,7 @@ public final class Reflection {
* @see #getField(Class, boolean, String) * @see #getField(Class, boolean, String)
*/ */
public static void setValue(Object instance, Class<?> clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { public static void setValue(Object instance, Class<?> clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
getField(clazz, declared, fieldName).set(instance, value); Ref.putField(instance, getField(clazz, declared, fieldName), value);
} }
/** /**

View File

@ -3,6 +3,7 @@ package io.izzel.taboolib.util.serialize;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.gson.*; import com.google.gson.*;
import io.izzel.taboolib.module.lite.SimpleReflection; import io.izzel.taboolib.module.lite.SimpleReflection;
import io.izzel.taboolib.util.Ref;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.configuration.serialization.ConfigurationSerializable;
@ -36,7 +37,7 @@ public class TSerializer {
} }
// Serializable // Serializable
if (declaredField.isAnnotationPresent(TSerializeCustom.class) && TSerializable.class.isAssignableFrom(declaredField.getType())) { if (declaredField.isAnnotationPresent(TSerializeCustom.class) && TSerializable.class.isAssignableFrom(declaredField.getType())) {
declaredField.set(serializable, generateElement((Class<? extends TSerializable>) declaredField.getType()).read(jsonElementEntry.getValue().getAsString())); Ref.putField(serializable, declaredField, generateElement((Class<? extends TSerializable>) declaredField.getType()).read(jsonElementEntry.getValue().getAsString()));
} }
// List // List
else if (declaredField.isAnnotationPresent(TSerializeCollection.class) && Collection.class.isAssignableFrom(declaredField.getType())) { else if (declaredField.isAnnotationPresent(TSerializeCollection.class) && Collection.class.isAssignableFrom(declaredField.getType())) {
@ -73,7 +74,7 @@ public class TSerializer {
if (serializer == null) { if (serializer == null) {
serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString()); serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
} else { } else {
declaredField.set(serializable, serializer.getSerializer().read(jsonElementEntry.getValue().getAsString())); Ref.putField(serializable, declaredField, serializer.getSerializer().read(jsonElementEntry.getValue().getAsString()));
} }
} }
} catch (Throwable t) { } catch (Throwable t) {