+ update packet api

+ update reflect api
This commit is contained in:
坏黑 2019-10-25 23:30:16 +08:00
parent fe0efbf297
commit e3daaf0162
9 changed files with 219 additions and 5 deletions

View File

@ -9,7 +9,9 @@ import java.lang.annotation.Target;
* @Author sky * @Author sky
* @Since 2018-08-22 13:41 * @Since 2018-08-22 13:41
*/ */
@Target(ElementType.TYPE) @Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface THook { public @interface THook {
String plugin() default "";
} }

View File

@ -2,8 +2,15 @@ package io.izzel.taboolib.module.inject;
import io.izzel.taboolib.TabooLibAPI; import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.TabooLibLoader; 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 org.bukkit.plugin.Plugin;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/** /**
* @Author sky * @Author sky
* @Since 2019-08-17 22:32 * @Since 2019-08-17 22:32
@ -18,5 +25,29 @@ public class THookLoader implements TabooLibLoader.Loader {
TabooLibAPI.getPluginBridge().registerExpansion(pluginClass); 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();
}
}
}
}
} }
} }

View File

@ -100,7 +100,7 @@ public class TInjectCreator implements TabooLibLoader.Loader {
/** /**
* 用于防止多个类使用同一个类型 * 用于防止多个类使用同一个类型
*/ */
public class ClassData { public static class ClassData {
private Class parent; private Class parent;
private Class type; private Class type;

View File

@ -2,6 +2,7 @@ package io.izzel.taboolib.module.lite;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import io.izzel.taboolib.TabooLibAPI; import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.util.Ref;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
@ -29,12 +30,20 @@ public class SimpleReflection {
return fieldCached.getOrDefault(nmsClass.getName(), Maps.newHashMap()).get(fieldName); 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) { public static void checkAndSave(Class<?> nmsClass) {
if (!isExists(nmsClass)) { if (!isExists(nmsClass)) {
saveField(nmsClass); saveField(nmsClass);
} }
} }
public static void saveField(Class<?>... nmsClass) {
Arrays.stream(nmsClass).forEach(SimpleReflection::saveField);
}
public static void saveField(Class<?> nmsClass) { public static void saveField(Class<?> nmsClass) {
try { try {
Arrays.stream(nmsClass.getDeclaredFields()).forEach(declaredField -> saveField(nmsClass, declaredField.getName())); 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) { public static void saveField(Class<?> nmsClass, String fieldName) {
try { try {
Field declaredField = nmsClass.getDeclaredField(fieldName); Field declaredField = nmsClass.getDeclaredField(fieldName);
declaredField.setAccessible(true); 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();

View File

@ -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> T read(String key, T def) {
return SimpleReflection.getFieldValue(this.packetClass, origin, key, def);
}
public <T> T read(String key, Class<? extends T> 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;
}
}

View File

@ -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
}
}

View File

@ -12,8 +12,15 @@ public abstract class TPacketListener {
return true; return true;
} }
public boolean onSend(Player player, Packet packet) {
return true;
}
public boolean onReceive(Player player, Object packet) { public boolean onReceive(Player player, Object packet) {
return true; return true;
} }
public boolean onReceive(Player player, Packet packet) {
return true;
}
} }

View File

@ -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;
}
}

View File

@ -1,5 +1,6 @@
package io.izzel.taboolib.module.packet.channel; package io.izzel.taboolib.module.packet.channel;
import io.izzel.taboolib.module.packet.Packet;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
@ -50,7 +51,7 @@ public abstract class ChannelExecutor {
@Override @Override
public void write(ChannelHandlerContext channelHandlerContext, Object o, ChannelPromise channelPromise) throws Exception { public void write(ChannelHandlerContext channelHandlerContext, Object o, ChannelPromise channelPromise) throws Exception {
try { 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; return;
} }
} catch (Exception e) { } catch (Exception e) {
@ -62,7 +63,7 @@ public abstract class ChannelExecutor {
@Override @Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception { public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
try { 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; return;
} }
} catch (Exception e) { } catch (Exception e) {