Taboolib 5.0 fully refactored & Not a plugin now.

This commit is contained in:
坏黑
2019-07-06 00:17:54 +08:00
parent dfae3001ef
commit ab3ed6bebe
335 changed files with 4225 additions and 12881 deletions

View File

@@ -0,0 +1,23 @@
package io.izzel.taboolib.module.inject;
/**
* @author sky
*/
public class Container {
private final Object container;
private final boolean uniqueId;
public Container(Object container, boolean uniqueId) {
this.container = container;
this.uniqueId = uniqueId;
}
public Object getContainer() {
return container;
}
public boolean isUniqueId() {
return uniqueId;
}
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.inject;
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.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PlayerContainer {
boolean uniqueId() default false;
}

View File

@@ -0,0 +1,59 @@
package io.izzel.taboolib.module.inject;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.module.logger.TLogger;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author sky
* @Since 2018-09-14 23:45
*/
@TListener
public class PlayerContainerLoader implements Listener, TabooLibLoader.Loader {
static Map<String, List<Container>> pluginContainer = new ConcurrentHashMap<>();
@Override
public void postLoad(Plugin plugin, Class<?> pluginClass) {
for (Field field : pluginClass.getDeclaredFields()) {
PlayerContainer annotation = field.getAnnotation(PlayerContainer.class);
if (annotation == null) {
continue;
}
field.setAccessible(true);
try {
pluginContainer.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(new Container(field.get(pluginClass), annotation.uniqueId()));
} catch (IllegalAccessException ignored) {
}
}
}
@Override
public void unload(Plugin plugin, Class<?> cancelClass) {
pluginContainer.remove(plugin.getName());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent e) {
pluginContainer.values().stream().flatMap(Collection::stream).forEach(container -> {
if (container.getContainer() instanceof Map) {
((Map) container.getContainer()).remove(container.isUniqueId() ? e.getPlayer().getUniqueId() : e.getPlayer().getName());
} else if (container.getContainer() instanceof Collection) {
((Collection) container.getContainer()).remove(container.isUniqueId() ? e.getPlayer().getUniqueId() : e.getPlayer().getName());
} else {
TLogger.getGlobalLogger().error("Invalid Container: " + container.getContainer().getClass().getSimpleName());
}
});
}
}

View File

@@ -0,0 +1,19 @@
package io.izzel.taboolib.module.inject;
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-08 14:01
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TFunction {
String enable() default "onEnable";
String disable() default "onDisable";
}

View File

@@ -0,0 +1,58 @@
package io.izzel.taboolib.module.inject;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.module.logger.TLogger;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* @Author sky
* @Since 2018-09-08 14:00
*/
public class TFunctionLoader implements TabooLibLoader.Loader {
@Override
public void postLoad(Plugin plugin, Class<?> pluginClass) {
if (pluginClass.isAnnotationPresent(TFunction.class)) {
TFunction function = pluginClass.getAnnotation(TFunction.class);
try {
Method method = pluginClass.getDeclaredMethod(function.enable());
if (!Modifier.isStatic(method.getModifiers())) {
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
return;
}
method.setAccessible(true);
method.invoke(null);
TabooLibAPI.debug("Function " + pluginClass.getSimpleName() + " loaded. (" + plugin.getName() + ")");
} catch (NoSuchMethodException ignore) {
} catch (Exception e) {
TLogger.getGlobalLogger().warn("TFunction load Failed: " + pluginClass.getName());
e.printStackTrace();
}
}
}
@Override
public void unload(Plugin plugin, Class<?> pluginClass) {
if (pluginClass.isAnnotationPresent(TFunction.class)) {
TFunction function = pluginClass.getAnnotation(TFunction.class);
try {
Method method = pluginClass.getDeclaredMethod(function.disable());
if (!Modifier.isStatic(method.getModifiers())) {
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
return;
}
method.setAccessible(true);
method.invoke(null);
TabooLibAPI.debug("Function " + pluginClass.getSimpleName() + " unloaded. (" + plugin.getName() + ")");
} catch (NoSuchMethodException ignore) {
} catch (Exception e) {
TLogger.getGlobalLogger().warn("TFunction unload Failed: " + pluginClass.getName());
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-10-05 12:11
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TInject {
String[] value() default {};
}

View File

@@ -0,0 +1,153 @@
package io.izzel.taboolib.module.inject;
import com.google.common.collect.Maps;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.module.command.lite.SimpleCommandBuilder;
import io.izzel.taboolib.module.config.TConfig;
import io.izzel.taboolib.module.logger.TLogger;
import io.izzel.taboolib.module.packet.TPacketHandler;
import io.izzel.taboolib.module.packet.TPacketListener;
import io.izzel.taboolib.origin.lite.cooldown.Cooldown;
import io.izzel.taboolib.origin.lite.cooldown.Cooldowns;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
/**
* @Author sky
* @Since 2018-10-05 13:40
*/
public class TInjectLoader implements TabooLibLoader.Loader {
private static Map<Class<?>, TInjectTask> injectTypes = Maps.newLinkedHashMap();
static {
// Instance Inject
injectTypes.put(Plugin.class, (plugin, field, args, instance) -> {
try {
field.set(instance, plugin);
} catch (Exception e) {
e.printStackTrace();
}
});
// TLogger Inject
injectTypes.put(TLogger.class, (plugin, field, args, instance) -> {
try {
field.set(instance, args.length == 0 ? TLogger.getUnformatted(plugin) : TLogger.getUnformatted(args[0]));
} catch (Exception e) {
e.printStackTrace();
}
});
// TPacketListener Inject
injectTypes.put(TPacketListener.class, (plugin, field, args, instance) -> {
try {
TPacketHandler.addListener(plugin, ((TPacketListener) field.get(instance)));
} catch (Exception e) {
e.printStackTrace();
}
});
// TConfiguration Inject
injectTypes.put(TConfig.class, (plugin, field, args, instance) -> {
try {
field.set(instance, TConfig.create(plugin, args.length == 0 ? "config.yml" : args[0]));
} catch (Exception e) {
e.printStackTrace();
}
});
// SimpleCommandBuilder Inject
injectTypes.put(SimpleCommandBuilder.class, (plugin, field, args, instance) -> {
try {
SimpleCommandBuilder builder = (SimpleCommandBuilder) field.get(instance);
if (builder.isBuild()) {
TLogger.getGlobalLogger().error("Command was registered. (" + field.getType().getName() + ")");
} else {
if (builder.getPlugin() == null) {
builder.plugin(plugin);
}
builder.build();
}
} catch (Exception e) {
e.printStackTrace();
}
});
// CooldownPack Inject
injectTypes.put(Cooldown.class, (plugin, field, args, instance) -> {
try {
Cooldowns.register((Cooldown) field.get(instance), plugin);
} catch (Throwable t) {
t.printStackTrace();
}
});
}
@Override
public int priority() {
return -999;
}
@Override
public void preLoad(Plugin plugin, Class<?> pluginClass) {
for (Field declaredField : pluginClass.getDeclaredFields()) {
TInject annotation = declaredField.getAnnotation(TInject.class);
// 是否为主类类型
if (annotation == null || !declaredField.getType().equals(plugin.getClass())) {
continue;
}
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. (" + declaredField.getType().getName() + ")");
continue;
}
}
inject(plugin, declaredField, instance, annotation, injectTypes.get(Plugin.class));
}
}
@Override
public void postLoad(Plugin plugin, Class<?> pluginClass) {
for (Field declaredField : pluginClass.getDeclaredFields()) {
TInject annotation = declaredField.getAnnotation(TInject.class);
if (annotation == null || declaredField.getType().equals(plugin.getClass())) {
continue;
}
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. (" + declaredField.getType().getName() + ")");
continue;
}
}
TInjectTask tInjectTask = injectTypes.get(declaredField.getType());
if (tInjectTask != null) {
inject(plugin, declaredField, instance, annotation, tInjectTask);
} else {
TLogger.getGlobalLogger().error(declaredField.getName() + " is an invalid inject type. (" + declaredField.getType().getName() + ")");
}
}
}
public void inject(Plugin plugin, Field field, Object instance, TInject annotation, TInjectTask injectTask) {
try {
field.setAccessible(true);
injectTask.run(plugin, field, annotation.value(), instance);
TabooLibAPI.debug(field.getName() + " injected. (" + field.getType().getName() + ")");
} catch (Throwable e) {
TLogger.getGlobalLogger().error(field.getName() + " inject failed: " + e.getMessage() + " (" + field.getType().getName() + ")");
if (e.getMessage() == null) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,15 @@
package io.izzel.taboolib.module.inject;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Field;
/**
* @Author sky
* @Since 2018-10-05 13:41
*/
public interface TInjectTask {
void run(Plugin plugin, Field field, String[] args, Object instance);
}

View File

@@ -0,0 +1,41 @@
package io.izzel.taboolib.module.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-08-22 13:41
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TListener {
/**
* 注册时执行的方法名
*/
String register() default "";
/**
* 注销时执行的方法名
*/
String cancel() default "";
/**
* 注册时判断的方法名,需返回布尔值
*/
String condition() default "";
/**
* 注册前判断依赖插件
*/
String[] depend() default "";
/**
* 注册前判断依赖版本
*/
String version() default ">0";
}

View File

@@ -0,0 +1,168 @@
package io.izzel.taboolib.module.inject;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.Version;
import io.izzel.taboolib.module.logger.TLogger;
import io.izzel.taboolib.origin.cronus.util.StringExpression;
import io.izzel.taboolib.util.Strings;
import io.izzel.taboolib.util.Reflection;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Method;
import java.util.*;
/**
* @Author sky
* @Since 2018-08-22 13:48
*/
public class TListenerHandler {
private static HashMap<String, List<Listener>> listeners = new HashMap<>();
/**
* 初始化所有插件的所有监听器
*/
public static void setupListeners() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
try {
setupListener(plugin);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 初始化插件的所有监听器
* 该操作会执行无参构造方法
*
* @param plugin 插件
*/
public static void setupListener(Plugin plugin) {
for (Class<?> pluginClass : TabooLibLoader.getPluginClassSafely(plugin)) {
if (Listener.class.isAssignableFrom(pluginClass) && pluginClass.isAnnotationPresent(TListener.class)) {
try {
TListener tListener = pluginClass.getAnnotation(TListener.class);
// 检查版本
if (!new StringExpression(tListener.version()).isSelect(Version.getCurrentVersion().getVersionInt())) {
continue;
}
// 检查注册条件
if (tListener.depend().length > 0 && !Strings.isBlank(tListener.depend()[0])) {
if (Arrays.stream(tListener.depend()).anyMatch(depend -> Bukkit.getPluginManager().getPlugin(depend) == null)) {
continue;
}
}
// 实例化监听器
Listener listener = plugin.getClass().equals(pluginClass) ? (Listener) plugin : (Listener) Reflection.instantiateObject(pluginClass);
try {
listeners.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(listener);
TabooLibAPI.debug("Listener " + listener.getClass().getSimpleName() + " setup successfully. (" + plugin.getName() + ")");
} catch (Exception e) {
TLogger.getGlobalLogger().warn("TListener setup Failed: " + pluginClass.getName());
e.printStackTrace();
}
} catch (Exception e) {
TabooLibAPI.debug("Listener " + pluginClass.getSimpleName() + "(" + plugin.getName() + ")" + " setup failed: " + e.toString());
}
}
}
}
/**
* 注册所有插件的所有监听器
*/
public static void registerListeners() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
try {
registerListener(plugin);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 注册插件的所有监听器
* 该操作会执行 TListener 注解中的 register() 对应方法
*
* @param plugin 插件
*/
public static void registerListener(Plugin plugin) {
Optional.ofNullable(listeners.get(plugin.getName())).ifPresent(listeners -> {
for (Listener listener : listeners) {
TListener tListener = listener.getClass().getAnnotation(TListener.class);
// 检查注册条件
if (!Strings.isBlank(tListener.condition())) {
try {
Method method = listener.getClass().getDeclaredMethod(tListener.condition());
method.setAccessible(true);
if (!(boolean) method.invoke(listener)) {
continue;
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 执行注册方法
if (!Strings.isBlank(tListener.register())) {
try {
Method method = listener.getClass().getDeclaredMethod(tListener.register());
method.setAccessible(true);
method.invoke(listener);
} catch (Exception e) {
e.printStackTrace();
}
}
// 注册监听
Bukkit.getPluginManager().registerEvents(listener, plugin);
TabooLibAPI.debug("Listener " + listener.getClass().getSimpleName() + " registered. (" + plugin.getName() + ")");
}
});
}
/**
* 注销所有插件的所有监听器
*/
public static void cancelListeners() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
try {
cancelListener(plugin);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 注销插件的所有监听器
* 该操作会执行 TListener 注解中的 cancel() 对应方法
*
* @param plugin 插件
*/
public static void cancelListener(Plugin plugin) {
Optional.ofNullable(listeners.remove(plugin.getName())).ifPresent(listeners -> {
for (Listener listener : listeners) {
HandlerList.unregisterAll(listener);
TListener tListener = listener.getClass().getAnnotation(TListener.class);
if (!Strings.isBlank(tListener.cancel())) {
try {
Method method = listener.getClass().getDeclaredMethod(tListener.cancel());
method.setAccessible(true);
method.invoke(listener);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
public static HashMap<String, List<Listener>> getListeners() {
return listeners;
}
}

View File

@@ -0,0 +1,21 @@
package io.izzel.taboolib.module.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author 坏黑
* @Since 2018-12-15 15:07
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TSchedule {
int delay() default 0;
int period() default -1;
boolean async() default false;
}

View File

@@ -0,0 +1,26 @@
package io.izzel.taboolib.module.inject;
import org.bukkit.scheduler.BukkitRunnable;
/**
* @Author 坏黑
* @Since 2018-12-15 15:25
*/
public class TScheduleData {
private final TSchedule annotation;
private final BukkitRunnable runnable;
public TScheduleData(TSchedule annotation, BukkitRunnable runnable) {
this.annotation = annotation;
this.runnable = runnable;
}
public TSchedule getAnnotation() {
return annotation;
}
public BukkitRunnable getRunnable() {
return runnable;
}
}

View File

@@ -0,0 +1,77 @@
package io.izzel.taboolib.module.inject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.module.logger.TLogger;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
/**
* @Author 坏黑
* @Since 2018-12-15 15:09
*/
public class TScheduleLoader implements TabooLibLoader.Loader {
static Map<String, List<TScheduleData>> schedules = Maps.newHashMap();
public static void run(Plugin plugin, BukkitRunnable runnable, int delay, int period, boolean async) {
if (async) {
runnable.runTaskTimerAsynchronously(plugin, delay, period);
} else {
runnable.runTaskTimer(plugin, delay, period);
}
}
@Override
public void postLoad(Plugin plugin, Class<?> loadClass) {
for (Method method : loadClass.getDeclaredMethods()) {
TSchedule annotation = method.getAnnotation(TSchedule.class);
if (annotation == null) {
continue;
}
Object instance = loadClass.equals(plugin.getClass()) ? plugin : null;
// 如果是非静态类型
if (!Modifier.isStatic(method.getModifiers()) && instance == null) {
// 是否为主类
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
continue;
}
method.setAccessible(true);
// 如果是本插件
if (plugin.equals(TabooLib.getPlugin())) {
run(plugin, new BukkitRunnable() {
@Override
public void run() {
try {
method.invoke(instance);
} catch (Throwable t) {
t.printStackTrace();
}
}
}, annotation.delay(), annotation.period(), annotation.async());
}
// 其他插件则添加到列队
else {
schedules.computeIfAbsent(plugin.getName(), n -> Lists.newArrayList()).add(new TScheduleData(annotation, new BukkitRunnable() {
@Override
public void run() {
try {
method.invoke(instance);
} catch (Throwable t) {
t.printStackTrace();
}
}
}));
}
}
}
}