From 80208eef6eb456abcf8c204beca08b90248b51d0 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sat, 1 Feb 2020 15:05:01 +0800 Subject: [PATCH 1/9] Add dependency jdk 11 compat --- .../module/dependency/TDependencyLoader.java | 19 ++++++++++++++++--- .../scala/io/izzel/taboolib/util/Ref.java | 3 +-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java index 0dd9f9f..fc638e7 100644 --- a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java @@ -1,10 +1,12 @@ package io.izzel.taboolib.module.dependency; import io.izzel.taboolib.common.plugin.InternalPlugin; +import io.izzel.taboolib.util.Ref; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import java.io.File; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; @@ -13,11 +15,22 @@ import java.net.URLClassLoader; public class TDependencyLoader { + private static final long ucpOffset; + + static { + try { + Field ucp = Bukkit.class.getClassLoader().getClass().getDeclaredField("ucp"); + ucpOffset = Ref.UNSAFE.objectFieldOffset(ucp); + } catch (Exception e) { + throw new IllegalStateException(); + } + } + public static synchronized void addToPath(Plugin plugin, URL url) { try { - Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); - method.setAccessible(true); - method.invoke(plugin instanceof InternalPlugin ? Bukkit.class.getClassLoader() : plugin.getClass().getClassLoader(), url); + Object ucp = Ref.UNSAFE.getObject(plugin instanceof InternalPlugin ? Bukkit.class.getClassLoader() : plugin.getClass().getClassLoader(), ucpOffset); + Method addURL = ucp.getClass().getMethod("addURL", URL.class); + addURL.invoke(ucp, url); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index 20a06d6..eec8d1b 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -34,9 +34,8 @@ public class Ref { try { return (Unsafe) io.izzel.taboolib.util.Reflection.getValue(null, Unsafe.class, true, "theUnsafe"); } catch (Throwable t) { - t.printStackTrace(); + throw new IllegalStateException("Unsafe not found"); } - return null; } public static List getDeclaredFields(Class clazz) { From 69b98c180fba85adc2167b94c9f6538db81ca577 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sat, 1 Feb 2020 15:08:51 +0800 Subject: [PATCH 2/9] Add dependency jdk 11 compat --- .../module/dependency/TDependencyLoader.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java index fc638e7..c3c14b9 100644 --- a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java @@ -15,23 +15,15 @@ import java.net.URLClassLoader; public class TDependencyLoader { - private static final long ucpOffset; - - static { - try { - Field ucp = Bukkit.class.getClassLoader().getClass().getDeclaredField("ucp"); - ucpOffset = Ref.UNSAFE.objectFieldOffset(ucp); - } catch (Exception e) { - throw new IllegalStateException(); - } - } - public static synchronized void addToPath(Plugin plugin, URL url) { try { - Object ucp = Ref.UNSAFE.getObject(plugin instanceof InternalPlugin ? Bukkit.class.getClassLoader() : plugin.getClass().getClassLoader(), ucpOffset); + ClassLoader loader = plugin instanceof InternalPlugin ? Bukkit.class.getClassLoader() : plugin.getClass().getClassLoader(); + Field ucpField = loader.getClass().getDeclaredField("ucp"); + long ucpOffset = Ref.UNSAFE.objectFieldOffset(ucpField); + Object ucp = Ref.UNSAFE.getObject(loader, ucpOffset); Method addURL = ucp.getClass().getMethod("addURL", URL.class); addURL.invoke(ucp, url); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + } catch (Exception e) { e.printStackTrace(); } } From e50bede493cb811237094913e3ec0441a5c6ac10 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sat, 1 Feb 2020 15:24:08 +0800 Subject: [PATCH 3/9] Add dependency jdk 11 compat --- .../module/dependency/TDependencyLoader.java | 12 +++++---- .../module/inject/TScheduleLoader.java | 2 +- .../scala/io/izzel/taboolib/util/Ref.java | 25 +++++++++++++++---- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java index c3c14b9..d8e5985 100644 --- a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java @@ -6,6 +6,8 @@ import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import java.io.File; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -19,11 +21,11 @@ public class TDependencyLoader { try { ClassLoader loader = plugin instanceof InternalPlugin ? Bukkit.class.getClassLoader() : plugin.getClass().getClassLoader(); Field ucpField = loader.getClass().getDeclaredField("ucp"); - long ucpOffset = Ref.UNSAFE.objectFieldOffset(ucpField); - Object ucp = Ref.UNSAFE.getObject(loader, ucpOffset); - Method addURL = ucp.getClass().getMethod("addURL", URL.class); - addURL.invoke(ucp, url); - } catch (Exception e) { + long ucpOffset = Ref.getUnsafe().objectFieldOffset(ucpField); + Object ucp = Ref.getUnsafe().getObject(loader, ucpOffset); + MethodHandle methodHandle = Ref.lookup().findVirtual(ucp.getClass(), "addURL", MethodType.methodType(void.class, java.net.URL.class)); + methodHandle.invoke(ucp, url); + } catch (Throwable e) { e.printStackTrace(); } } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java b/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java index 09ca9bf..6b17212 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java @@ -65,7 +65,7 @@ public class TScheduleLoader implements TabooLibLoader.Loader { method.invoke(instance); } catch (Throwable t) { try { - method.invoke(Ref.UNSAFE.allocateInstance(pluginClass)); + method.invoke(Ref.getUnsafe().allocateInstance(pluginClass)); } catch (Throwable t2) { t.printStackTrace(); t2.printStackTrace(); diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index eec8d1b..9ef6676 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -12,6 +12,7 @@ import sun.misc.Unsafe; import sun.reflect.Reflection; import javax.annotation.concurrent.ThreadSafe; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -19,6 +20,7 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +@SuppressWarnings("restriction") @ThreadSafe public class Ref { @@ -28,16 +30,29 @@ public class Ref { public static final int ACC_BRIDGE = 0x0040; public static final int ACC_SYNTHETIC = 0x1000; - public static final Unsafe UNSAFE = getUnsafe(); + private static final Unsafe UNSAFE; + private static final MethodHandles.Lookup LOOKUP; - static Unsafe getUnsafe() { + static { try { - return (Unsafe) io.izzel.taboolib.util.Reflection.getValue(null, Unsafe.class, true, "theUnsafe"); + UNSAFE = (Unsafe) io.izzel.taboolib.util.Reflection.getValue(null, Unsafe.class, true, "theUnsafe"); + Field lookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); + Object lookupBase = UNSAFE.staticFieldBase(lookupField); + long lookupOffset = UNSAFE.staticFieldOffset(lookupField); + LOOKUP = (MethodHandles.Lookup) UNSAFE.getObject(lookupBase, lookupOffset); } catch (Throwable t) { throw new IllegalStateException("Unsafe not found"); } } + public static Unsafe getUnsafe() { + return UNSAFE; + } + + public static MethodHandles.Lookup lookup() { + return LOOKUP; + } + public static List getDeclaredFields(Class clazz) { return getDeclaredFields(clazz, 0, true); } @@ -73,7 +88,7 @@ public class Ref { } catch (Exception | Error e) { try { List list = Arrays.stream(clazz.getDeclaredFields()) - .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); + .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); cachedFields.putIfAbsent(clazz.getName(), list); return list; } catch (Error err) { @@ -117,7 +132,7 @@ public class Ref { } catch (Exception | Error e) { try { List list = Arrays.stream(clazz.getDeclaredMethods()) - .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); + .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); cacheMethods.putIfAbsent(clazz.getName(), list); return list; } catch (Error err) { From 3ccdfb7abb2ae07052187ed0289f86c0313c2e7f Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sat, 1 Feb 2020 15:33:16 +0800 Subject: [PATCH 4/9] Remove illegal reflection access warnings on Field#modifiers --- src/main/scala/io/izzel/taboolib/util/Ref.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index 9ef6676..ae61517 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -32,6 +32,7 @@ public class Ref { public static final int ACC_SYNTHETIC = 0x1000; private static final Unsafe UNSAFE; private static final MethodHandles.Lookup LOOKUP; + private static final long modifiersOffset; static { try { @@ -40,6 +41,7 @@ public class Ref { Object lookupBase = UNSAFE.staticFieldBase(lookupField); long lookupOffset = UNSAFE.staticFieldOffset(lookupField); LOOKUP = (MethodHandles.Lookup) UNSAFE.getObject(lookupBase, lookupOffset); + modifiersOffset = UNSAFE.objectFieldOffset(Field.class.getDeclaredField("modifiers")); } catch (Throwable t) { throw new IllegalStateException("Unsafe not found"); } @@ -208,9 +210,7 @@ public class Ref { public static void forcedAccess(Field field) { try { field.setAccessible(true); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + getUnsafe().putInt(field, modifiersOffset, field.getModifiers() & ~Modifier.FINAL); } catch (Throwable t) { t.printStackTrace(); } From 8bb2987e575bc0795e99889d5112a5a2305fb37c Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sat, 1 Feb 2020 16:18:18 +0800 Subject: [PATCH 5/9] Fix compatibility with JDK 13 --- .../taboolib/module/db/local/LocalLoader.java | 3 +-- .../izzel/taboolib/module/event/EventNormal.java | 3 +-- .../izzel/taboolib/module/inject/THookLoader.java | 3 +-- .../izzel/taboolib/module/inject/TInjectAsm.java | 3 +-- .../taboolib/module/inject/TInjectCreator.java | 3 +-- src/main/scala/io/izzel/taboolib/util/Ref.java | 14 +++++++++++--- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/main/scala/io/izzel/taboolib/module/db/local/LocalLoader.java b/src/main/scala/io/izzel/taboolib/module/db/local/LocalLoader.java index 3410d31..42ae92b 100644 --- a/src/main/scala/io/izzel/taboolib/module/db/local/LocalLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/db/local/LocalLoader.java @@ -20,10 +20,9 @@ public class LocalLoader implements TabooLibLoader.Loader { if (annotation == null) { continue; } - Ref.forcedAccess(field); for (Object instance : TInjectHelper.getInstance(field, pluginClass, plugin)) { try { - field.set(instance, Local.get(plugin.getName()).get(annotation.value())); + Ref.putField(instance, field, Local.get(plugin.getName()).get(annotation.value())); } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/event/EventNormal.java b/src/main/scala/io/izzel/taboolib/module/event/EventNormal.java index 814217e..709f69b 100644 --- a/src/main/scala/io/izzel/taboolib/module/event/EventNormal.java +++ b/src/main/scala/io/izzel/taboolib/module/event/EventNormal.java @@ -32,8 +32,7 @@ public abstract class EventNormal extends Event { public T async(boolean value) { try { Field asyncField = Reflection.getField(Event.class, true, "async"); - Ref.forcedAccess(asyncField); - asyncField.setBoolean(this, value); + Ref.putField(this, asyncField, value); } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/THookLoader.java b/src/main/scala/io/izzel/taboolib/module/inject/THookLoader.java index d617698..a97882e 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/THookLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/THookLoader.java @@ -27,10 +27,9 @@ public class THookLoader implements TabooLibLoader.Loader { if (Plugin.class.isAssignableFrom(declaredField.getType()) && declaredField.isAnnotationPresent(THook.class)) { THook hook = declaredField.getAnnotation(THook.class); if (Strings.nonEmpty(hook.plugin())) { - Ref.forcedAccess(declaredField); for (Object instance : TInjectHelper.getInstance(declaredField, pluginClass, plugin)) { try { - declaredField.set(instance, Bukkit.getPluginManager().getPlugin(hook.plugin())); + Ref.putField(instance, declaredField, Bukkit.getPluginManager().getPlugin(hook.plugin())); } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TInjectAsm.java b/src/main/scala/io/izzel/taboolib/module/inject/TInjectAsm.java index c2b3e1d..48b93ab 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TInjectAsm.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TInjectAsm.java @@ -20,10 +20,9 @@ public class TInjectAsm implements TabooLibLoader.Loader { if (annotation == null || annotation.asm().isEmpty()) { continue; } - Ref.forcedAccess(declaredField); for (Object instance : TInjectHelper.getInstance(declaredField, pluginClass, plugin)) { try { - declaredField.set(instance, SimpleVersionControl.createNMS(annotation.asm()).useCache().translate(plugin).newInstance()); + Ref.putField(instance, declaredField, SimpleVersionControl.createNMS(annotation.asm()).useCache().translate(plugin).newInstance()); } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TInjectCreator.java b/src/main/scala/io/izzel/taboolib/module/inject/TInjectCreator.java index 5bdb0fa..00a5220 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TInjectCreator.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TInjectCreator.java @@ -58,10 +58,9 @@ public class TInjectCreator implements TabooLibLoader.Loader { if (instance.isEmpty()) { continue; } - Ref.forcedAccess(declaredField); try { InstanceData instanceData = new InstanceData(declaredField.getType().newInstance(), annotation); - declaredField.set(instance, instanceData.getInstance()); + Ref.putField(instance, declaredField, instanceData.getInstance()); instanceMap.put(new ClassData(loadClass, declaredField.getType()), instanceData); } catch (Throwable t) { TLogger.getGlobalLogger().error(declaredField.getName() + " instantiation failed: " + t.getMessage()); diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index ae61517..f2f83e4 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -32,7 +32,6 @@ public class Ref { public static final int ACC_SYNTHETIC = 0x1000; private static final Unsafe UNSAFE; private static final MethodHandles.Lookup LOOKUP; - private static final long modifiersOffset; static { try { @@ -41,7 +40,6 @@ public class Ref { Object lookupBase = UNSAFE.staticFieldBase(lookupField); long lookupOffset = UNSAFE.staticFieldOffset(lookupField); LOOKUP = (MethodHandles.Lookup) UNSAFE.getObject(lookupBase, lookupOffset); - modifiersOffset = UNSAFE.objectFieldOffset(Field.class.getDeclaredField("modifiers")); } catch (Throwable t) { throw new IllegalStateException("Unsafe not found"); } @@ -55,6 +53,17 @@ public class Ref { return LOOKUP; } + public static void putField(Object src, Field field, Object value) { + if (Modifier.isStatic(field.getModifiers())) { + Object base = getUnsafe().staticFieldBase(field); + long offset = getUnsafe().staticFieldOffset(field); + getUnsafe().putObject(base, offset, value); + } else { + long offset = getUnsafe().objectFieldOffset(field); + getUnsafe().putObject(src, offset, value); + } + } + public static List getDeclaredFields(Class clazz) { return getDeclaredFields(clazz, 0, true); } @@ -210,7 +219,6 @@ public class Ref { public static void forcedAccess(Field field) { try { field.setAccessible(true); - getUnsafe().putInt(field, modifiersOffset, field.getModifiers() & ~Modifier.FINAL); } catch (Throwable t) { t.printStackTrace(); } From 7563559fda7a4679c39ef5e93b67971c1f1179c4 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sat, 1 Feb 2020 17:04:36 +0800 Subject: [PATCH 6/9] Fix compatibility with JDK 13 --- .../internal/InternalPathfinderExecutor.java | 9 ++- .../module/command/base/BaseMainCommand.java | 4 +- .../taboolib/module/inject/TInjectLoader.java | 12 ++-- .../module/lite/SimpleReflection.java | 14 ++-- .../scala/io/izzel/taboolib/util/Ref.java | 72 ++++++++++++++++++- .../io/izzel/taboolib/util/Reflection.java | 4 +- .../taboolib/util/serialize/TSerializer.java | 5 +- 7 files changed, 95 insertions(+), 25 deletions(-) diff --git a/src/main/scala/io/izzel/taboolib/module/ai/internal/InternalPathfinderExecutor.java b/src/main/scala/io/izzel/taboolib/module/ai/internal/InternalPathfinderExecutor.java index d72c69b..c73f40a 100644 --- a/src/main/scala/io/izzel/taboolib/module/ai/internal/InternalPathfinderExecutor.java +++ b/src/main/scala/io/izzel/taboolib/module/ai/internal/InternalPathfinderExecutor.java @@ -4,6 +4,7 @@ import io.izzel.taboolib.module.ai.PathfinderExecutor; import io.izzel.taboolib.module.ai.SimpleAi; import io.izzel.taboolib.module.ai.SimpleAiSelector; import io.izzel.taboolib.module.lite.SimpleReflection; +import io.izzel.taboolib.util.Ref; import net.minecraft.server.v1_8_R3.*; import org.bukkit.Location; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; @@ -95,7 +96,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public void setPathEntity(LivingEntity entity, Object pathEntity) { try { - this.pathEntity.set(getNavigation(entity), pathEntity); + Ref.putField(getNavigation(entity), this.pathEntity, pathEntity); } catch (Exception e) { e.printStackTrace(); } @@ -152,7 +153,8 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public void setGoalAi(LivingEntity entity, Iterable ai) { try { - pathfinderGoalSelectorSet.set(((EntityInsentient) getEntityInsentient(entity)).goalSelector, ai); + Ref.putField(((EntityInsentient) getEntityInsentient(entity)).goalSelector, + this.pathfinderGoalSelectorSet, ai); } catch (Throwable t) { t.printStackTrace(); } @@ -161,7 +163,8 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public void setTargetAi(LivingEntity entity, Iterable ai) { try { - pathfinderGoalSelectorSet.set(((EntityInsentient) getEntityInsentient(entity)).targetSelector, ai); + Ref.putField(((EntityInsentient) getEntityInsentient(entity)).targetSelector, + this.pathfinderGoalSelectorSet, ai); } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/command/base/BaseMainCommand.java b/src/main/scala/io/izzel/taboolib/module/command/base/BaseMainCommand.java index 570f30d..2dbacd7 100644 --- a/src/main/scala/io/izzel/taboolib/module/command/base/BaseMainCommand.java +++ b/src/main/scala/io/izzel/taboolib/module/command/base/BaseMainCommand.java @@ -7,6 +7,7 @@ import io.izzel.taboolib.TabooLibAPI; import io.izzel.taboolib.Version; import io.izzel.taboolib.module.locale.TLocale; import io.izzel.taboolib.util.ArrayUtil; +import io.izzel.taboolib.util.Ref; import io.izzel.taboolib.util.Strings; import org.bukkit.Bukkit; import org.bukkit.command.*; @@ -249,8 +250,7 @@ public abstract class BaseMainCommand implements CommandExecutor, TabExecutor { private void disguisedPlugin(Class targetClass, Plugin plugin) { try { Field pluginField = targetClass.getClassLoader().getClass().getDeclaredField("plugin"); - pluginField.setAccessible(true); - pluginField.set(targetClass.newInstance(), plugin); + Ref.putField(targetClass.newInstance(), pluginField, plugin); } catch (Exception ignored) { } } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java b/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java index 8459457..cdf0094 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java @@ -34,7 +34,7 @@ public class TInjectLoader implements TabooLibLoader.Loader { // Instance Inject injectTypes.put(Plugin.class, (plugin, field, args, pluginClass, instance) -> { try { - field.set(instance, plugin); + Ref.putField(instance, field, plugin); } catch (Exception e) { e.printStackTrace(); } @@ -42,7 +42,7 @@ public class TInjectLoader implements TabooLibLoader.Loader { // TLogger Inject injectTypes.put(TLogger.class, (plugin, field, args, pluginClass, instance) -> { 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) { e.printStackTrace(); } @@ -50,7 +50,7 @@ public class TInjectLoader implements TabooLibLoader.Loader { // TPacketListener Inject injectTypes.put(TPacketListener.class, (plugin, field, args, pluginClass, instance) -> { try { - TPacketHandler.addListener(plugin, ((TPacketListener) field.get(instance))); + TPacketHandler.addListener(plugin, ((TPacketListener) Ref.getField(instance, field))); } catch (Exception e) { e.printStackTrace(); } @@ -59,7 +59,7 @@ public class TInjectLoader implements TabooLibLoader.Loader { injectTypes.put(TConfig.class, (plugin, field, args, pluginClass, instance) -> { try { 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())) { config.listener(() -> { List localePriority = Lists.newArrayList(); @@ -124,7 +124,7 @@ public class TInjectLoader implements TabooLibLoader.Loader { injectTypes.put(Boolean.TYPE, (plugin, field, args, pluginClass, instance) -> { try { 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) { t.printStackTrace(); @@ -134,7 +134,7 @@ public class TInjectLoader implements TabooLibLoader.Loader { injectTypes.put(JavaPlugin.class, (plugin, field, args, pluginClass, instance) -> { try { 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) { t.printStackTrace(); diff --git a/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java b/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java index 4c9a714..60c92c2 100644 --- a/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java +++ b/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java @@ -56,7 +56,6 @@ public class SimpleReflection { public static void saveField(Class nmsClass, String fieldName) { try { Field declaredField = nmsClass.getDeclaredField(fieldName); - Ref.forcedAccess(declaredField); fieldCached.computeIfAbsent(nmsClass.getName(), name -> Maps.newHashMap()).put(fieldName, declaredField); } catch (Exception e) { e.printStackTrace(); @@ -73,8 +72,8 @@ public class SimpleReflection { return; } try { - field.set(instance, value); - } catch (IllegalAccessException e) { + Ref.putField(instance, field, value); + } catch (Throwable e) { e.printStackTrace(); } } @@ -89,13 +88,14 @@ public class SimpleReflection { return null; } try { - return field.get(instance); - } catch (IllegalAccessException e) { + return Ref.getField(instance, field); + } catch (Exception e) { e.printStackTrace(); } return null; } + @SuppressWarnings("unchecked") public static T getFieldValue(Class nmsClass, Object instance, String fieldName, T def) { Map fields = fieldCached.get(nmsClass.getName()); if (fields == null) { @@ -106,8 +106,8 @@ public class SimpleReflection { return null; } try { - return (T) field.get(instance); - } catch (IllegalAccessException e) { + return (T) Ref.getField(instance, field); + } catch (Exception e) { e.printStackTrace(); } return def; diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index f2f83e4..b9a5d54 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -1,5 +1,6 @@ package io.izzel.taboolib.util; +import com.google.common.primitives.Primitives; import com.google.gson.annotations.SerializedName; import io.izzel.taboolib.TabooLib; import io.izzel.taboolib.TabooLibAPI; @@ -35,7 +36,9 @@ public class Ref { static { 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"); Object lookupBase = UNSAFE.staticFieldBase(lookupField); long lookupOffset = UNSAFE.staticFieldOffset(lookupField); @@ -57,10 +60,73 @@ public class Ref { if (Modifier.isStatic(field.getModifiers())) { Object base = getUnsafe().staticFieldBase(field); long offset = getUnsafe().staticFieldOffset(field); - getUnsafe().putObject(base, offset, value); + put(field, base, offset, value); } else { 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); } } diff --git a/src/main/scala/io/izzel/taboolib/util/Reflection.java b/src/main/scala/io/izzel/taboolib/util/Reflection.java index 5ee962f..a025810 100644 --- a/src/main/scala/io/izzel/taboolib/util/Reflection.java +++ b/src/main/scala/io/izzel/taboolib/util/Reflection.java @@ -247,7 +247,7 @@ public final class Reflection { * @see #getField(Class, boolean, String) */ 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) */ 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); } /** diff --git a/src/main/scala/io/izzel/taboolib/util/serialize/TSerializer.java b/src/main/scala/io/izzel/taboolib/util/serialize/TSerializer.java index 92e17f0..a98a01d 100644 --- a/src/main/scala/io/izzel/taboolib/util/serialize/TSerializer.java +++ b/src/main/scala/io/izzel/taboolib/util/serialize/TSerializer.java @@ -3,6 +3,7 @@ package io.izzel.taboolib.util.serialize; import com.google.common.collect.Maps; import com.google.gson.*; import io.izzel.taboolib.module.lite.SimpleReflection; +import io.izzel.taboolib.util.Ref; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.serialization.ConfigurationSerializable; @@ -36,7 +37,7 @@ public class TSerializer { } // Serializable if (declaredField.isAnnotationPresent(TSerializeCustom.class) && TSerializable.class.isAssignableFrom(declaredField.getType())) { - declaredField.set(serializable, generateElement((Class) declaredField.getType()).read(jsonElementEntry.getValue().getAsString())); + Ref.putField(serializable, declaredField, generateElement((Class) declaredField.getType()).read(jsonElementEntry.getValue().getAsString())); } // List else if (declaredField.isAnnotationPresent(TSerializeCollection.class) && Collection.class.isAssignableFrom(declaredField.getType())) { @@ -73,7 +74,7 @@ public class TSerializer { if (serializer == null) { serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString()); } else { - declaredField.set(serializable, serializer.getSerializer().read(jsonElementEntry.getValue().getAsString())); + Ref.putField(serializable, declaredField, serializer.getSerializer().read(jsonElementEntry.getValue().getAsString())); } } } catch (Throwable t) { From 498854260d28c14537509cf669b2ba2d987afa11 Mon Sep 17 00:00:00 2001 From: sky Date: Sun, 2 Feb 2020 14:55:20 +0800 Subject: [PATCH 7/9] Update JDK 11 --- .../client/packet/PacketSerializer.java | 3 ++- .../ai/internal/InternalPathfinderExecutor.java | 17 ++++++++--------- .../module/command/base/BaseMainCommand.java | 3 +-- .../module/inject/PlayerContainerLoader.java | 3 ++- .../taboolib/module/inject/TInjectLoader.java | 4 ++-- .../io/izzel/taboolib/module/nms/NMSImpl.java | 3 ++- src/main/scala/io/izzel/taboolib/util/Ref.java | 16 +++++++++------- .../taboolib/util/asm/AsmClassTransformer.java | 3 ++- .../izzel/taboolib/util/plugin/PluginUtils.java | 13 +++++++------ .../taboolib/util/serialize/TSerializer.java | 6 +++--- 10 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/main/scala/io/izzel/taboolib/client/packet/PacketSerializer.java b/src/main/scala/io/izzel/taboolib/client/packet/PacketSerializer.java index eeb957e..3c80e1b 100644 --- a/src/main/scala/io/izzel/taboolib/client/packet/PacketSerializer.java +++ b/src/main/scala/io/izzel/taboolib/client/packet/PacketSerializer.java @@ -7,6 +7,7 @@ import io.izzel.taboolib.TabooLibAPI; import io.izzel.taboolib.TabooLibLoader; import io.izzel.taboolib.client.packet.impl.PacketEmpty; import io.izzel.taboolib.module.inject.TListener; +import io.izzel.taboolib.util.Ref; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -68,7 +69,7 @@ public class PacketSerializer implements Listener { Arrays.stream(packet.getClass().getDeclaredFields()).filter(field -> field.isAnnotationPresent(PacketValue.class)).forEach(field -> { field.setAccessible(true); try { - Object obj = field.get(packet); + Object obj = Ref.getField(packet, field); if (obj instanceof Number) { json.addProperty(field.getName(), (Number) obj); } else if (obj instanceof Boolean) { diff --git a/src/main/scala/io/izzel/taboolib/module/ai/internal/InternalPathfinderExecutor.java b/src/main/scala/io/izzel/taboolib/module/ai/internal/InternalPathfinderExecutor.java index c73f40a..98c71d4 100644 --- a/src/main/scala/io/izzel/taboolib/module/ai/internal/InternalPathfinderExecutor.java +++ b/src/main/scala/io/izzel/taboolib/module/ai/internal/InternalPathfinderExecutor.java @@ -30,7 +30,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { try { SimpleReflection.saveField(PathfinderGoalSelector.class); SimpleReflection.saveField(ControllerJump.class); - pathfinderGoalSelectorSet =SimpleReflection.getField(PathfinderGoalSelector.class, "b"); + pathfinderGoalSelectorSet = SimpleReflection.getField(PathfinderGoalSelector.class, "b"); controllerJumpCurrent = SimpleReflection.getField(ControllerJump.class, "a"); } catch (Exception e) { e.printStackTrace(); @@ -86,7 +86,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public Object getPathEntity(LivingEntity entity) { try { - return pathEntity.get(getNavigation(entity)); + return Ref.getField(getNavigation(entity), pathEntity); } catch (Exception e) { e.printStackTrace(); } @@ -115,7 +115,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public void clearGoalAi(LivingEntity entity) { try { - ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).goalSelector)).clear(); + ((Collection) Ref.getField(((EntityInsentient) getEntityInsentient(entity)).goalSelector, pathfinderGoalSelectorSet)).clear(); } catch (Exception e) { e.printStackTrace(); } @@ -124,7 +124,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public void clearTargetAi(LivingEntity entity) { try { - ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).targetSelector)).clear(); + ((Collection) Ref.getField(((EntityInsentient) getEntityInsentient(entity)).targetSelector, pathfinderGoalSelectorSet)).clear(); } catch (Exception e) { e.printStackTrace(); } @@ -133,7 +133,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public Iterable getGoalAi(LivingEntity entity) { try { - return ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).goalSelector)); + return ((Collection) Ref.getField(((EntityInsentient) getEntityInsentient(entity)).goalSelector, pathfinderGoalSelectorSet)); } catch (Throwable t) { t.printStackTrace(); } @@ -143,7 +143,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public Iterable getTargetAi(LivingEntity entity) { try { - return ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).targetSelector)); + return ((Collection) Ref.getField(((EntityInsentient) getEntityInsentient(entity)).targetSelector, pathfinderGoalSelectorSet)); } catch (Throwable t) { t.printStackTrace(); } @@ -153,8 +153,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { @Override public void setGoalAi(LivingEntity entity, Iterable ai) { try { - Ref.putField(((EntityInsentient) getEntityInsentient(entity)).goalSelector, - this.pathfinderGoalSelectorSet, ai); + Ref.putField(((EntityInsentient) getEntityInsentient(entity)).goalSelector, this.pathfinderGoalSelectorSet, ai); } catch (Throwable t) { t.printStackTrace(); } @@ -164,7 +163,7 @@ public class InternalPathfinderExecutor extends PathfinderExecutor { public void setTargetAi(LivingEntity entity, Iterable ai) { try { Ref.putField(((EntityInsentient) getEntityInsentient(entity)).targetSelector, - this.pathfinderGoalSelectorSet, ai); + this.pathfinderGoalSelectorSet, ai); } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/command/base/BaseMainCommand.java b/src/main/scala/io/izzel/taboolib/module/command/base/BaseMainCommand.java index 2dbacd7..7db8c25 100644 --- a/src/main/scala/io/izzel/taboolib/module/command/base/BaseMainCommand.java +++ b/src/main/scala/io/izzel/taboolib/module/command/base/BaseMainCommand.java @@ -83,8 +83,7 @@ public abstract class BaseMainCommand implements CommandExecutor, TabExecutor { fields.sort(Comparator.comparingDouble(commandField -> commandField.getField().getAnnotation(SubCommand.class).priority())); fields.forEach(commandField -> { try { - commandField.getField().setAccessible(true); - BaseSubCommand subCommand = (BaseSubCommand) commandField.getField().get(commandField.getParent().newInstance()); + BaseSubCommand subCommand = Ref.getField(commandField.getParent().newInstance(), commandField.getField(), BaseSubCommand.class); subCommand.label(commandField.getField().getName()).annotation(commandField.getField().getAnnotation(SubCommand.class)); baseMainCommand.registerSubCommand(subCommand); } catch (Throwable ignored) { diff --git a/src/main/scala/io/izzel/taboolib/module/inject/PlayerContainerLoader.java b/src/main/scala/io/izzel/taboolib/module/inject/PlayerContainerLoader.java index f110082..12b4704 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/PlayerContainerLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/PlayerContainerLoader.java @@ -2,6 +2,7 @@ package io.izzel.taboolib.module.inject; import io.izzel.taboolib.TabooLibLoader; import io.izzel.taboolib.module.locale.logger.TLogger; +import io.izzel.taboolib.util.Ref; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -34,7 +35,7 @@ public class PlayerContainerLoader implements Listener, TabooLibLoader.Loader { field.setAccessible(true); for (Object instance : TInjectHelper.getInstance(field, pluginClass, plugin)) { try { - pluginContainer.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(new Container(field.get(instance), annotation.uniqueId())); + pluginContainer.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(new Container(Ref.getField(instance, field), annotation.uniqueId())); } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java b/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java index cdf0094..39080a9 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java @@ -98,7 +98,7 @@ public class TInjectLoader implements TabooLibLoader.Loader { // SimpleCommandBuilder Inject injectTypes.put(CommandBuilder.class, (plugin, field, args, pluginClass, instance) -> { try { - CommandBuilder builder = (CommandBuilder) field.get(instance); + CommandBuilder builder = Ref.getField(instance, field, CommandBuilder.class); if (!builder.isBuild()) { if (builder.isSimpleMode()) { builder.command(field.getName()); @@ -115,7 +115,7 @@ public class TInjectLoader implements TabooLibLoader.Loader { // CooldownPack Inject injectTypes.put(Cooldown.class, (plugin, field, args, pluginClass, instance) -> { try { - Cooldowns.register((Cooldown) field.get(instance), plugin); + Cooldowns.register((Cooldown) Ref.getField(instance, field), plugin); } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/nms/NMSImpl.java b/src/main/scala/io/izzel/taboolib/module/nms/NMSImpl.java index 21149bd..4d064a1 100644 --- a/src/main/scala/io/izzel/taboolib/module/nms/NMSImpl.java +++ b/src/main/scala/io/izzel/taboolib/module/nms/NMSImpl.java @@ -6,6 +6,7 @@ import io.izzel.taboolib.Version; import io.izzel.taboolib.module.lite.SimpleReflection; import io.izzel.taboolib.module.nms.nbt.*; import io.izzel.taboolib.module.packet.TPacketHandler; +import io.izzel.taboolib.util.Ref; import net.minecraft.server.v1_12_R1.ChatMessageType; import net.minecraft.server.v1_12_R1.EntityVillager; import net.minecraft.server.v1_12_R1.MinecraftServer; @@ -130,7 +131,7 @@ public class NMSImpl extends NMS { return "entity.minecraft." + ((net.minecraft.server.v1_14_R1.MinecraftKey) minecraftKey).getKey(); } else if (Version.isAfter(Version.v1_13)) { try { - String name = "entity.minecraft." + IRegistry.ENTITY_TYPE.getKey((net.minecraft.server.v1_13_R2.EntityTypes) entityTypesField.get(((org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity) entity).getHandle())).getKey(); + String name = "entity.minecraft." + IRegistry.ENTITY_TYPE.getKey((net.minecraft.server.v1_13_R2.EntityTypes) Ref.getField(((org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity) entity).getHandle(), entityTypesField)).getKey(); if (entity instanceof Villager && ((CraftVillager) entity).getCareer() != null) { name += "." + String.valueOf(((CraftVillager) entity).getCareer()).toLowerCase(); } diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index b9a5d54..367ff03 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -1,6 +1,5 @@ package io.izzel.taboolib.util; -import com.google.common.primitives.Primitives; import com.google.gson.annotations.SerializedName; import io.izzel.taboolib.TabooLib; import io.izzel.taboolib.TabooLibAPI; @@ -92,6 +91,11 @@ public class Ref { } } + public static T getField(Object src, Field field, Class cast) { + Object obj = getField(src, field); + return obj == null ? null : (T) obj; + } + public static Object getField(Object src, Field field) { if (Modifier.isStatic(field.getModifiers())) { Object base = getUnsafe().staticFieldBase(field); @@ -165,7 +169,7 @@ public class Ref { } catch (Exception | Error e) { try { List list = Arrays.stream(clazz.getDeclaredFields()) - .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); + .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); cachedFields.putIfAbsent(clazz.getName(), list); return list; } catch (Error err) { @@ -209,7 +213,7 @@ public class Ref { } catch (Exception | Error e) { try { List list = Arrays.stream(clazz.getDeclaredMethods()) - .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); + .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); cacheMethods.putIfAbsent(clazz.getName(), list); return list; } catch (Error err) { @@ -257,10 +261,8 @@ public class Ref { return cachePlugin.computeIfAbsent(callerClass.getName(), n -> { try { ClassLoader loader = callerClass.getClassLoader(); - Field pluginF = loader.getClass().getDeclaredField("plugin"); - pluginF.setAccessible(true); - Object o = pluginF.get(loader); - return (JavaPlugin) o; + Object instance = getField(loader, loader.getClass().getDeclaredField("plugin")); + return (JavaPlugin) instance; } catch (Exception e) { return TabooLib.getPlugin(); } diff --git a/src/main/scala/io/izzel/taboolib/util/asm/AsmClassTransformer.java b/src/main/scala/io/izzel/taboolib/util/asm/AsmClassTransformer.java index a4048d0..a04920d 100644 --- a/src/main/scala/io/izzel/taboolib/util/asm/AsmClassTransformer.java +++ b/src/main/scala/io/izzel/taboolib/util/asm/AsmClassTransformer.java @@ -1,6 +1,7 @@ package io.izzel.taboolib.util.asm; +import io.izzel.taboolib.util.Ref; import org.bukkit.Bukkit; import org.objectweb.asm.*; @@ -36,7 +37,7 @@ public class AsmClassTransformer extends ClassVisitor implements Opcodes { Class clazz = AsmClassLoader.createNewClass(newClassName, writer.toByteArray()); Field field = from.getClassLoader().getClass().getDeclaredField("classes"); field.setAccessible(true); - ((Map>) field.get(from.getClassLoader())).put(newClassName, clazz); + Ref.getField(from.getClassLoader(), field, Map.class).put(newClassName, clazz); Constructor constructor = clazz.getDeclaredConstructor(); constructor.setAccessible(true); return constructor.newInstance(); diff --git a/src/main/scala/io/izzel/taboolib/util/plugin/PluginUtils.java b/src/main/scala/io/izzel/taboolib/util/plugin/PluginUtils.java index 6b562d1..163bca3 100644 --- a/src/main/scala/io/izzel/taboolib/util/plugin/PluginUtils.java +++ b/src/main/scala/io/izzel/taboolib/util/plugin/PluginUtils.java @@ -2,6 +2,7 @@ package io.izzel.taboolib.util.plugin; import com.google.common.base.Joiner; import io.izzel.taboolib.TabooLib; +import io.izzel.taboolib.util.Ref; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.Command; @@ -248,26 +249,26 @@ public class PluginUtils { try { Field pluginsField = Bukkit.getPluginManager().getClass().getDeclaredField("plugins"); pluginsField.setAccessible(true); - plugins = (List) pluginsField.get(pluginManager); + plugins = (List) Ref.getField(pluginManager, pluginsField); Field lookupNamesField = Bukkit.getPluginManager().getClass().getDeclaredField("lookupNames"); lookupNamesField.setAccessible(true); - names = (Map) lookupNamesField.get(pluginManager); + names = (Map) Ref.getField(pluginManager, lookupNamesField); Field commandMapField; try { commandMapField = Bukkit.getPluginManager().getClass().getDeclaredField("listeners"); commandMapField.setAccessible(true); - listeners = (Map) commandMapField.get(pluginManager); + listeners = (Map) Ref.getField(pluginManager, commandMapField); } catch (Exception ignored) { } commandMapField = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap"); commandMapField.setAccessible(true); - commandMap = (SimpleCommandMap) commandMapField.get(pluginManager); + commandMap = (SimpleCommandMap) Ref.getField(pluginManager, commandMapField); Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands"); knownCommandsField.setAccessible(true); - commands = (Map) knownCommandsField.get(commandMap); - } catch (NoSuchFieldException | IllegalAccessException e) { + commands = (Map) Ref.getField(commandMap, knownCommandsField); + } catch (NoSuchFieldException e) { return new PluginUnloadState(true, e.toString()); } } diff --git a/src/main/scala/io/izzel/taboolib/util/serialize/TSerializer.java b/src/main/scala/io/izzel/taboolib/util/serialize/TSerializer.java index a98a01d..1397c1b 100644 --- a/src/main/scala/io/izzel/taboolib/util/serialize/TSerializer.java +++ b/src/main/scala/io/izzel/taboolib/util/serialize/TSerializer.java @@ -50,7 +50,7 @@ public class TSerializer { if (serializer == null) { serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString()); } else { - readCollection((Collection) declaredField.get(serializable), jsonElementEntry.getValue().getAsString(), checkCustom(listType, serializer)); + readCollection((Collection) Ref.getField(serializable, declaredField), jsonElementEntry.getValue().getAsString(), checkCustom(listType, serializer)); } } // Map @@ -65,7 +65,7 @@ public class TSerializer { if (serializerK == null || serializerV == null) { serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString()); } else { - readMap((Map) declaredField.get(serializable), jsonElementEntry.getValue().getAsString(), checkCustom(mapType[0], serializerK), checkCustom(mapType[1], serializerV)); + readMap((Map) Ref.getField(serializable, declaredField), jsonElementEntry.getValue().getAsString(), checkCustom(mapType[0], serializerK), checkCustom(mapType[1], serializerV)); } } // 未声明类型 @@ -95,7 +95,7 @@ public class TSerializer { declaredField.setAccessible(true); try { if (!declaredField.isAnnotationPresent(DoNotSerialize.class) && !Modifier.isStatic(declaredField.getModifiers())) { - Object fieldObject = declaredField.get(serializable); + Object fieldObject = Ref.getField(serializable, declaredField); if (fieldObject == null) { continue; } From 3a70acebd8b455cb50926d7208f1c44b1ee3812b Mon Sep 17 00:00:00 2001 From: sky Date: Sun, 2 Feb 2020 15:30:29 +0800 Subject: [PATCH 8/9] Update JDK 11 --- build.gradle | 2 +- .../common/listener/ListenerCommand.java | 6 +- .../io/izzel/taboolib/util/Hastebin.java | 57 +++ .../izzel/taboolib/util/item/MapBuilder.java | 329 ++++++++++++++++++ 4 files changed, 390 insertions(+), 4 deletions(-) create mode 100644 src/main/scala/io/izzel/taboolib/util/Hastebin.java create mode 100644 src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java diff --git a/build.gradle b/build.gradle index 471f833..2a96889 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'me.skymc' -version = '5.15' +version = '5.16' sourceCompatibility = 1.8 targetCompatibility = 1.8 diff --git a/src/main/scala/io/izzel/taboolib/common/listener/ListenerCommand.java b/src/main/scala/io/izzel/taboolib/common/listener/ListenerCommand.java index 385609a..d12419b 100644 --- a/src/main/scala/io/izzel/taboolib/common/listener/ListenerCommand.java +++ b/src/main/scala/io/izzel/taboolib/common/listener/ListenerCommand.java @@ -62,10 +62,10 @@ public class ListenerCommand implements Listener { TabooLibAPI.debug(true); TLogger.getGlobalLogger().info("&aEnabled."); } - } else if ("libupdate".equalsIgnoreCase(e.getCommand())) { + } else if (e.getCommand().equalsIgnoreCase("libUpdate")) { e.setCancelled(true); - e.getSender().sendMessage("§8[§fTabooLib§8] §cWARNING §7| §4Update TabooLib will force to restart your server. Please confirm this action by type §c/libupdateConfirm"); - } else if ("libupdateConfirm".equalsIgnoreCase(e.getCommand()) || "libupdate confirm".equalsIgnoreCase(e.getCommand())) { + e.getSender().sendMessage("§8[§fTabooLib§8] §cWARNING §7| §4Update TabooLib will force to restart your server. Please confirm this action by type §c/libupdateconfirm"); + } else if (e.getCommand().equalsIgnoreCase("libUpdateConfirm") || e.getCommand().equalsIgnoreCase("libUpdate confirm")) { e.getSender().sendMessage("§8[§fTabooLib§8] §7Downloading TabooLib file..."); Files.downloadFile("https://skymc.oss-cn-shanghai.aliyuncs.com/plugins/TabooLib.jar", new File("libs/TabooLib.jar")); e.getSender().sendMessage("§8[§fTabooLib§8] §2Download completed, the server will restart in 3 secs"); diff --git a/src/main/scala/io/izzel/taboolib/util/Hastebin.java b/src/main/scala/io/izzel/taboolib/util/Hastebin.java new file mode 100644 index 0000000..f1f4183 --- /dev/null +++ b/src/main/scala/io/izzel/taboolib/util/Hastebin.java @@ -0,0 +1,57 @@ +package io.izzel.taboolib.util; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +/** + * @author Arasple + * @date 2020/1/20 16:40 + */ +public class Hastebin { + + private static final String HASTEBIN_URL = "https://hasteb.in/"; + + public static Result paste(String content) { + try { + HttpURLConnection con = (HttpURLConnection) new URL(HASTEBIN_URL + "documents").openConnection(); + con.setRequestMethod("POST"); + con.setRequestProperty("Charset", "UTF-8"); + con.setDoInput(true); + con.setDoOutput(true); + OutputStream os = con.getOutputStream(); + os.write(content.getBytes(StandardCharsets.UTF_8)); + return new Result(IO.readFully(con.getInputStream(), StandardCharsets.UTF_8)); + } catch (Throwable e) { + return null; + } + } + + public static class Result { + + private String source; + private JsonObject sourceJson; + + public Result(String source) { + this.source = source; + this.sourceJson = new JsonParser().parse(source).getAsJsonObject(); + } + + public String getURL() { + return HASTEBIN_URL + sourceJson.get("key").getAsString(); + } + + public String getSource() { + return source; + } + + public JsonObject getSourceJson() { + return sourceJson; + } + } + +} \ No newline at end of file diff --git a/src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java b/src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java new file mode 100644 index 0000000..2e6d65c --- /dev/null +++ b/src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java @@ -0,0 +1,329 @@ +package io.izzel.taboolib.util.item; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.MapMeta; +import org.bukkit.map.*; +import org.bukkit.map.MapView.Scale; +import org.bukkit.plugin.AuthorNagException; + +import javax.annotation.Nonnull; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +/** + * @Author LagBug + */ +public class MapBuilder { + + public static final String VERSION = "1.5"; + private MapView map; + private BufferedImage image; + private List texts; + private MapCursorCollection cursors; + + private boolean rendered; + private boolean renderOnce; + private boolean isNewVersion; + + public MapBuilder() { + cursors = new MapCursorCollection(); + texts = new ArrayList<>(); + rendered = false; + renderOnce = true; + isNewVersion = Bukkit.getVersion().contains("1.15") || Bukkit.getVersion().contains("1.14") || Bukkit.getVersion().contains("1.13"); + } + + /** + * Get the image that's being used + * + * @return the image used + */ + public BufferedImage getImage() { + return image; + } + + /** + * Set an image to be used + * + * @param image the buffered image to use + * @return the instance of this class + */ + public MapBuilder setImage(@Nonnull BufferedImage image) { + this.image = image; + return this; + } + + /** + * Set and image to be used + * + * @param x, y the coordinates to add the text + * @param font the font to be used + * @param text the string that will be displayed + * @return the instance of this class + */ + public MapBuilder addText(@Nonnull int x, @Nonnull int y, @Nonnull MapFont font, @Nonnull String text) { + this.texts.add(new Text(x, y, font, text)); + return this; + } + + /** + * Gets the list of all the texts used + * + * @return a List of all the texts + */ + public List getTexts() { + return texts; + } + + /** + * Adds a cursor to the map + * + * @param x, y the coordinates to add the cursor + * @param direction the direction to display the cursor + * @param type the type of the cursor + * @return the instance of this class + */ + @SuppressWarnings("deprecation") + public MapBuilder addCursor(@Nonnull int x, @Nonnull int y, @Nonnull CursorDirection direction, @Nonnull CursorType type) { + cursors.addCursor(x, y, (byte) direction.getId(), (byte) type.getId()); + return this; + } + + /** + * Gets all the currently used cursors + * + * @return a MapCursorCollection with all current cursors + */ + public MapCursorCollection getCursors() { + return cursors; + } + + /** + * Sets whether the image should only be rendered once. + * Good for static images and reduces lag. + * + * @param renderOnce the value to determine if it's going to be rendered once + * @return the instance of this class + */ + public MapBuilder setRenderOnce(@Nonnull boolean renderOnce) { + this.renderOnce = renderOnce; + return this; + } + + /** + * Builds an ItemStack of the map. + * + * @return the ItemStack of the map containing what's been set from the above methods + */ + @SuppressWarnings("deprecation") + public ItemStack build() { + ItemStack item = null; + + try { + item = new ItemStack(isNewVersion ? Material.MAP : Material.valueOf("MAP")); + } catch (AuthorNagException ex) { + System.out.println("Could not get material for the current spigot version. This won't be shown again until server restats"); + } + + map = Bukkit.createMap(Bukkit.getWorlds().get(0)); + + map.setScale(Scale.NORMAL); + map.getRenderers().forEach(map::removeRenderer); + map.addRenderer(new MapRenderer() { + @Override + public void render(MapView mapView, MapCanvas mapCanvas, Player player) { + if (rendered && renderOnce) { + return; + } + + if (player != null && player.isOnline()) { + if (image != null) { + mapCanvas.drawImage(0, 0, image); + } + + if (!texts.isEmpty()) { + texts.forEach(text -> mapCanvas.drawText(text.getX(), text.getY(), text.getFont(), text.getMessage())); + } + + if (cursors.size() > 0) { + mapCanvas.setCursors(cursors); + } + + rendered = true; + } + } + }); + + if (isNewVersion) { + MapMeta mapMeta = (MapMeta) item.getItemMeta(); + mapMeta.setMapView(map); + item.setItemMeta(mapMeta); + } else { + item.setDurability(getMapId(map)); + } + return item; + } + + /** + * Gets a map id cross-version using reflection + * + * @param mapView the map to get the id + * @return the instance of this class + */ + private short getMapId(@Nonnull MapView mapView) { + try { + return (short) mapView.getId(); + } catch (NoSuchMethodError ex) { + try { + return (short) Class.forName("org.bukkit.map.MapView").getMethod("getId", (Class[]) new Class[0]) + .invoke(mapView, new Object[0]); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException | ClassNotFoundException e) { + e.printStackTrace(); + return -1; + } + } + } + + /** + * An enum containing user friendly cursor directions. Instead of using the integers, you can instead use this enum + */ + public enum CursorDirection { + SOUTH(0), SOUTH_WEST_SOUTH(1), SOUTH_WEST(2), SOUTH_WEST_WEST(3), WEST(4), NORTH_WEST_WEST(5), NORTH_WEST(6), + NORTH_WEST_NORTH(7), NORTH(8), NORTH_EAST_NORTH(9), NORTH_EAST(10), NORTH_EAST_EAST(11), EAST(12), + SOUTH_EAST_EAST(13), SOUNT_EAST(14), SOUTH_EAST_SOUTH(15); + + private final int id; + + CursorDirection(@Nonnull int id) { + this.id = id; + } + + /** + * Returns the actual integer to use + * + * @return the integer of the specified enum type + */ + public int getId() { + return this.id; + } + } + + /** + * An enum containing user friendly cursor types. Instead of using the integers, you can instead use this enum + */ + public enum CursorType { + WHITE_POINTER(0), GREEN_POINTER(1), RED_POINTER(2), BLUE_POINTER(3), WHITE_CLOVER(4), RED_BOLD_POINTER(5), + WHITE_DOT(6), LIGHT_BLUE_SQUARE(7); + + private final int id; + + CursorType(@Nonnull int id) { + this.id = id; + } + + /** + * Returns the actual integer to use + * + * @return the integer of the specified enum type + */ + public int getId() { + return this.id; + } + } + + /** + * A storage class to save text information to later be used in order to write in maps + */ + public static class Text { + + private int x; + private int y; + private MapFont font; + private String message; + + public Text(@Nonnull int x, @Nonnull int y, @Nonnull MapFont font, @Nonnull String message) { + setX(x); + setY(y); + setFont(font); + setMessage(message); + } + + /** + * Gets the x position for the text to be displayed + * + * @return the x position + */ + public int getX() { + return x; + } + + /** + * Sets the x position of the text to display it + * + * @param x the x postion + */ + public void setX(@Nonnull int x) { + this.x = x; + } + + /** + * Gets the y position for the text to be displayed + * + * @return the y position + */ + public int getY() { + return y; + } + + /** + * Sets the y position of the text to display it + * + * @param y the y position + */ + public void setY(@Nonnull int y) { + this.y = y; + } + + /** + * Gets the font to be used + * + * @return the MapFont that is used + */ + public MapFont getFont() { + return font; + } + + /** + * Sets what font should be used + * + * @param font the actual font + */ + public void setFont(@Nonnull MapFont font) { + this.font = font; + } + + /** + * Gets what test will be displayed + * + * @return the text + */ + public String getMessage() { + return message; + } + + /** + * Sets what text will be displayed + * + * @param message the actual text + */ + public void setMessage(@Nonnull String message) { + this.message = message; + } + } +} \ No newline at end of file From 725d2899b274657cb03025d15f26730272f14031 Mon Sep 17 00:00:00 2001 From: sky Date: Sun, 2 Feb 2020 17:31:20 +0800 Subject: [PATCH 9/9] Update JDK 11 --- .../io/izzel/taboolib/module/lite/SimpleReflection.java | 7 +++---- src/main/scala/io/izzel/taboolib/util/Ref.java | 4 ++++ src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java | 6 +++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java b/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java index 60c92c2..52c642e 100644 --- a/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java +++ b/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java @@ -2,7 +2,6 @@ package io.izzel.taboolib.module.lite; import com.google.common.collect.Maps; import io.izzel.taboolib.TabooLibAPI; -import io.izzel.taboolib.module.locale.logger.TLogger; import io.izzel.taboolib.util.Ref; import java.lang.reflect.Field; @@ -65,7 +64,7 @@ public class SimpleReflection { public static void setFieldValue(Class nmsClass, Object instance, String fieldName, Object value) { Map fields = fieldCached.get(nmsClass.getName()); if (fields == null) { - TLogger.getGlobalLogger().error("Field Not Found: " + nmsClass.getName()); + return; } Field field = fields.get(fieldName); if (value == null) { @@ -81,7 +80,7 @@ public class SimpleReflection { public static Object getFieldValue(Class nmsClass, Object instance, String fieldName) { Map fields = fieldCached.get(nmsClass.getName()); if (fields == null) { - TLogger.getGlobalLogger().error("Field Not Found: " + nmsClass.getName()); + return null; } Field field = fields.get(fieldName); if (field == null) { @@ -99,7 +98,7 @@ public class SimpleReflection { public static T getFieldValue(Class nmsClass, Object instance, String fieldName, T def) { Map fields = fieldCached.get(nmsClass.getName()); if (fields == null) { - TLogger.getGlobalLogger().error("Field Not Found: " + nmsClass.getName()); + return null; } Field field = fields.get(fieldName); if (field == null) { diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index 367ff03..983c075 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -1,5 +1,6 @@ package io.izzel.taboolib.util; +import com.google.common.base.Preconditions; import com.google.gson.annotations.SerializedName; import io.izzel.taboolib.TabooLib; import io.izzel.taboolib.TabooLibAPI; @@ -56,6 +57,7 @@ public class Ref { } public static void putField(Object src, Field field, Object value) { + Preconditions.checkNotNull(field); if (Modifier.isStatic(field.getModifiers())) { Object base = getUnsafe().staticFieldBase(field); long offset = getUnsafe().staticFieldOffset(field); @@ -97,6 +99,8 @@ public class Ref { } public static Object getField(Object src, Field field) { + Preconditions.checkNotNull(field); + getUnsafe().ensureClassInitialized(field.getDeclaringClass()); if (Modifier.isStatic(field.getModifiers())) { Object base = getUnsafe().staticFieldBase(field); long offset = getUnsafe().staticFieldOffset(field); diff --git a/src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java b/src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java index 2e6d65c..431bda2 100644 --- a/src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java +++ b/src/main/scala/io/izzel/taboolib/util/item/MapBuilder.java @@ -1,5 +1,6 @@ package io.izzel.taboolib.util.item; +import io.izzel.taboolib.util.Reflection; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -161,7 +162,10 @@ public class MapBuilder { if (isNewVersion) { MapMeta mapMeta = (MapMeta) item.getItemMeta(); - mapMeta.setMapView(map); + try { + Reflection.invokeMethod(mapMeta, "setMapView", map); + } catch (Throwable ignored) { + } item.setItemMeta(mapMeta); } else { item.setDurability(getMapId(map));