From e3daaf01626d1548a84202259b602c592c33111f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9D=8F=E9=BB=91?= Date: Fri, 25 Oct 2019 23:30:16 +0800 Subject: [PATCH] + update packet api + update reflect api --- .../izzel/taboolib/module/inject/THook.java | 4 +- .../taboolib/module/inject/THookLoader.java | 31 +++++++ .../module/inject/TInjectCreator.java | 2 +- .../module/lite/SimpleReflection.java | 11 ++- .../izzel/taboolib/module/packet/Packet.java | 58 +++++++++++++ .../izzel/taboolib/module/packet/TPacket.java | 22 +++++ .../module/packet/TPacketListener.java | 7 ++ .../taboolib/module/packet/TPacketLoader.java | 84 +++++++++++++++++++ .../packet/channel/ChannelExecutor.java | 5 +- 9 files changed, 219 insertions(+), 5 deletions(-) create mode 100644 src/main/scala/io/izzel/taboolib/module/packet/Packet.java create mode 100644 src/main/scala/io/izzel/taboolib/module/packet/TPacket.java create mode 100644 src/main/scala/io/izzel/taboolib/module/packet/TPacketLoader.java diff --git a/src/main/scala/io/izzel/taboolib/module/inject/THook.java b/src/main/scala/io/izzel/taboolib/module/inject/THook.java index e826801..87dacac 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/THook.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/THook.java @@ -9,7 +9,9 @@ import java.lang.annotation.Target; * @Author sky * @Since 2018-08-22 13:41 */ -@Target(ElementType.TYPE) +@Target({ElementType.TYPE, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface THook { + + String plugin() default ""; } \ No newline at end of file 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 8ce4692..3412548 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/THookLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/THookLoader.java @@ -2,8 +2,15 @@ package io.izzel.taboolib.module.inject; import io.izzel.taboolib.TabooLibAPI; import io.izzel.taboolib.TabooLibLoader; +import io.izzel.taboolib.module.locale.logger.TLogger; +import io.izzel.taboolib.util.Ref; +import io.izzel.taboolib.util.Strings; +import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + /** * @Author sky * @Since 2019-08-17 22:32 @@ -18,5 +25,29 @@ public class THookLoader implements TabooLibLoader.Loader { TabooLibAPI.getPluginBridge().registerExpansion(pluginClass); } } + for (Field declaredField : pluginClass.getDeclaredFields()) { + if (Plugin.class.isAssignableFrom(declaredField.getType()) && declaredField.isAnnotationPresent(THook.class)) { + THook hook = declaredField.getAnnotation(THook.class); + if (Strings.nonEmpty(hook.plugin())) { + Object instance = null; + // 如果是非静态类型 + if (!Modifier.isStatic(declaredField.getModifiers())) { + // 是否为主类 + if (pluginClass.equals(plugin.getClass())) { + instance = plugin; + } else { + TLogger.getGlobalLogger().error(declaredField.getName() + " is not a static field. (" + pluginClass.getName() + ")"); + continue; + } + } + Ref.forcedAccess(declaredField); + try { + declaredField.set(instance, Bukkit.getPluginManager().getPlugin(hook.plugin())); + } 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 6ec643a..a8aa7ab 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TInjectCreator.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TInjectCreator.java @@ -100,7 +100,7 @@ public class TInjectCreator implements TabooLibLoader.Loader { /** * 用于防止多个类使用同一个类型 */ - public class ClassData { + public static class ClassData { private Class parent; private Class type; 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 faabd6e..abf15fe 100644 --- a/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java +++ b/src/main/scala/io/izzel/taboolib/module/lite/SimpleReflection.java @@ -2,6 +2,7 @@ package io.izzel.taboolib.module.lite; import com.google.common.collect.Maps; import io.izzel.taboolib.TabooLibAPI; +import io.izzel.taboolib.util.Ref; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; @@ -29,12 +30,20 @@ public class SimpleReflection { return fieldCached.getOrDefault(nmsClass.getName(), Maps.newHashMap()).get(fieldName); } + public static void checkAndSave(Class... nmsClass) { + Arrays.stream(nmsClass).forEach(SimpleReflection::checkAndSave); + } + public static void checkAndSave(Class nmsClass) { if (!isExists(nmsClass)) { saveField(nmsClass); } } + public static void saveField(Class... nmsClass) { + Arrays.stream(nmsClass).forEach(SimpleReflection::saveField); + } + public static void saveField(Class nmsClass) { try { Arrays.stream(nmsClass.getDeclaredFields()).forEach(declaredField -> saveField(nmsClass, declaredField.getName())); @@ -46,7 +55,7 @@ public class SimpleReflection { public static void saveField(Class nmsClass, String fieldName) { try { Field declaredField = nmsClass.getDeclaredField(fieldName); - declaredField.setAccessible(true); + Ref.forcedAccess(declaredField); fieldCached.computeIfAbsent(nmsClass.getName(), name -> Maps.newHashMap()).put(fieldName, declaredField); } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/scala/io/izzel/taboolib/module/packet/Packet.java b/src/main/scala/io/izzel/taboolib/module/packet/Packet.java new file mode 100644 index 0000000..3b1c81e --- /dev/null +++ b/src/main/scala/io/izzel/taboolib/module/packet/Packet.java @@ -0,0 +1,58 @@ +package io.izzel.taboolib.module.packet; + +import io.izzel.taboolib.module.lite.SimpleReflection; + +import java.util.Arrays; + +/** + * @Author sky + * @Since 2019-10-25 22:52 + */ +public class Packet { + + private Object origin; + private Class packetClass; + + public Packet(Object origin) { + this.origin = origin; + this.packetClass = origin.getClass(); + SimpleReflection.checkAndSave(this.packetClass); + } + + public boolean is(Class packetClass) { + return this.packetClass.equals(packetClass); + } + + public boolean is(String packetName) { + return this.packetClass.getSimpleName().equalsIgnoreCase(packetName); + } + + public boolean any(Class... packetClass) { + return Arrays.stream(packetClass).anyMatch(this::is); + } + + public boolean any(String... packetClass) { + return Arrays.stream(packetClass).anyMatch(this::is); + } + + public Object read(String key) { + return SimpleReflection.getFieldValue(this.packetClass, origin, key); + } + + public T read(String key, T def) { + return SimpleReflection.getFieldValue(this.packetClass, origin, key, def); + } + + public T read(String key, Class type) { + Object value = SimpleReflection.getFieldValue(this.packetClass, origin, key); + return value == null ? null : (T) value; + } + + public void write(String key, Object value) { + SimpleReflection.setFieldValue(this.packetClass, origin, key, value); + } + + public Object get() { + return origin; + } +} diff --git a/src/main/scala/io/izzel/taboolib/module/packet/TPacket.java b/src/main/scala/io/izzel/taboolib/module/packet/TPacket.java new file mode 100644 index 0000000..69203bf --- /dev/null +++ b/src/main/scala/io/izzel/taboolib/module/packet/TPacket.java @@ -0,0 +1,22 @@ +package io.izzel.taboolib.module.packet; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @Author sky + * @Since 2018-09-14 23:45 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface TPacket { + + Type type(); + + enum Type { + + SEND, RECEIVE + } +} \ No newline at end of file diff --git a/src/main/scala/io/izzel/taboolib/module/packet/TPacketListener.java b/src/main/scala/io/izzel/taboolib/module/packet/TPacketListener.java index cc36ce4..440e0e9 100644 --- a/src/main/scala/io/izzel/taboolib/module/packet/TPacketListener.java +++ b/src/main/scala/io/izzel/taboolib/module/packet/TPacketListener.java @@ -12,8 +12,15 @@ public abstract class TPacketListener { return true; } + public boolean onSend(Player player, Packet packet) { + return true; + } + public boolean onReceive(Player player, Object packet) { return true; } + public boolean onReceive(Player player, Packet packet) { + return true; + } } diff --git a/src/main/scala/io/izzel/taboolib/module/packet/TPacketLoader.java b/src/main/scala/io/izzel/taboolib/module/packet/TPacketLoader.java new file mode 100644 index 0000000..0262030 --- /dev/null +++ b/src/main/scala/io/izzel/taboolib/module/packet/TPacketLoader.java @@ -0,0 +1,84 @@ +package io.izzel.taboolib.module.packet; + +import io.izzel.taboolib.TabooLibLoader; +import io.izzel.taboolib.module.locale.logger.TLogger; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; + +/** + * @Author sky + * @Since 2019-10-25 22:50 + */ +public class TPacketLoader implements TabooLibLoader.Loader { + + @Override + public void activeLoad(Plugin plugin, Class pluginClass) { + for (Method method : pluginClass.getDeclaredMethods()) { + if (method.isAnnotationPresent(TPacket.class)) { + Object instance = null; + // 如果是非静态类型 + if (!Modifier.isStatic(method.getModifiers())) { + // 是否为主类 + if (pluginClass.equals(plugin.getClass())) { + instance = plugin; + } else { + TLogger.getGlobalLogger().error(method.getName() + " is not a static method. (" + pluginClass.getName() + ")"); + continue; + } + } + method.setAccessible(true); + TPacket packet = method.getAnnotation(TPacket.class); + boolean packetType = method.getReturnType().equals(Boolean.TYPE) || method.getReturnType().equals(Boolean.class); + // object type + if (Arrays.equals(method.getParameterTypes(), new Class[] {Player.class, Object.class})) { + Object finalInstance = instance; + TPacketHandler.addListener(plugin, new TPacketListener() { + @Override + public boolean onSend(Player player, Object p) { + return eval(finalInstance, packet, TPacket.Type.SEND, packetType, method, player, p); + } + + @Override + public boolean onReceive(Player player, Object p) { + return eval(finalInstance, packet, TPacket.Type.RECEIVE, packetType, method, player, p); + } + }); + } + // packet type + else if (Arrays.equals(method.getParameterTypes(), new Class[] {Player.class, Packet.class})) { + Object finalInstance1 = instance; + TPacketHandler.addListener(plugin, new TPacketListener() { + @Override + public boolean onSend(Player player, Packet p) { + return eval(finalInstance1, packet, TPacket.Type.SEND, packetType, method, player, p); + } + + @Override + public boolean onReceive(Player player, Packet p) { + return eval(finalInstance1, packet, TPacket.Type.RECEIVE, packetType, method, player, p); + } + }); + } else { + TLogger.getGlobalLogger().error(method.getName() + " is an invalid packet listener. (" + pluginClass.getName() + ")"); + TLogger.getGlobalLogger().error("Usage: boolean fun(Player player, Object packet) { ... }"); + } + } + } + } + + private boolean eval(Object instance, TPacket packet, TPacket.Type type, boolean packetType, Method method, Player player, Object obj) { + if (packet.type() == type) { + try { + return !packetType || (boolean) method.invoke(instance, player, obj); + } catch (Throwable t) { + t.printStackTrace(); + } + return false; + } + return true; + } +} diff --git a/src/main/scala/io/izzel/taboolib/module/packet/channel/ChannelExecutor.java b/src/main/scala/io/izzel/taboolib/module/packet/channel/ChannelExecutor.java index 99835b5..36e9283 100644 --- a/src/main/scala/io/izzel/taboolib/module/packet/channel/ChannelExecutor.java +++ b/src/main/scala/io/izzel/taboolib/module/packet/channel/ChannelExecutor.java @@ -1,5 +1,6 @@ package io.izzel.taboolib.module.packet.channel; +import io.izzel.taboolib.module.packet.Packet; import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; @@ -50,7 +51,7 @@ public abstract class ChannelExecutor { @Override public void write(ChannelHandlerContext channelHandlerContext, Object o, ChannelPromise channelPromise) throws Exception { try { - if (TPacketHandler.getListeners().stream().flatMap(Collection::stream).anyMatch(packetListener -> !packetListener.onSend(player, o))) { + if (TPacketHandler.getListeners().stream().flatMap(Collection::stream).anyMatch(packetListener -> !packetListener.onSend(player, o) || !packetListener.onSend(player, new Packet(o)))) { return; } } catch (Exception e) { @@ -62,7 +63,7 @@ public abstract class ChannelExecutor { @Override public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception { try { - if (TPacketHandler.getListeners().stream().flatMap(Collection::stream).anyMatch(packetListener -> !packetListener.onReceive(player, o))) { + if (TPacketHandler.getListeners().stream().flatMap(Collection::stream).anyMatch(packetListener -> !packetListener.onReceive(player, o) || !packetListener.onReceive(player, new Packet(o)))) { return; } } catch (Exception e) {