diff --git a/README.md b/README.md index 3d39de1..115619a 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,76 @@ -# TabooLib +

+
+
+
+ TabooLib +

+ 插件功能   + 插件文档   + 插件命令   + 插件下载   + MCBBS +

+
+
+
+
+
+ -> Bukkit 开发工具库集合 + +插件功能 +--- +本插件包含大量常用开发工具及扩展工具,可以帮助入门开发者完成一些繁琐或是复杂的操作,在你没有自己的工具库时,这些工具可以大量提升你的而开发速度,本插件自带的大部分计算都是异步处理,不会影响服务器的正常运行,你只要不去使用我标注为过时的工具,那么我可以向你保证工具的运行效率。插件在 3.55 版本后开始逐渐将一些常用的工具添加到配置文件中, 来让不会开发的服主使用。 -[![](http://ci.pcd.ac.cn/job/TabooLib/badge/icon)](http://ci.pcd.ac.cn/job/TabooLib) +
+ + +插件文档 +--- +| 文档(更新中) | 地址 | +| --- | --- | +| 主文档 | https://bkm016.github.io/TabooLib/#/ | + +
+ + +插件命令 +--- +| 命令 | 作用 | 权限 | +| --- | --- | --- | +| /taboolib | 插件主命令 | taboolib.admin | +| /tabooliblocale | TLocale 工具主命令 | taboolib.admin | +| /taboolibplugin | TPlugin 工具主命令 | taboolib.admin | +| /taboolibexecute | TExecute 工具主命令 | taboolib.admin | +| /tabooliblogs | TLogs 工具主命令 | taboolib.admin | +| /taboolibrarymodule | TLM 模块主命令 | tlm.use | +| /language2 | Language2 工具主命令 | taboolib.admin | +| /translateuuid | TranslateUUID 工具主命令 | taboolib.admin | + +
+ + +插件下载 +--- +[![](http://jenkins.mirez.cc/buildStatus/icon?job=TabooLib)](http://jenkins.mirez.cc/job/TabooLib/) [![](https://img.shields.io/github/downloads/Bkm016/TabooLib/total.svg)](https://github.com/Bkm016/TabooLib/releases) [![](https://img.shields.io/github/release/Bkm016/TabooLib.svg)](https://github.com/Bkm016/TabooLib/tags) [![](https://img.shields.io/github/stars/Bkm016/TabooLib.svg?style=flat-square&label=Stars)](https://github.com/Bkm016/TabooLib) [![](https://jitpack.io/v/Bkm016/TabooLib.svg)](https://jitpack.io/#Bkm016/TabooLib) -## 插件文档 +你可以在 [**这里**](https://github.com/Bkm016/TabooLib/releases) 下载正式版本 +如果你的服务器没有连接互联网(内网跨服),请下载 **libs.rar** 文件并手动解压至服务端目录 -[TabooLib 文档](https://bkm016.github.io/TabooLib/#/) +如果你无法连接到 Github,可以在由 **Mirez** 服务器提供的 [**构建站**](http://jenkins.15imc.com:8080/job/TabooLib/) 下载最新版本 +该网站下载到的插件有可能是 **正在测试** 的不稳定版本,最新版本以 Github 为准 -## 下载 TabooLib 插件 +从 **4.0** 版本起,不再对 **1.7.10** 进行支持与维护,部分功能在该版本可能会失效 +如果你需要在 1.7.10 安装本插件,请在 [**这里**](https://pcd.ac.cn/2018/05/19/71/) 修复因 **SpecialSource** 版本过低导致插件无法载入的问题。 -在 [这里](https://github.com/bkm016/TabooLib/releases) 根据您服务器的网络状态下载**在线**或**离线**版本 -离线版为 **offline** 结尾的 **jar** 文件 - -如果你的服务器是 **1.7.10** 版本,在 [这里](https://pcd.ac.cn/2018/05/19/71/) 修复因 **SpecialSource** 版本过低导致插件无法载入的问题 - -## 添加 TabooLib 为库 - -### Maven - -```xml - - - - jitpack.io - https://jitpack.io - - - - com.github.Bkm016 - TabooLib - JitPack版本 - - -``` - -### Gradle - -```groovy -repositories { - maven { url 'https://jitpack.io' } -} -dependencies { - compile 'com.github.Bkm016:TabooLib:JitPack版本' -} -``` - -### sbt - -```scala -resolvers += "jitpack" at "https://jitpack.io" -libraryDependencies += "com.github.Bkm016" % "TabooLib" % "JitPack版本" -``` - -在添加依赖后,你还需要在 `plugin.yml` 中添加 `softdepend` 或者 `depend` 才能享受到 TabooLib 的全部功能。 +
+ +MCBBS --- -**3.56** 版本开始 `com.sun.tools.jar` 不再和插件一起发布。 - -如果需要启用 *JavaShell* 功能请将 [com.sun.tools.jar](http://skymc.oss-cn-shanghai.aliyuncs.com/plugins/com.sun.tools.jar) 放入 *"TabooLib/JavaShell/lib"* 文件夹中。   - ---- -**3.832** 版本后开源协议更改为 `MIT` +本插件仅在 [**MCBBS**](http://www.mcbbs.net/thread-773065-1-1.html) 发布 +
diff --git a/pom.xml b/pom.xml index 9c53f9a..f9b19a9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.skymc TabooLib - 4.2 + 4.325 UTF-8 diff --git a/src/main/java/com/ilummc/tlib/ExampleMain.java b/src/main/java/com/ilummc/tlib/ExampleMain.java index 324599f..b6426a6 100644 --- a/src/main/java/com/ilummc/tlib/ExampleMain.java +++ b/src/main/java/com/ilummc/tlib/ExampleMain.java @@ -13,6 +13,8 @@ import java.util.concurrent.TimeUnit; @TConfig(name = "cfg.yml", charset = "GBK") public class ExampleMain extends JavaPlugin { + private Property update = Property.of(false); + public static void main(String[] args) { MemoryMXBean bean = ManagementFactory.getMemoryMXBean(); System.out.println(bean.getHeapMemoryUsage().toString()); @@ -34,8 +36,6 @@ public class ExampleMain extends JavaPlugin { } } - private Property update = Property.of(false); - @Override public void onEnable() { update.addListener(((oldVal, newVal) -> { diff --git a/src/main/java/com/ilummc/tlib/TLib.java b/src/main/java/com/ilummc/tlib/TLib.java index 3857f35..06c5863 100644 --- a/src/main/java/com/ilummc/tlib/TLib.java +++ b/src/main/java/com/ilummc/tlib/TLib.java @@ -14,15 +14,16 @@ import com.ilummc.tlib.resources.TLocaleLoader; import com.ilummc.tlib.util.IO; import me.skymc.taboolib.Main; import me.skymc.taboolib.fileutils.FileUtils; +import me.skymc.taboolib.plugin.PluginUtils; import org.bukkit.Bukkit; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.Plugin; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.nio.charset.Charset; +import java.util.Arrays; @Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.1.0") @Dependency(type = Dependency.Type.LIBRARY, maven = "org.slf4j:slf4j-api:1.7.25") @@ -58,14 +59,6 @@ public class TLib { } } - public static TLib getTLib() { - return tLib; - } - - public static YamlConfiguration getInternalLanguage() { - return internalLanguage; - } - public static void init() { tLib = new TLib(); @@ -94,6 +87,11 @@ public class TLib { } public static void injectPluginManager() { + if (!tLib.isInjectEnabled() || tLib.isBlackListPluginExists()) { + TLocale.Logger.fatal("TLIB.INJECTION-DISABLED"); + Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(plugin -> plugin != Main.getInst()).forEach(plugin -> TDependencyInjector.inject(plugin, plugin)); + return; + } try { Field field = Bukkit.getServer().getClass().getDeclaredField("pluginManager"); field.setAccessible(true); @@ -101,14 +99,18 @@ public class TLib { TLocale.Logger.info("TLIB.INJECTION-SUCCESS"); } catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException ignored) { TLocale.Logger.fatal("TLIB.INJECTION-FAILED"); - for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { - if (plugin != Main.getInst()) { - TDependencyInjector.inject(plugin, plugin); - } - } + Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(plugin -> plugin != Main.getInst()).forEach(plugin -> TDependencyInjector.inject(plugin, plugin)); } } + public static TLib getTLib() { + return tLib; + } + + public static YamlConfiguration getInternalLanguage() { + return internalLanguage; + } + public TLogger getLogger() { return logger; } @@ -124,4 +126,18 @@ public class TLib { public File getLibsFolder() { return libsFolder; } + + // ********************************* + // + // Private Methods + // + // ********************************* + + private boolean isInjectEnabled() { + return Main.getInst().getConfig().getBoolean("PLUGIN-INJECTOR.ENABLE", true); + } + + private boolean isBlackListPluginExists() { + return Main.getInst().getConfig().getStringList("PLUGIN-INJECTOR.DISABLE-ON-PLUGIN-EXISTS").stream().anyMatch(PluginUtils::isPluginExists); + } } diff --git a/src/main/java/com/ilummc/tlib/logger/TLogger.java b/src/main/java/com/ilummc/tlib/logger/TLogger.java index 0feee53..2b3b664 100644 --- a/src/main/java/com/ilummc/tlib/logger/TLogger.java +++ b/src/main/java/com/ilummc/tlib/logger/TLogger.java @@ -1,9 +1,12 @@ package com.ilummc.tlib.logger; +import com.ilummc.tlib.resources.TLocale; import com.ilummc.tlib.util.Strings; import me.skymc.taboolib.Main; +import me.skymc.taboolib.TabooLib; +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.plugin.Plugin; public class TLogger { @@ -12,7 +15,7 @@ public class TLogger { private static TLogger globalLogger = new TLogger("§8[§3§lTabooLib§8][§r{1}§8] §f{2}", Main.getInst(), TLogger.FINE); private final String pattern; - private Plugin plugin; + private String name; private int level; public static TLogger getGlobalLogger() { @@ -23,8 +26,8 @@ public class TLogger { return pattern; } - public Plugin getPlugin() { - return plugin; + public String getName() { + return name; } public int getLevel() { @@ -37,49 +40,83 @@ public class TLogger { public TLogger(String pattern, Plugin plugin, int level) { this.pattern = pattern; - this.plugin = plugin; + this.name = plugin.getName(); + this.level = level; + } + + public TLogger(String pattern, String name, int level) { + this.pattern = pattern; + this.name = name; this.level = level; } public void verbose(String msg) { if (level <= VERBOSE) { - Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§f全部", ChatColor.translateAlternateColorCodes('&', msg))); + if (TabooLib.isSpigot()) { + Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§f全部", TLocale.Translate.setColored(msg))); + } else { + BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§f全部", TLocale.Translate.setColored(msg)))); + } } } public void finest(String msg) { if (level <= FINEST) { - Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§e良好", ChatColor.translateAlternateColorCodes('&', msg))); + if (TabooLib.isSpigot()) { + Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§e良好", TLocale.Translate.setColored(msg))); + } else { + BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§e良好", TLocale.Translate.setColored(msg)))); + } } } public void fine(String msg) { if (level <= FINE) { - Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§a正常", ChatColor.translateAlternateColorCodes('&', msg))); + if (TabooLib.isSpigot()) { + Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§a正常", TLocale.Translate.setColored(msg))); + } else { + BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§a正常", TLocale.Translate.setColored(msg)))); + } } } public void info(String msg) { if (level <= INFO) { - Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§b信息", ChatColor.translateAlternateColorCodes('&', msg))); + if (TabooLib.isSpigot()) { + Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§b信息", TLocale.Translate.setColored(msg))); + } else { + BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§b信息", TLocale.Translate.setColored(msg)))); + } } } public void warn(String msg) { if (level <= WARN) { - Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§6警告", "§6" + ChatColor.translateAlternateColorCodes('&', msg))); + if (TabooLib.isSpigot()) { + Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§6警告", "§6" + TLocale.Translate.setColored(msg))); + } else { + BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§6警告", "§6" + TLocale.Translate.setColored(msg)))); + } } } public void error(String msg) { if (level <= ERROR) { - Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§c错误", "§c" + ChatColor.translateAlternateColorCodes('&', msg))); + if (TabooLib.isSpigot()) { + Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§c错误", "§c" + TLocale.Translate.setColored(msg))); + } else { + BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§c错误", "§c" + TLocale.Translate.setColored(msg)))); + } } } public void fatal(String msg) { if (level <= FATAL) { - Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§4致命错误", "§4" + ChatColor.translateAlternateColorCodes('&', msg))); + if (TabooLib.isSpigot()) { + Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§4致命错误", "§4" + TLocale.Translate.setColored(msg))); + } else { + BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§4致命错误", "§4" + TLocale.Translate.setColored(msg)))); + } } } @@ -87,4 +124,7 @@ public class TLogger { return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", plugin, TLogger.FINE); } + public static TLogger getUnformatted(String name) { + return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", name, TLogger.FINE); + } } diff --git a/src/main/java/com/ilummc/tlib/nms/ActionBar.java b/src/main/java/com/ilummc/tlib/nms/ActionBar.java index 7ef5d6a..46e3edc 100644 --- a/src/main/java/com/ilummc/tlib/nms/ActionBar.java +++ b/src/main/java/com/ilummc/tlib/nms/ActionBar.java @@ -40,10 +40,8 @@ public abstract class ActionBar { @Override public void send(Player player, String text) { net.minecraft.server.v1_12_R1.ChatComponentText component = new net.minecraft.server.v1_12_R1.ChatComponentText(text); - net.minecraft.server.v1_12_R1.PacketPlayOutChat packet = new net.minecraft.server.v1_12_R1.PacketPlayOutChat(component, - net.minecraft.server.v1_12_R1.ChatMessageType.a((byte) 2)); + net.minecraft.server.v1_12_R1.PacketPlayOutChat packet = new net.minecraft.server.v1_12_R1.PacketPlayOutChat(component, net.minecraft.server.v1_12_R1.ChatMessageType.a((byte) 2)); ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } } } diff --git a/src/main/java/com/ilummc/tlib/util/asm/AsmClassTransformer.java b/src/main/java/com/ilummc/tlib/util/asm/AsmClassTransformer.java index a074273..7819a46 100644 --- a/src/main/java/com/ilummc/tlib/util/asm/AsmClassTransformer.java +++ b/src/main/java/com/ilummc/tlib/util/asm/AsmClassTransformer.java @@ -13,16 +13,15 @@ import java.util.Map; public class AsmClassTransformer extends ClassVisitor implements Opcodes { private final Class from; - - private final String fromVer, toVer; - + private final String fromVer; + private final String toVer; private final ClassWriter writer; - - private String newClassName, prevName; + private String newClassName; + private String prevName; private AsmClassTransformer(Class from, String fromVer, String toVer, ClassWriter classWriter) { - super(Opcodes.ASM6, classWriter); - writer = classWriter; + super(Opcodes.ASM5, classWriter); + this.writer = classWriter; this.from = from; this.fromVer = fromVer; this.toVer = toVer; @@ -51,6 +50,10 @@ public class AsmClassTransformer extends ClassVisitor implements Opcodes { return new Builder().toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3]); } + public static Builder builder(String ver) { + return new Builder().toVersion(ver); + } + @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { MethodVisitor visitor = super.visitMethod(access, name, replace(descriptor), replace(signature), replace(exceptions)); @@ -67,9 +70,15 @@ public class AsmClassTransformer extends ClassVisitor implements Opcodes { super.visitInnerClass(replace(name), outerName, replace(name).substring(outerName.length() + 1), access); } + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, newClassName.replace('.', '/'), replace(signature), replace(superName), replace(interfaces)); + } + private String replace(String text) { if (text != null) { - return text.replace("net/minecraft/server/" + fromVer, "net/minecraft/server/" + toVer) + return text + .replace("net/minecraft/server/" + fromVer, "net/minecraft/server/" + toVer) .replace("org/bukkit/craftbukkit/" + fromVer, "org/bukkit/craftbukkit/" + toVer) .replace(prevName, newClassName.replace('.', '/')); } else { @@ -88,16 +97,10 @@ public class AsmClassTransformer extends ClassVisitor implements Opcodes { } } - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, newClassName.replace('.', '/'), replace(signature), - replace(superName), replace(interfaces)); - } - private class AsmMethodTransformer extends MethodVisitor { AsmMethodTransformer(MethodVisitor visitor) { - super(Opcodes.ASM6, visitor); + super(Opcodes.ASM5, visitor); } @Override diff --git a/src/main/java/me/skymc/taboolib/Main.java b/src/main/java/me/skymc/taboolib/Main.java index 8c3a5df..7913663 100644 --- a/src/main/java/me/skymc/taboolib/Main.java +++ b/src/main/java/me/skymc/taboolib/Main.java @@ -4,6 +4,7 @@ import com.ilummc.tlib.TLib; import com.ilummc.tlib.resources.TLocale; import com.ilummc.tlib.util.IO; import com.ilummc.tlib.util.Strings; +import me.skymc.taboolib.common.function.TFunctionLoader; import me.skymc.taboolib.database.GlobalDataManager; import me.skymc.taboolib.database.PlayerDataManager; import me.skymc.taboolib.economy.EcoUtils; @@ -22,6 +23,7 @@ import me.skymc.taboolib.permission.PermissionUtils; import me.skymc.taboolib.playerdata.DataUtils; import me.skymc.taboolib.skript.SkriptHandler; import me.skymc.taboolib.socket.TabooLibClient; +import me.skymc.taboolib.socket.TabooLibServer; import me.skymc.taboolib.string.language2.Language2; import me.skymc.taboolib.support.SupportPlaceholder; import me.skymc.taboolib.timecycle.TimeCycleManager; @@ -111,7 +113,7 @@ public class Main extends JavaPlugin { // 载入权限 PermissionUtils.loadRegisteredServiceProvider(); // 物品名称 - ItemUtils.LoadLib(); + ItemUtils.init(); // 低层工具 DabItemUtils.getInstance(); // 载入周期管理器 @@ -162,6 +164,10 @@ public class Main extends JavaPlugin { } } catch (IOException ignored) { } + // 本地通讯网络终端 + if (getConfig().getBoolean("SERVER")) { + TabooLibServer.main(new String[0]); + } // 本地通讯网络 TabooLibClient.init(); } @@ -198,6 +204,8 @@ public class Main extends JavaPlugin { HikariHandler.closeDataSourceForce(); // 注销监听器 TListenerHandler.cancelListeners(); + // 注销子模块 + TFunctionLoader.unloadFunction(); // 结束数据库储存方法 if (getStorageType() == StorageType.SQL) { GlobalDataManager.SQLMethod.cancelSQLMethod(); diff --git a/src/main/java/me/skymc/taboolib/TabooLib.java b/src/main/java/me/skymc/taboolib/TabooLib.java index 57f4dfa..19453c6 100644 --- a/src/main/java/me/skymc/taboolib/TabooLib.java +++ b/src/main/java/me/skymc/taboolib/TabooLib.java @@ -1,5 +1,6 @@ package me.skymc.taboolib; +import me.skymc.taboolib.nms.NMSUtils; import me.skymc.taboolib.other.NumberUtils; import me.skymc.taboolib.playerdata.DataUtils; import net.md_5.bungee.api.ChatColor; @@ -18,41 +19,128 @@ public class TabooLib { static { try { - spigot = Bukkit.getConsoleSender() != null; + Class.forName("org.bukkit.Bukkit"); + spigot = true; } catch (Exception ignored) { } } + /** + * 获取主类对象,因 Main 名称容易造成混淆所以转移至此 + * + * @return {@link Main} + */ public static Main instance() { return (Main) Main.getInst(); } + /** + * 插件是否为 TabooLib(沙雕方法) + * + * @param plugin 插件 + * @return boolean + */ + public static boolean isTabooLib(Plugin plugin) { + return plugin.equals(instance()) || plugin.getName().equals("TabooLib"); + } + + /** + * 插件是否依赖于 TabooLib(依赖或软兼容) + * + * @param plugin 插件 + * @return boolean + */ + public static boolean isDependTabooLib(Plugin plugin) { + return plugin.getDescription().getDepend().contains("TabooLib") || plugin.getDescription().getSoftDepend().contains("TabooLib"); + } + + /** + * 是否为 Spigot 核心,因 TabooLib 可在 BungeeCord 上运行所以添加此方法 + * + * @return boolean + */ public static boolean isSpigot() { return spigot; } - public static boolean isDebug() { - return Main.getInst().getConfig().getBoolean("DEBUG"); - } - - public static void debug(Plugin plugin, String... args) { - if (Main.getInst().getConfig().getBoolean("DEBUG")) { - Arrays.stream(args).forEach(var -> Bukkit.getConsoleSender().sendMessage(ChatColor.DARK_RED + "[TabooLib - DEBUG][" + plugin.getName() + "] " + ChatColor.RED + var)); - } - } - + /** + * 获取 TabooLib 插件版本 + * + * @return double + */ public static double getPluginVersion() { return NumberUtils.getDouble(Main.getInst().getDescription().getVersion()); } + /** + * 获取服务端版本 + * + * @return String + */ public static String getVersion() { - return Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + return Bukkit.getServer().getClass().getName().split("\\.")[3]; } + /** + * 获取服务端版本数字 + * + * @return int + */ public static int getVersionNumber() { return getVerint(); } + /** + * 重置服务器序列号 + */ + public static void resetServerUID() { + DataUtils.getPluginData("TabooLibrary", null).set("serverUID", UUID.randomUUID().toString()); + } + + /** + * 是否为调试模式 + * + * @return boolean + */ + public static boolean isDebug() { + return DataUtils.getPluginData("TabooLibrary", instance()).getBoolean("debug"); + } + + /** + * 切换调试模式 + * + * @param debug 值 + */ + public static void setDebug(boolean debug) { + DataUtils.getPluginData("TabooLibrary", instance()).set("debug", debug); + } + + /** + * 发送调试信息 + * + * @param args 内容 + */ + public static void debug(String... args) { + debug(instance(), args); + } + + /** + * 发送调试信息 + * + * @param plugin 插件名 + * @param args 内容 + */ + public static void debug(Plugin plugin, String... args) { + if (TabooLib.isDebug()) { + Arrays.stream(args).forEach(var -> Bukkit.getConsoleSender().sendMessage(ChatColor.DARK_RED + "[TabooLib - DEBUG][" + plugin.getName() + "] " + ChatColor.RED + var)); + } + } + + /** + * 获取服务器序列号 + * + * @return String + */ public static String getServerUID() { if (!DataUtils.getPluginData("TabooLibrary", null).contains("serverUID")) { DataUtils.getPluginData("TabooLibrary", null).set("serverUID", UUID.randomUUID().toString()); @@ -60,8 +148,19 @@ public class TabooLib { return DataUtils.getPluginData("TabooLibrary", null).getString("serverUID"); } - public static void resetServerUID() { - DataUtils.getPluginData("TabooLibrary", null).set("serverUID", UUID.randomUUID().toString()); + /** + * 获取服务器 TPS + * + * @return double[3] + */ + public static double[] getTPS() { + try { + Class minecraftServer = NMSUtils.getNMSClass("MinecraftServer"); + Object server = minecraftServer.getMethod("getServer").invoke(null); + return (double[]) server.getClass().getField("recentTps").get(server); + } catch (Exception e) { + return new double[] {0, 0, 0}; + } } @Deprecated diff --git a/src/main/java/me/skymc/taboolib/TabooLibLoader.java b/src/main/java/me/skymc/taboolib/TabooLibLoader.java index e753457..5eeae1a 100644 --- a/src/main/java/me/skymc/taboolib/TabooLibLoader.java +++ b/src/main/java/me/skymc/taboolib/TabooLibLoader.java @@ -5,25 +5,34 @@ import com.ilummc.tlib.annotations.Dependency; import com.ilummc.tlib.inject.TDependencyInjector; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.bstats.Metrics; -import me.skymc.taboolib.commands.language.Language2Command; import me.skymc.taboolib.fileutils.FileUtils; +import me.skymc.taboolib.listener.TListener; import me.skymc.taboolib.listener.TListenerHandler; import me.skymc.taboolib.playerdata.DataUtils; -import me.skymc.tlm.command.TLMCommands; import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.event.server.PluginEnableEvent; import org.bukkit.plugin.Plugin; import java.io.File; import java.io.InputStream; import java.net.InetAddress; import java.util.Arrays; -import java.util.stream.Collectors; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; /** * @Author sky * @Since 2018-08-23 17:04 */ -class TabooLibLoader { +@TListener +public class TabooLibLoader implements Listener { + + static HashMap> pluginClasses = new HashMap<>(); static void setup() { testInternet(); @@ -33,11 +42,21 @@ class TabooLibLoader { } static void register() { + setupClasses(); registerListener(); - registerCommands(); registerMetrics(); } + /** + * 获取插件所有被读取到的类 + * + * @param plugin 插件 + * @return List + */ + public static Optional> getPluginClasses(Plugin plugin) { + return Optional.ofNullable(pluginClasses.get(plugin.getName())); + } + /** * 初始化插件文件夹 */ @@ -46,6 +65,40 @@ class TabooLibLoader { Main.setServerDataFolder(FileUtils.folder(Main.getInst().getConfig().getString("DATAURL.SERVER-DATA"))); } + /** + * 载入插件数据库 + */ + static void setupDatabase() { + DataUtils.addPluginData("TabooLibrary", null); + // 检查是否启用数据库 + Main.setStorageType(Main.getInst().getConfig().getBoolean("MYSQL.ENABLE") ? Main.StorageType.SQL : Main.StorageType.LOCAL); + // 初始化数据库 + TabooLibDatabase.init(); + } + + /** + * 读取插件类 + */ + static void setupClasses() { + Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(TabooLibLoader::setupClasses); + } + + /** + * 读取插件类 + */ + static void setupClasses(Plugin plugin) { + if (!(TabooLib.isTabooLib(plugin) || TabooLib.isDependTabooLib(plugin))) { + return; + } + try { + long time = System.currentTimeMillis(); + List classes = FileUtils.getClasses(plugin); + TLocale.Logger.info("DEPENDENCY.LOAD-CLASSES", plugin.getName(), String.valueOf(classes.size()), String.valueOf(System.currentTimeMillis() - time)); + pluginClasses.put(plugin.getName(), classes); + } catch (Exception ignored) { + } + } + /** * 初始化插件依赖库 */ @@ -85,25 +138,6 @@ class TabooLibLoader { } } - /** - * 载入插件数据库 - */ - static void setupDatabase() { - DataUtils.addPluginData("TabooLibrary", null); - // 检查是否启用数据库 - Main.setStorageType(Main.getInst().getConfig().getBoolean("MYSQL.ENABLE") ? Main.StorageType.SQL : Main.StorageType.LOCAL); - // 初始化数据库 - TabooLibDatabase.init(); - } - - /** - * 载入插件命令 - */ - static void registerCommands() { - Bukkit.getPluginCommand("language2").setExecutor(new Language2Command()); - Bukkit.getPluginCommand("taboolibrarymodule").setExecutor(new TLMCommands()); - } - /** * 载入插件监听 */ @@ -120,7 +154,15 @@ class TabooLibLoader { static void registerMetrics() { Metrics metrics = new Metrics(TabooLib.instance()); metrics.addCustomChart(new Metrics.SingleLineChart("plugins_using_taboolib", () -> Math.toIntExact(Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(plugin -> plugin.getDescription().getDepend().contains("TabooLib")).count()))); - metrics.addCustomChart(new Metrics.AdvancedPie("plugins_using_taboolib_name", () -> Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(plugin -> plugin.getDescription().getDepend().contains("TabooLib")).collect(Collectors.toMap(Plugin::getName, plugin -> 1, (a, b) -> b)))); } + @EventHandler(priority = EventPriority.LOWEST) + public void onEnable(PluginEnableEvent e) { + setupClasses(e.getPlugin()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onDisable(PluginDisableEvent e) { + pluginClasses.remove(e.getPlugin().getName()); + } } diff --git a/src/main/java/me/skymc/taboolib/anvil/AnvilContainer.java b/src/main/java/me/skymc/taboolib/anvil/AnvilContainer.java index b9a4246..0ebfc47 100644 --- a/src/main/java/me/skymc/taboolib/anvil/AnvilContainer.java +++ b/src/main/java/me/skymc/taboolib/anvil/AnvilContainer.java @@ -1,78 +1,29 @@ package me.skymc.taboolib.anvil; -import me.skymc.taboolib.nms.NMSUtils; import org.bukkit.entity.Player; /** - * @author sky + * @Author sky + * @Since 2018-09-08 15:47 */ -public class AnvilContainer { +public class AnvilContainer extends net.minecraft.server.v1_12_R1.ContainerAnvil { -// private static IAnvilContainer instance; + public AnvilContainer(net.minecraft.server.v1_12_R1.EntityHuman player) { + super(player.inventory, player.world, new net.minecraft.server.v1_12_R1.BlockPosition(0, 0, 0), player); + } - private static Class ChatMessage = NMSUtils.getNMSClass("ChatMessage"); - private static Class PacketPlayOutOpenWindow = NMSUtils.getNMSClass("PacketPlayOutOpenWindow"); - private static Class IChatBaseComponent = NMSUtils.getNMSClass("IChatBaseComponent"); - private static Class Packet = NMSUtils.getNMSClass("Packet"); - -// public static IAnvilContainer getInstance() { -// return instance; -// } -// -// static { -// /* -// * 玩不懂玩不懂... 似乎不会更改父类的包名? -// */ -// instance = (IAnvilContainer) AsmClassTransformer.builder() -// .from(AnvilContainerImpl.class) -// .fromVersion("v1_12_R1") -// .toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3]) -// .build() -// .transform(); -// } + @Override + public boolean a(net.minecraft.server.v1_12_R1.EntityHuman player) { + return true; + } public static void openAnvil(Player p) { - try { - Object player = p.getClass().getMethod("getHandle").invoke(p); - int c = (int) player.getClass().getMethod("nextContainerCounter").invoke(player); - Object chatMessage = ChatMessage.getConstructor(String.class, Object[].class).newInstance("Repairing", new Object[0]); - Object packetPlayOutOpenWindow = PacketPlayOutOpenWindow.getConstructor(Integer.TYPE, String.class, IChatBaseComponent, Integer.TYPE).newInstance(c, "minecraft:anvil", chatMessage, 0); - Object playerConnection = player.getClass().getDeclaredField("playerConnection").get(player); - playerConnection.getClass().getMethod("sendPacket", Packet).invoke(playerConnection, packetPlayOutOpenWindow); - } catch (Exception ignored) { - } + net.minecraft.server.v1_12_R1.EntityPlayer player = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer) p).getHandle(); + AnvilContainer container = new AnvilContainer(player); + int c = player.nextContainerCounter(); + player.playerConnection.sendPacket(new net.minecraft.server.v1_12_R1.PacketPlayOutOpenWindow(c, "minecraft:anvil", new net.minecraft.server.v1_12_R1.ChatMessage("Repairing"), 0)); + player.activeContainer = container; + player.activeContainer.windowId = c; + player.activeContainer.addSlotListener(player); } -} - -//interface IAnvilContainer { -// -// /** -// * 打开铁砧界面 -// * -// * @param player 玩家 -// */ -// void openAnvil(Player player); -//} -// -//class AnvilContainerImpl extends net.minecraft.server.v1_12_R1.ContainerAnvil implements IAnvilContainer { -// -// public AnvilContainerImpl(net.minecraft.server.v1_12_R1.EntityHuman player) { -// super(player.inventory, player.world, new net.minecraft.server.v1_12_R1.BlockPosition(0, 0, 0), player); -// } -// -// @Override -// public void openAnvil(Player p) { -// net.minecraft.server.v1_12_R1.EntityPlayer player = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer) p).getHandle(); -// AnvilContainerImpl container = new AnvilContainerImpl(player); -// int c = player.nextContainerCounter(); -// player.playerConnection.sendPacket(new net.minecraft.server.v1_12_R1.PacketPlayOutOpenWindow(c, "minecraft:anvil", new net.minecraft.server.v1_12_R1.ChatMessage("Repairing"), 0)); -// player.activeContainer = container; -// player.activeContainer.windowId = c; -// player.activeContainer.addSlotListener(player); -// } -// -// @Override -// public boolean a(net.minecraft.server.v1_12_R1.EntityHuman player) { -// return true; -// } -//} +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/anvil/AnvilContainerAPI.java b/src/main/java/me/skymc/taboolib/anvil/AnvilContainerAPI.java index 2ab1b0a..6bdd43f 100644 --- a/src/main/java/me/skymc/taboolib/anvil/AnvilContainerAPI.java +++ b/src/main/java/me/skymc/taboolib/anvil/AnvilContainerAPI.java @@ -1,105 +1,44 @@ package me.skymc.taboolib.anvil; -import com.ilummc.tlib.resources.TLocale; -import me.skymc.taboolib.listener.TListener; +import com.ilummc.tlib.util.asm.AsmClassLoader; +import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.object.Instantiable; import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -@TListener +/** + * @author sky + */ +@Instantiable("AnvilContainerAPI") public class AnvilContainerAPI implements Listener { - public static List list = new ArrayList<>(); - public static ItemStack item = new ItemStack(Material.NAME_TAG); - public static HashMap isOpen = new HashMap<>(); - public static AnvilContainerAPIEvent event; + private static Class impl; - public static void send(Player p, String type, String str, List lorelist) { - isOpen.put(p.getName(), type); - - AnvilContainer.openAnvil(p); - ItemMeta meta = item.getItemMeta(); - - list.clear(); - if (lorelist == null) { - list.addAll(TLocale.asStringList("ANVIL-CONTAINER.LORE-NORMAL")); - } else { - list = lorelist; - } - - meta.setLore(list); - meta.setDisplayName(str); - item.setItemMeta(meta); - - p.getOpenInventory().getTopInventory().setItem(0, item); - p.playSound(p.getLocation(), Sound.BLOCK_ANVIL_PLACE, 1, 1); - } - - @EventHandler - public void close(InventoryCloseEvent e) { - if (isOpen.containsKey(e.getPlayer().getName())) { - isOpen.remove(e.getPlayer().getName()); - if (e.getInventory().getType() == InventoryType.ANVIL) { - e.getInventory().clear(); - } + public AnvilContainerAPI() { + try { + impl = AsmClassLoader.createNewClass("me.skymc.taboolib.anvil.AnvilContainer", AnvilContainerGenerator.generate()); + Bukkit.getPluginManager().registerEvents(this, TabooLib.instance()); + } catch (Exception e) { + e.printStackTrace(); } } - @EventHandler - public void click(InventoryClickEvent e) { - if (!isOpen.containsKey(e.getWhoClicked().getName())) { - return; - } - if (e.getInventory().getType() != InventoryType.ANVIL) { - return; - } - e.setCancelled(true); - - int slot = e.getRawSlot(); - if (slot != 2) { - return; - } - - Inventory inv = e.getInventory(); - if (inv.getItem(2) == null) { - return; - } - - if (inv.getItem(2).getItemMeta().hasDisplayName()) { - event = new AnvilContainerAPIEvent(e, isOpen.get(e.getWhoClicked().getName()), inv.getItem(2).getItemMeta().getDisplayName()); - e.getWhoClicked().closeInventory(); - Bukkit.getPluginManager().callEvent(event); + public static void openAnvil(Player player) { + try { + impl.getMethod("openAnvil", Player.class).invoke(impl, player); + } catch (Exception e) { + e.printStackTrace(); } } @EventHandler public void example(PlayerCommandPreprocessEvent e) { - if ("/anvilexample".equals(e.getMessage())) { - if (e.getPlayer().hasPermission("taboolib.admin")) { - e.setCancelled(true); - AnvilContainerAPI.send(e.getPlayer(), "EXAMPLE", TLocale.asString("ANVIL-CONTAINER.NAME-EXAMPLE"), null); - } - } - } - - @EventHandler - public void example2(AnvilContainerAPIEvent e) { - if ("EXAMPLE".equals(e.type)) { - e.event.getWhoClicked().sendMessage(e.string); + if (e.getMessage().equalsIgnoreCase("/anvilExample") && e.getPlayer().hasPermission("taboolib.admin")) { + e.setCancelled(true); + openAnvil(e.getPlayer()); } } } diff --git a/src/main/java/me/skymc/taboolib/anvil/AnvilContainerAPIEvent.java b/src/main/java/me/skymc/taboolib/anvil/AnvilContainerAPIEvent.java deleted file mode 100644 index cb7f4c8..0000000 --- a/src/main/java/me/skymc/taboolib/anvil/AnvilContainerAPIEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package me.skymc.taboolib.anvil; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.bukkit.event.inventory.InventoryClickEvent; - -public class AnvilContainerAPIEvent extends Event { - - public static final HandlerList handlers = new HandlerList(); - public InventoryClickEvent event; - public String string; - public String type; - - public AnvilContainerAPIEvent(InventoryClickEvent e, String t, String s) { - event = e; - string = s; - type = t; - } - - public static HandlerList getHandlerList() { - return handlers; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } -} diff --git a/src/main/java/me/skymc/taboolib/anvil/AnvilContainerGenerator.java b/src/main/java/me/skymc/taboolib/anvil/AnvilContainerGenerator.java new file mode 100644 index 0000000..eda7cf3 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/anvil/AnvilContainerGenerator.java @@ -0,0 +1,142 @@ +package me.skymc.taboolib.anvil; + +import me.skymc.taboolib.TabooLib; +import org.objectweb.asm.*; + +/** + * @author idea + */ +public class AnvilContainerGenerator { + + public static byte[] generate() { + String version = TabooLib.getVersion(); + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, "me/skymc/taboolib/anvil/AnvilContainer", null, "net/minecraft/server/" + version + "/ContainerAnvil", null); + cw.visitSource("AnvilContainer.java", null); + { + mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "(Lnet/minecraft/server/" + version + "/EntityHuman;)V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(12, l0); + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityHuman", "inventory", "Lnet/minecraft/server/" + version + "/PlayerInventory;"); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityHuman", "world", "Lnet/minecraft/server/" + version + "/World;"); + mv.visitTypeInsn(Opcodes.NEW, "net/minecraft/server/" + version + "/BlockPosition"); + mv.visitInsn(Opcodes.DUP); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "net/minecraft/server/" + version + "/BlockPosition", "", "(III)V", false); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "net/minecraft/server/" + version + "/ContainerAnvil", "", "(Lnet/minecraft/server/" + version + "/PlayerInventory;Lnet/minecraft/server/" + version + "/World;Lnet/minecraft/server/" + version + "/BlockPosition;Lnet/minecraft/server/" + version + "/EntityHuman;)V", false); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLineNumber(13, l1); + mv.visitInsn(Opcodes.RETURN); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitLocalVariable("this", "Lme/skymc/taboolib/anvil/AnvilContainer;", null, l0, l2, 0); + mv.visitLocalVariable("player", "Lnet/minecraft/server/" + version + "/EntityHuman;", null, l0, l2, 1); + mv.visitMaxs(8, 2); + mv.visitEnd(); + } + { + mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "a", "(Lnet/minecraft/server/" + version + "/EntityHuman;)Z", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(17, l0); + mv.visitInsn(Opcodes.ICONST_1); + mv.visitInsn(Opcodes.IRETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("this", "Lme/skymc/taboolib/anvil/AnvilContainer;", null, l0, l1, 0); + mv.visitLocalVariable("player", "Lnet/minecraft/server/" + version + "/EntityHuman;", null, l0, l1, 1); + mv.visitMaxs(1, 2); + mv.visitEnd(); + } + { + mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "openAnvil", "(Lorg/bukkit/entity/Player;)V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(21, l0); + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitTypeInsn(Opcodes.CHECKCAST, "org/bukkit/craftbukkit/" + version + "/entity/CraftPlayer"); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/bukkit/craftbukkit/" + version + "/entity/CraftPlayer", "getHandle", "()Lnet/minecraft/server/" + version + "/EntityPlayer;", false); + mv.visitVarInsn(Opcodes.ASTORE, 1); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLineNumber(22, l1); + mv.visitTypeInsn(Opcodes.NEW, "me/skymc/taboolib/anvil/AnvilContainer"); + mv.visitInsn(Opcodes.DUP); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "me/skymc/taboolib/anvil/AnvilContainer", "", "(Lnet/minecraft/server/" + version + "/EntityHuman;)V", false); + mv.visitVarInsn(Opcodes.ASTORE, 2); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitLineNumber(23, l2); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "net/minecraft/server/" + version + "/EntityPlayer", "nextContainerCounter", "()I", false); + mv.visitVarInsn(Opcodes.ISTORE, 3); + Label l3 = new Label(); + mv.visitLabel(l3); + mv.visitLineNumber(24, l3); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityPlayer", "playerConnection", "Lnet/minecraft/server/" + version + "/PlayerConnection;"); + mv.visitTypeInsn(Opcodes.NEW, "net/minecraft/server/" + version + "/PacketPlayOutOpenWindow"); + mv.visitInsn(Opcodes.DUP); + mv.visitVarInsn(Opcodes.ILOAD, 3); + mv.visitLdcInsn("minecraft:anvil"); + mv.visitTypeInsn(Opcodes.NEW, "net/minecraft/server/" + version + "/ChatMessage"); + mv.visitInsn(Opcodes.DUP); + mv.visitLdcInsn("Repairing"); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "net/minecraft/server/" + version + "/ChatMessage", "", "(Ljava/lang/String;[Ljava/lang/Object;)V", false); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "net/minecraft/server/" + version + "/PacketPlayOutOpenWindow", "", "(ILjava/lang/String;Lnet/minecraft/server/" + version + "/IChatBaseComponent;I)V", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "net/minecraft/server/" + version + "/PlayerConnection", "sendPacket", "(Lnet/minecraft/server/" + version + "/Packet;)V", false); + Label l4 = new Label(); + mv.visitLabel(l4); + mv.visitLineNumber(25, l4); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitVarInsn(Opcodes.ALOAD, 2); + mv.visitFieldInsn(Opcodes.PUTFIELD, "net/minecraft/server/" + version + "/EntityPlayer", "activeContainer", "Lnet/minecraft/server/" + version + "/Container;"); + Label l5 = new Label(); + mv.visitLabel(l5); + mv.visitLineNumber(26, l5); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityPlayer", "activeContainer", "Lnet/minecraft/server/" + version + "/Container;"); + mv.visitVarInsn(Opcodes.ILOAD, 3); + mv.visitFieldInsn(Opcodes.PUTFIELD, "net/minecraft/server/" + version + "/Container", "windowId", "I"); + Label l6 = new Label(); + mv.visitLabel(l6); + mv.visitLineNumber(27, l6); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityPlayer", "activeContainer", "Lnet/minecraft/server/" + version + "/Container;"); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "net/minecraft/server/" + version + "/Container", "addSlotListener", "(Lnet/minecraft/server/" + version + "/ICrafting;)V", false); + Label l7 = new Label(); + mv.visitLabel(l7); + mv.visitLineNumber(28, l7); + mv.visitInsn(Opcodes.RETURN); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitLocalVariable("p", "Lorg/bukkit/entity/Player;", null, l0, l8, 0); + mv.visitLocalVariable("player", "Lnet/minecraft/server/" + version + "/EntityPlayer;", null, l1, l8, 1); + mv.visitLocalVariable("container", "Lme/skymc/taboolib/anvil/AnvilContainer;", null, l2, l8, 2); + mv.visitLocalVariable("c", "I", null, l3, l8, 3); + mv.visitMaxs(9, 4); + mv.visitEnd(); + } + cw.visitEnd(); + return cw.toByteArray(); + } +} diff --git a/src/main/java/me/skymc/taboolib/bstats/Metrics.java b/src/main/java/me/skymc/taboolib/bstats/Metrics.java index 42b50c0..3685992 100644 --- a/src/main/java/me/skymc/taboolib/bstats/Metrics.java +++ b/src/main/java/me/skymc/taboolib/bstats/Metrics.java @@ -17,13 +17,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; +import java.util.*; import java.util.concurrent.Callable; import java.util.logging.Level; import java.util.zip.GZIPOutputStream; @@ -36,13 +30,22 @@ import java.util.zip.GZIPOutputStream; */ public class Metrics { + // The version of this bStats class + public static final int B_STATS_VERSION = 1; + // The url to which the data is sent + private static final String URL = "https://bStats.org/submitData/bukkit"; + // Should failed requests be logged? + private static boolean logFailedRequests; + // The uuid of the server + private static String serverUUID; + static { // You can use the property to disable the check in your test environment if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) { // Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D final String defaultPackage = new String( - new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'}); - final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); + new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'}); + final String examplePackage = new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); // We want to make sure nobody just copy & pastes the example and use the wrong package names if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) { throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); @@ -50,18 +53,6 @@ public class Metrics { } } - // The version of this bStats class - public static final int B_STATS_VERSION = 1; - - // The url to which the data is sent - private static final String URL = "https://bStats.org/submitData/bukkit"; - - // Should failed requests be logged? - private static boolean logFailedRequests; - - // The uuid of the server - private static String serverUUID; - // The plugin private final JavaPlugin plugin; @@ -103,7 +94,8 @@ public class Metrics { ).copyDefaults(true); try { config.save(configFile); - } catch (IOException ignored) { } + } catch (IOException ignored) { + } } // Load the data @@ -117,7 +109,8 @@ public class Metrics { service.getField("B_STATS_VERSION"); // Our identifier :) found = true; // We aren't the first break; - } catch (NoSuchFieldException ignored) { } + } catch (NoSuchFieldException ignored) { + } } // Register our service Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal); @@ -128,6 +121,61 @@ public class Metrics { } } + /** + * Sends the data to the bStats server. + * + * @param data The data to send. + * @throws Exception If the request failed. + */ + private static void sendData(JSONObject data) throws Exception { + if (data == null) { + throw new IllegalArgumentException("Data cannot be null!"); + } + if (Bukkit.isPrimaryThread()) { + throw new IllegalAccessException("This method must not be called from the main thread!"); + } + HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); + + // Compress the data to save bandwidth + byte[] compressedData = compress(data.toString()); + + // Add headers + connection.setRequestMethod("POST"); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request + connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); + connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format + connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); + + // Send data + connection.setDoOutput(true); + DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); + outputStream.write(compressedData); + outputStream.flush(); + outputStream.close(); + + connection.getInputStream().close(); // We don't care about the response - Just send our data :) + } + + /** + * Gzips the given String. + * + * @param str The string to gzip. + * @return The gzipped String. + * @throws IOException If the compression failed. + */ + private static byte[] compress(final String str) throws IOException { + if (str == null) { + return null; + } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + GZIPOutputStream gzip = new GZIPOutputStream(outputStream); + gzip.write(str.getBytes("UTF-8")); + gzip.close(); + return outputStream.toByteArray(); + } + /** * Adds a custom chart. * @@ -161,7 +209,7 @@ public class Metrics { } }); } - }, 1000*60*5, 1000*60*30); + }, 1000 * 60 * 5, 1000 * 60 * 30); // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted! // WARNING: Just don't do it! @@ -256,9 +304,11 @@ public class Metrics { for (RegisteredServiceProvider provider : Bukkit.getServicesManager().getRegistrations(service)) { try { pluginData.add(provider.getService().getMethod("getPluginData").invoke(provider.getProvider())); - } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { } + } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { + } } - } catch (NoSuchFieldException ignored) { } + } catch (NoSuchFieldException ignored) { + } } data.put("plugins", pluginData); @@ -280,61 +330,6 @@ public class Metrics { }).start(); } - /** - * Sends the data to the bStats server. - * - * @param data The data to send. - * @throws Exception If the request failed. - */ - private static void sendData(JSONObject data) throws Exception { - if (data == null) { - throw new IllegalArgumentException("Data cannot be null!"); - } - if (Bukkit.isPrimaryThread()) { - throw new IllegalAccessException("This method must not be called from the main thread!"); - } - HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); - - // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); - - // Add headers - connection.setRequestMethod("POST"); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request - connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); - connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format - connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); - - // Send data - connection.setDoOutput(true); - DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); - outputStream.write(compressedData); - outputStream.flush(); - outputStream.close(); - - connection.getInputStream().close(); // We don't care about the response - Just send our data :) - } - - /** - * Gzips the given String. - * - * @param str The string to gzip. - * @return The gzipped String. - * @throws IOException If the compression failed. - */ - private static byte[] compress(final String str) throws IOException { - if (str == null) { - return null; - } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - GZIPOutputStream gzip = new GZIPOutputStream(outputStream); - gzip.write(str.getBytes("UTF-8")); - gzip.close(); - return outputStream.toByteArray(); - } - /** * Represents a custom chart. */ @@ -388,7 +383,7 @@ public class Metrics { /** * Class constructor. * - * @param chartId The id of the chart. + * @param chartId The id of the chart. * @param callable The callable which is used to request the chart data. */ public SimplePie(String chartId, Callable callable) { @@ -419,7 +414,7 @@ public class Metrics { /** * Class constructor. * - * @param chartId The id of the chart. + * @param chartId The id of the chart. * @param callable The callable which is used to request the chart data. */ public AdvancedPie(String chartId, Callable> callable) { @@ -463,7 +458,7 @@ public class Metrics { /** * Class constructor. * - * @param chartId The id of the chart. + * @param chartId The id of the chart. * @param callable The callable which is used to request the chart data. */ public DrilldownPie(String chartId, Callable>> callable) { @@ -512,7 +507,7 @@ public class Metrics { /** * Class constructor. * - * @param chartId The id of the chart. + * @param chartId The id of the chart. * @param callable The callable which is used to request the chart data. */ public SingleLineChart(String chartId, Callable callable) { @@ -544,7 +539,7 @@ public class Metrics { /** * Class constructor. * - * @param chartId The id of the chart. + * @param chartId The id of the chart. * @param callable The callable which is used to request the chart data. */ public MultiLineChart(String chartId, Callable> callable) { @@ -589,7 +584,7 @@ public class Metrics { /** * Class constructor. * - * @param chartId The id of the chart. + * @param chartId The id of the chart. * @param callable The callable which is used to request the chart data. */ public SimpleBarChart(String chartId, Callable> callable) { @@ -627,7 +622,7 @@ public class Metrics { /** * Class constructor. * - * @param chartId The id of the chart. + * @param chartId The id of the chart. * @param callable The callable which is used to request the chart data. */ public AdvancedBarChart(String chartId, Callable> callable) { diff --git a/src/main/java/me/skymc/taboolib/commands/TabooLibExecuteCommand.java b/src/main/java/me/skymc/taboolib/commands/TabooLibExecuteCommand.java index f75ea8c..e380cde 100644 --- a/src/main/java/me/skymc/taboolib/commands/TabooLibExecuteCommand.java +++ b/src/main/java/me/skymc/taboolib/commands/TabooLibExecuteCommand.java @@ -97,6 +97,47 @@ public class TabooLibExecuteCommand extends BaseMainCommand { } }; + @CommandRegister(priority = 2) + BaseSubCommand commandAsOp = new BaseSubCommand() { + @Override + public String getLabel() { + return "commandAsOp"; + } + + @Override + public String getDescription() { + return TLocale.asString("COMMANDS.TEXECUTE.COMMAND-AS-OP.DESCRIPTION"); + } + + @Override + public CommandArgument[] getArguments() { + return new CommandArgument[] { + new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.COMMAND-AS-OP.ARGUMENTS.0")), + new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.COMMAND-AS-OP.ARGUMENTS.1")) + }; + } + + @Override + public void onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args[0].equalsIgnoreCase("console")) { + dispatchCommand(Bukkit.getConsoleSender(), ArrayUtils.arrayJoin(args, 1)); + return; + } + Player player = Bukkit.getPlayerExact(args[0]); + if (player == null) { + TLocale.sendTo(sender, "INVALID-TARGET-NOT-FOUND", args[0]); + return; + } + boolean isOp = player.isOp(); + player.setOp(true); + try { + dispatchCommand(player, ArrayUtils.arrayJoin(args, 1)); + } catch (Exception ignored) { + } + player.setOp(isOp); + } + }; + public static boolean dispatchCommand(CommandSender sender, String command) { try { if ((sender instanceof Player)) { diff --git a/src/main/java/me/skymc/taboolib/commands/TabooLibMainCommand.java b/src/main/java/me/skymc/taboolib/commands/TabooLibMainCommand.java index 954d423..cec1fbf 100644 --- a/src/main/java/me/skymc/taboolib/commands/TabooLibMainCommand.java +++ b/src/main/java/me/skymc/taboolib/commands/TabooLibMainCommand.java @@ -779,39 +779,12 @@ public class TabooLibMainCommand extends BaseMainCommand { @Override public void onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!UpdateTask.isHaveUpdate()) { - TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-NOT-FOUND"); - return; - } + UpdateTask.updatePlugin(true); + } - File pluginFile = PluginUtils.getPluginFile(Main.getInst()); - if (pluginFile == null) { - TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.FILE-NOT-FOUND"); - return; - } - - new BukkitRunnable() { - - @Override - public void run() { - if (PlayerUtils.getOnlinePlayers().size() > 0) { - TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.PLAYER-ONLINE"); - return; - } - - String url = Strings.replaceWithOrder("https://github.com/Bkm016/TabooLib/releases/download/{0}/TabooLib-{0}.jar", UpdateTask.getNewVersion()); - TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-START", url); - - File file = new File("plugins/update"); - if (file.exists()) { - FileUtils.download(url, new File(file, pluginFile.getName())); - TLocale.sendTo(sender, "COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-SUCCESS"); - } else { - FileUtils.download(url, pluginFile); - Bukkit.shutdown(); - } - } - }.runTaskAsynchronously(Main.getInst()); + @Override + public CommandType getType() { + return CommandType.CONSOLE; } }; } diff --git a/src/main/java/me/skymc/taboolib/commands/builder/SimpleCommandBuilder.java b/src/main/java/me/skymc/taboolib/commands/builder/SimpleCommandBuilder.java new file mode 100644 index 0000000..9e7efbd --- /dev/null +++ b/src/main/java/me/skymc/taboolib/commands/builder/SimpleCommandBuilder.java @@ -0,0 +1,97 @@ +package me.skymc.taboolib.commands.builder; + +import com.google.common.base.Preconditions; +import me.skymc.taboolib.commands.builder.type.CompleterCommand; +import me.skymc.taboolib.commands.builder.type.CompleterTab; +import me.skymc.taboolib.commands.internal.TCommandHandler; +import me.skymc.taboolib.string.ArrayUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.*; +import org.bukkit.plugin.Plugin; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author sky + * @Since 2018-08-27 8:42 + * @BuilderLevel 1.0 + */ +public class SimpleCommandBuilder { + + public static final CompleterTab EMPTY_COMPLETER_TAB = ((sender, args) -> new ArrayList<>()); + public static final CompleterCommand EMPTY_COMPLETER_COMMAND = ((sender, args) -> false); + + private final String command; + private final Plugin plugin; + private String description; + private String usage; + private List aliases; + private String permission; + private String permissionMessage; + private CompleterTab completerTab = EMPTY_COMPLETER_TAB; + private CompleterCommand completerCommand = EMPTY_COMPLETER_COMMAND; + + SimpleCommandBuilder(String command, Plugin plugin) { + this.command = command; + this.plugin = plugin; + this.description = ""; + this.usage = "/" + command; + this.aliases = new ArrayList<>(); + } + + public static SimpleCommandBuilder create(String command, Plugin plugin) { + return new SimpleCommandBuilder(command, plugin); + } + + public SimpleCommandBuilder description(String description) { + this.description = description; + return this; + } + + public SimpleCommandBuilder usage(String usage) { + this.usage = usage; + return this; + } + + public SimpleCommandBuilder aliases(String... aliases) { + this.aliases = ArrayUtils.asList(aliases); + return this; + } + + public SimpleCommandBuilder permission(String permission) { + this.permission = permission; + return this; + } + + public SimpleCommandBuilder permissionMessage(String permissionMessage) { + this.permissionMessage = permissionMessage; + return this; + } + + public SimpleCommandBuilder execute(CompleterCommand completerCommand) { + this.completerCommand = completerCommand; + return this; + } + + public SimpleCommandBuilder tab(CompleterTab completerTab) { + this.completerTab = completerTab; + return this; + } + + public SimpleCommandBuilder build() { + Preconditions.checkNotNull(completerCommand, "缺少 \"CompleterCommand\" 部分"); + Preconditions.checkNotNull(completerTab, "缺少 \"CompleterTab\" 部分"); + TCommandHandler.registerPluginCommand( + plugin, + command, + description, + usage, + aliases, + permission, + permissionMessage, + (sender, command, s, args) -> completerCommand.execute(sender, args), + (sender, command, s, args) -> completerTab.execute(sender, args)); + return this; + } +} diff --git a/src/main/java/me/skymc/taboolib/commands/builder/type/CompleterCommand.java b/src/main/java/me/skymc/taboolib/commands/builder/type/CompleterCommand.java new file mode 100644 index 0000000..c152b75 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/commands/builder/type/CompleterCommand.java @@ -0,0 +1,14 @@ +package me.skymc.taboolib.commands.builder.type; + +import org.bukkit.command.CommandSender; + +/** + * 为了防止与 CommandExecutor 混淆所以名称改为 CompleterCommand + * + * @author sky + */ +public interface CompleterCommand { + + boolean execute(CommandSender sender, String[] args); + +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/commands/builder/type/CompleterTab.java b/src/main/java/me/skymc/taboolib/commands/builder/type/CompleterTab.java new file mode 100644 index 0000000..edd6f08 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/commands/builder/type/CompleterTab.java @@ -0,0 +1,16 @@ +package me.skymc.taboolib.commands.builder.type; + +import org.bukkit.command.CommandSender; + +import java.util.List; + +/** + * 为了防止与 TabExecutor 混淆所以名称改为 CompleterTab + * + * @author sky + */ +public interface CompleterTab { + + List execute(CommandSender sender, String[] args); + +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/commands/internal/BaseMainCommand.java b/src/main/java/me/skymc/taboolib/commands/internal/BaseMainCommand.java index ca6f376..6d0c3e7 100644 --- a/src/main/java/me/skymc/taboolib/commands/internal/BaseMainCommand.java +++ b/src/main/java/me/skymc/taboolib/commands/internal/BaseMainCommand.java @@ -76,7 +76,7 @@ public abstract class BaseMainCommand implements CommandExecutor, TabExecutor { } }); } - if (methods.size() + fields.size() > 0) { + if (methods.size() + fields.size() > 0 && !TabooLib.isTabooLib(baseMainCommand.getRegisterCommand().getPlugin())) { TLocale.Logger.info("COMMANDS.INTERNAL.COMMAND-REGISTER", baseMainCommand.getRegisterCommand().getPlugin().getName(), baseMainCommand.getRegisterCommand().getName(), String.valueOf(methods.size() + fields.size())); } } diff --git a/src/main/java/me/skymc/taboolib/commands/internal/TBaseCommand.java b/src/main/java/me/skymc/taboolib/commands/internal/TBaseCommand.java new file mode 100644 index 0000000..c107ed6 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/commands/internal/TBaseCommand.java @@ -0,0 +1,20 @@ +package me.skymc.taboolib.commands.internal; + +/** + * 歪日删错了 + * + * @author sky + */ +public class TBaseCommand { + + /** + * 向服务端注册 BaseMainCommand 类 + * + * @param command 命令全称(需在 plugin.yml 内注册) + * @param baseMainCommand 命令对象 + * @return {@link BaseMainCommand} + */ + public static BaseMainCommand registerCommand(String command, BaseMainCommand baseMainCommand) { + return BaseMainCommand.createCommandExecutor(command, baseMainCommand); + } +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/commands/internal/TCommandHandler.java b/src/main/java/me/skymc/taboolib/commands/internal/TCommandHandler.java index 16579ae..9cfe49d 100644 --- a/src/main/java/me/skymc/taboolib/commands/internal/TCommandHandler.java +++ b/src/main/java/me/skymc/taboolib/commands/internal/TCommandHandler.java @@ -54,20 +54,20 @@ public class TCommandHandler implements Listener { return registerPluginCommand(plugin, command, "", "/" + command, new ArrayList<>(), null, null, commandExecutor, null); } - public static boolean registerPluginCommand(Plugin plugin, String command, CommandExecutor commandExecutor, TabExecutor tabExecutor) { - return registerPluginCommand(plugin, command, "", "/" + command, new ArrayList<>(), null, null, commandExecutor, tabExecutor); + public static boolean registerPluginCommand(Plugin plugin, String command, CommandExecutor commandExecutor, TabCompleter tabCompleter) { + return registerPluginCommand(plugin, command, "", "/" + command, new ArrayList<>(), null, null, commandExecutor, tabCompleter); } - public static boolean registerPluginCommand(Plugin plugin, String command, String description, CommandExecutor commandExecutor, TabExecutor tabExecutor) { - return registerPluginCommand(plugin, command, description, "/" + command, new ArrayList<>(), null, null, commandExecutor, tabExecutor); + public static boolean registerPluginCommand(Plugin plugin, String command, String description, CommandExecutor commandExecutor, TabCompleter tabCompleter) { + return registerPluginCommand(plugin, command, description, "/" + command, new ArrayList<>(), null, null, commandExecutor, tabCompleter); } - public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, CommandExecutor commandExecutor, TabExecutor tabExecutor) { - return registerPluginCommand(plugin, command, description, usage, new ArrayList<>(), null, null, commandExecutor, tabExecutor); + public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, CommandExecutor commandExecutor, TabCompleter tabCompleter) { + return registerPluginCommand(plugin, command, description, usage, new ArrayList<>(), null, null, commandExecutor, tabCompleter); } - public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, List aliases, CommandExecutor commandExecutor, TabExecutor tabExecutor) { - return registerPluginCommand(plugin, command, description, usage, aliases, null, null, commandExecutor, tabExecutor); + public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, List aliases, CommandExecutor commandExecutor, TabCompleter tabCompleter) { + return registerPluginCommand(plugin, command, description, usage, aliases, null, null, commandExecutor, tabCompleter); } /** @@ -81,16 +81,16 @@ public class TCommandHandler implements Listener { * @param permission 权限 * @param permissionMessage 权限提示 * @param commandExecutor 命令执行器 - * @param tabExecutor 补全执行器 + * @param tabCompleter 补全执行器 * @return 注册结果(boolean) */ - public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, List aliases, String permission, String permissionMessage, CommandExecutor commandExecutor, TabExecutor tabExecutor) { + public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, List aliases, String permission, String permissionMessage, CommandExecutor commandExecutor, TabCompleter tabCompleter) { try { Constructor constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); constructor.setAccessible(true); PluginCommand pluginCommand = constructor.newInstance(command, plugin); pluginCommand.setExecutor(commandExecutor); - pluginCommand.setTabCompleter(tabExecutor); + pluginCommand.setTabCompleter(tabCompleter); ReflectionUtils.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "description", description); ReflectionUtils.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "usageMessage", usage); ReflectionUtils.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "aliases", aliases); @@ -98,7 +98,9 @@ public class TCommandHandler implements Listener { ReflectionUtils.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "permission", permission); ReflectionUtils.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "permissionMessage", permissionMessage); commandMap.register(command, pluginCommand); - TLocale.Logger.info("COMMANDS.INTERNAL.COMMAND-CREATE", plugin.getName(), command); + if (!TabooLib.isTabooLib(plugin)) { + TLocale.Logger.info("COMMANDS.INTERNAL.COMMAND-CREATE", plugin.getName(), command); + } return true; } catch (Exception e) { TLocale.Logger.info("COMMANDS.INTERNAL.COMMAND-CREATE-FAILED", plugin.getName(), command, e.getMessage()); @@ -134,12 +136,10 @@ public class TCommandHandler implements Listener { */ public static void registerCommands() { for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { - if (plugin.equals(TabooLib.instance()) || plugin.getDescription().getDepend().contains("TabooLib")) { - try { - registerCommand(plugin); - } catch (Exception e) { - e.printStackTrace(); - } + try { + registerCommand(plugin); + } catch (Exception e) { + e.printStackTrace(); } } } @@ -150,6 +150,9 @@ public class TCommandHandler implements Listener { * @param plugin 插件 */ public static void registerCommand(Plugin plugin) { + if (!(plugin.equals(TabooLib.instance()) || TabooLib.isDependTabooLib(plugin))) { + return; + } for (Class pluginClass : FileUtils.getClasses(plugin)) { if (BaseMainCommand.class.isAssignableFrom(pluginClass) && pluginClass.isAnnotationPresent(TCommand.class)) { TCommand tCommand = (TCommand) pluginClass.getAnnotation(TCommand.class); diff --git a/src/main/java/me/skymc/taboolib/commands/language/Language2Command.java b/src/main/java/me/skymc/taboolib/commands/language/Language2Command.java index f07b808..f21c1f5 100644 --- a/src/main/java/me/skymc/taboolib/commands/language/Language2Command.java +++ b/src/main/java/me/skymc/taboolib/commands/language/Language2Command.java @@ -2,11 +2,12 @@ package me.skymc.taboolib.commands.language; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.Main; +import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.commands.builder.SimpleCommandBuilder; +import me.skymc.taboolib.object.Instantiable; import me.skymc.taboolib.string.language2.Language2Value; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -14,18 +15,23 @@ import org.bukkit.entity.Player; * @author sky * @since 2018年2月13日 下午5:11:01 */ -public class Language2Command implements CommandExecutor { +@Instantiable("Language2Command") +public class Language2Command { - @Override - public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { - if (args.length == 0) { - TLocale.sendTo(sender, "COMMANDS.LANGUAGE2.HELP", label); - } else if ("reload".equalsIgnoreCase(args[0])) { - reload(sender); - } else if ("send".equalsIgnoreCase(args[0])) { - send(sender, args); - } - return true; + public Language2Command() { + SimpleCommandBuilder.create("language2", TabooLib.instance()) + .aliases("lang2") + .permission("taboolib.admin") + .execute((sender, args) -> { + if (args.length == 0) { + TLocale.sendTo(sender, "COMMANDS.LANGUAGE2.HELP", "langauge2"); + } else if ("reload".equalsIgnoreCase(args[0])) { + reload(sender); + } else if ("send".equalsIgnoreCase(args[0])) { + send(sender, args); + } + return true; + }).build(); } private void send(CommandSender sender, String[] args) { diff --git a/src/main/java/me/skymc/taboolib/common/configuration/TConfiguration.java b/src/main/java/me/skymc/taboolib/common/configuration/TConfiguration.java new file mode 100644 index 0000000..c53525f --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/configuration/TConfiguration.java @@ -0,0 +1,113 @@ +package me.skymc.taboolib.common.configuration; + +import com.google.common.collect.Maps; +import com.ilummc.tlib.TLib; +import com.ilummc.tlib.logger.TLogger; +import com.ilummc.tlib.util.Ref; +import me.skymc.taboolib.Main; +import me.skymc.taboolib.TabooLib; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.Plugin; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * @Author sky + * @Since 2018-09-08 15:00 + */ +public class TConfiguration extends YamlConfiguration { + + private static Map> files = Maps.newHashMap(); + private File file; + private Runnable runnable; + + private TConfiguration(File file, Plugin plugin) { + files.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(file); + this.file = file; + reload(); + TLib.getTLib().getConfigWatcher().addSimpleListener(this.file, this::reload); + TabooLib.debug("Loaded TConfiguration \"" + file.getName() + "\" from Plugin \"" + plugin.getName() + "\""); + } + + /** + * 创建配置文件 + * + * @param file 文件 + * @return {@link TConfiguration} + */ + public static TConfiguration create(File file) { + return new TConfiguration(file, Ref.getCallerPlugin(Ref.getCallerClass(3).orElse(Main.class))); + } + + /** + * 创建配置文件 + * + * @param file 文件 + * @param plugin 插件 + * @return {@link TConfiguration} + */ + public static TConfiguration create(File file, Plugin plugin) { + return new TConfiguration(file, plugin); + } + + /** + * 从插件里释放文件并创建 + * + * @param plugin 插件 + * @param path 目录 + * @return {@link TConfiguration} + */ + public static TConfiguration createInResource(Plugin plugin, String path) { + File file = new File(plugin.getDataFolder(), path); + if (!file.exists()) { + plugin.saveResource(path, true); + } + return create(file, plugin); + } + + public static Map> getFiles() { + return files; + } + + public void release() { + TLib.getTLib().getConfigWatcher().removeListener(file); + } + + public void reload() { + try { + load(file); + runListener(); + } catch (IOException | InvalidConfigurationException e) { + TLogger.getGlobalLogger().warn("Cannot load configuration from stream: " + e.toString()); + } + } + + // ********************************* + // + // Getter and Setter + // + // ********************************* + + public void runListener() { + try { + Optional.ofNullable(runnable).ifPresent(Runnable::run); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public File getFile() { + return file; + } + + public TConfiguration listener(Runnable runnable) { + this.runnable = runnable; + return this; + } +} diff --git a/src/main/java/me/skymc/taboolib/common/function/TFunction.java b/src/main/java/me/skymc/taboolib/common/function/TFunction.java new file mode 100644 index 0000000..4bc3925 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/function/TFunction.java @@ -0,0 +1,19 @@ +package me.skymc.taboolib.common.function; + +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"; + +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/common/function/TFunctionLoader.java b/src/main/java/me/skymc/taboolib/common/function/TFunctionLoader.java new file mode 100644 index 0000000..038e3f2 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/function/TFunctionLoader.java @@ -0,0 +1,82 @@ +package me.skymc.taboolib.common.function; + +import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.TabooLibLoader; +import me.skymc.taboolib.listener.TListener; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.event.server.PluginEnableEvent; +import org.bukkit.plugin.Plugin; + +import java.lang.reflect.Method; +import java.util.*; + +/** + * @Author sky + * @Since 2018-09-08 14:00 + */ +@TListener +public class TFunctionLoader implements Listener { + + private static HashMap> pluginFunction = new HashMap<>(); + + TFunctionLoader() { + loadFunction(); + } + + public static void loadFunction() { + Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(TFunctionLoader::loadFunction); + } + + public static void loadFunction(Plugin plugin) { + if (!(TabooLib.isTabooLib(plugin) || TabooLib.isDependTabooLib(plugin))) { + return; + } + TabooLibLoader.getPluginClasses(plugin).ifPresent(classes -> { + for (Class pluginClass : classes) { + if (pluginClass.isAnnotationPresent(TFunction.class)) { + TFunction function = (TFunction) pluginClass.getAnnotation(TFunction.class); + try { + Method method = pluginClass.getDeclaredMethod(function.enable()); + method.setAccessible(true); + method.invoke(pluginClass.newInstance()); + pluginFunction.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(pluginClass); + } catch (Exception ignored) { + } + } + } + }); + } + + public static void unloadFunction() { + Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(TFunctionLoader::unloadFunction); + } + + public static void unloadFunction(Plugin plugin) { + Optional.ofNullable(pluginFunction.remove(plugin.getName())).ifPresent(classes -> { + for (Class pluginClass : classes) { + if (pluginClass.isAnnotationPresent(TFunction.class)) { + TFunction function = (TFunction) pluginClass.getAnnotation(TFunction.class); + try { + Method method = pluginClass.getDeclaredMethod(function.disable()); + method.setAccessible(true); + method.invoke(pluginClass.newInstance()); + } catch (Exception ignored) { + } + } + } + }); + } + + @EventHandler + public void onEnable(PluginEnableEvent e) { + loadFunction(e.getPlugin()); + } + + @EventHandler + public void onDisable(PluginDisableEvent e) { + unloadFunction(e.getPlugin()); + } +} diff --git a/src/main/java/me/skymc/taboolib/common/pathfinder/PathfinderCreator.java b/src/main/java/me/skymc/taboolib/common/pathfinder/PathfinderCreator.java new file mode 100644 index 0000000..e84fddb --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/pathfinder/PathfinderCreator.java @@ -0,0 +1,11 @@ +package me.skymc.taboolib.common.pathfinder; + +/** + * @Author sky + * @Since 2018-09-21 13:06 + */ +public interface PathfinderCreator { + + Object createPathfinderGoal(SimpleAi ai); + +} diff --git a/src/main/java/me/skymc/taboolib/common/pathfinder/PathfinderExecutor.java b/src/main/java/me/skymc/taboolib/common/pathfinder/PathfinderExecutor.java new file mode 100644 index 0000000..d726120 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/pathfinder/PathfinderExecutor.java @@ -0,0 +1,58 @@ +package me.skymc.taboolib.common.pathfinder; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; + +/** + * @Author sky + * @Since 2018-09-20 20:47 + */ +public abstract class PathfinderExecutor { + + public abstract Object getEntityInsentient(LivingEntity entity); + + public abstract Object getNavigation(LivingEntity entity); + + public abstract Object getControllerJump(LivingEntity entity); + + public abstract Object getControllerMove(LivingEntity entity); + + public abstract Object getControllerLook(LivingEntity entity); + + public abstract Object getGoalSelector(LivingEntity entity); + + public abstract Object getTargetSelector(LivingEntity entity); + + public abstract Object getPathEntity(LivingEntity entity); + + public abstract void setPathEntity(LivingEntity entity, Object pathEntity); + + public abstract void setGoalAi(LivingEntity entity, SimpleAi ai, int priority); + + public abstract void setTargetAi(LivingEntity entity, SimpleAi ai, int priority); + + public abstract void clearGoalAi(LivingEntity entity); + + public abstract void clearTargetAi(LivingEntity entity); + + public abstract boolean navigationMove(LivingEntity entity, Location location); + + public abstract boolean navigationMove(LivingEntity entity, Location location, double speed); + + public abstract boolean navigationMove(LivingEntity entity, LivingEntity target); + + public abstract boolean navigationMove(LivingEntity entity, LivingEntity target, double speed); + + public abstract boolean navigationReach(LivingEntity entity); + + public abstract void controllerLookAt(LivingEntity entity, Location target); + + public abstract void controllerLookAt(LivingEntity entity, Entity target); + + public abstract void controllerJumpReady(LivingEntity entity); + + public abstract boolean controllerJumpCurrent(LivingEntity entity); + + public abstract void setFollowRange(LivingEntity entity, double value); +} diff --git a/src/main/java/me/skymc/taboolib/common/pathfinder/SimpleAi.java b/src/main/java/me/skymc/taboolib/common/pathfinder/SimpleAi.java new file mode 100644 index 0000000..e1ac15b --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/pathfinder/SimpleAi.java @@ -0,0 +1,23 @@ +package me.skymc.taboolib.common.pathfinder; + +/** + * @Author sky + * @Since 2018-09-19 19:42 + */ +public abstract class SimpleAi { + + public abstract boolean shouldExecute(); + + public boolean continueExecute() { + return shouldExecute(); + } + + public void startTask() { + } + + public void resetTask() { + } + + public void updateTask() { + } +} diff --git a/src/main/java/me/skymc/taboolib/common/pathfinder/SimpleAiSelector.java b/src/main/java/me/skymc/taboolib/common/pathfinder/SimpleAiSelector.java new file mode 100644 index 0000000..f80d04d --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/pathfinder/SimpleAiSelector.java @@ -0,0 +1,46 @@ +package me.skymc.taboolib.common.pathfinder; + +import me.skymc.taboolib.common.versioncontrol.SimpleVersionControl; +import me.skymc.taboolib.object.Instantiable; + +/** + * @Author sky + * @Since 2018-09-19 20:31 + */ +@Instantiable("SimpleAiSelector") +public class SimpleAiSelector { + + private static PathfinderCreator internalPathfinderCreator; + private static PathfinderExecutor internalPathfinderExecutor; + + public SimpleAiSelector() { + try { + internalPathfinderCreator = (PathfinderCreator) SimpleVersionControl.create() + .from("1_8_R3") + .target("me.skymc.taboolib.common.pathfinder.internal.InternalPathfinderCreator") + .translate() + .newInstance(); + internalPathfinderExecutor = (PathfinderExecutor) SimpleVersionControl.create() + .from("1_8_R3") + .target("me.skymc.taboolib.common.pathfinder.internal.InternalPathfinderExecutor") + .translate() + .newInstance(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // ********************************* + // + // Getter and Setter + // + // ********************************* + + public static PathfinderExecutor getExecutor() { + return internalPathfinderExecutor; + } + + public static PathfinderCreator getCreator() { + return internalPathfinderCreator; + } +} diff --git a/src/main/java/me/skymc/taboolib/common/pathfinder/internal/InternalPathfinderCreator.java b/src/main/java/me/skymc/taboolib/common/pathfinder/internal/InternalPathfinderCreator.java new file mode 100644 index 0000000..027ec95 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/pathfinder/internal/InternalPathfinderCreator.java @@ -0,0 +1,52 @@ +package me.skymc.taboolib.common.pathfinder.internal; + +import me.skymc.taboolib.common.pathfinder.PathfinderCreator; +import me.skymc.taboolib.common.pathfinder.SimpleAi; + +/** + * 该类仅用作生成 ASM 代码,无任何意义 + * + * @Author sky + * @Since 2018-09-19 22:31 + */ +public class InternalPathfinderCreator extends net.minecraft.server.v1_8_R3.PathfinderGoal implements PathfinderCreator { + + private SimpleAi simpleAI; + + public InternalPathfinderCreator() { + } + + public InternalPathfinderCreator(SimpleAi ai) { + this.simpleAI = ai; + } + + @Override + public Object createPathfinderGoal(SimpleAi ai) { + return new InternalPathfinderCreator(ai); + } + + @Override + public boolean a() { + return simpleAI.shouldExecute(); + } + + @Override + public boolean b() { + return simpleAI.continueExecute(); + } + + @Override + public void c() { + simpleAI.startTask(); + } + + @Override + public void d() { + simpleAI.resetTask(); + } + + @Override + public void e() { + simpleAI.updateTask(); + } +} diff --git a/src/main/java/me/skymc/taboolib/common/pathfinder/internal/InternalPathfinderExecutor.java b/src/main/java/me/skymc/taboolib/common/pathfinder/internal/InternalPathfinderExecutor.java new file mode 100644 index 0000000..8f0b5e3 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/pathfinder/internal/InternalPathfinderExecutor.java @@ -0,0 +1,187 @@ +package me.skymc.taboolib.common.pathfinder.internal; + +import me.skymc.taboolib.common.pathfinder.PathfinderExecutor; +import me.skymc.taboolib.common.pathfinder.SimpleAi; +import me.skymc.taboolib.common.pathfinder.SimpleAiSelector; +import me.skymc.taboolib.nms.NMSUtils; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; + +import java.lang.reflect.Field; +import java.util.Collection; + +/** + * 该类仅用作生成 ASM 代码,无任何意义 + * + * @Author sky + * @Since 2018-09-20 20:57 + */ +public class InternalPathfinderExecutor extends PathfinderExecutor { + + private Field pathEntity; + private Field pathfinderGoalSelectorSet; + private Field controllerJumpCurrent; + + public InternalPathfinderExecutor() { + try { + pathfinderGoalSelectorSet = NMSUtils.getNMSClass("PathfinderGoalSelector").getDeclaredField("b"); + pathfinderGoalSelectorSet.setAccessible(true); + controllerJumpCurrent = NMSUtils.getNMSClass("ControllerJump").getDeclaredField("a"); + controllerJumpCurrent.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + try { + Class pathEntityClass = NMSUtils.getNMSClass("PathEntity"); + for (Field field : NMSUtils.getNMSClass("NavigationAbstract").getDeclaredFields()) { + if (field.getType().equals(pathEntityClass)) { + field.setAccessible(true); + pathEntity = field; + return; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public Object getEntityInsentient(LivingEntity entity) { + return ((CraftEntity) entity).getHandle(); + } + + @Override + public Object getNavigation(LivingEntity entity) { + return ((EntityInsentient) getEntityInsentient(entity)).getNavigation(); + } + + @Override + public Object getControllerJump(LivingEntity entity) { + return ((EntityInsentient) getEntityInsentient(entity)).getControllerJump(); + } + + @Override + public Object getControllerMove(LivingEntity entity) { + return ((EntityInsentient) getEntityInsentient(entity)).getControllerMove(); + } + + @Override + public Object getControllerLook(LivingEntity entity) { + return ((EntityInsentient) getEntityInsentient(entity)).getControllerLook(); + } + + @Override + public Object getGoalSelector(LivingEntity entity) { + return ((EntityInsentient) getEntityInsentient(entity)).goalSelector; + } + + @Override + public Object getTargetSelector(LivingEntity entity) { + return ((EntityInsentient) getEntityInsentient(entity)).targetSelector; + } + + @Override + public Object getPathEntity(LivingEntity entity) { + try { + return pathEntity.get(getNavigation(entity)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void setPathEntity(LivingEntity entity, Object pathEntity) { + try { + this.pathEntity.set(getNavigation(entity), pathEntity); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void setGoalAi(LivingEntity entity, SimpleAi ai, int priority) { + ((EntityInsentient) getEntityInsentient(entity)).goalSelector.a(priority, (PathfinderGoal) SimpleAiSelector.getCreator().createPathfinderGoal(ai)); + } + + @Override + public void setTargetAi(LivingEntity entity, SimpleAi ai, int priority) { + ((EntityInsentient) getEntityInsentient(entity)).targetSelector.a(priority, (PathfinderGoal) SimpleAiSelector.getCreator().createPathfinderGoal(ai)); + } + + @Override + public void clearGoalAi(LivingEntity entity) { + try { + ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).goalSelector)).clear(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void clearTargetAi(LivingEntity entity) { + try { + ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).targetSelector)).clear(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public boolean navigationMove(LivingEntity entity, Location location) { + return navigationMove(entity, location, 0.6); + } + + @Override + public boolean navigationMove(LivingEntity entity, Location location, double speed) { + return ((Navigation) getNavigation(entity)).a(location.getX(), location.getY(), location.getZ(), speed); + } + + @Override + public boolean navigationMove(LivingEntity entity, LivingEntity target) { + return navigationMove(entity, target, 0.6); + } + + @Override + public boolean navigationMove(LivingEntity entity, LivingEntity target, double speed) { + return ((Navigation) getNavigation(entity)).a(((CraftEntity) target).getHandle(), speed); + } + + @Override + public boolean navigationReach(LivingEntity entity) { + Object pathEntity = getPathEntity(entity); + return pathEntity == null || ((PathEntity) pathEntity).b(); + } + + @Override + public void controllerLookAt(LivingEntity entity, Location target) { + ((ControllerLook) getControllerLook(entity)).a(target.getX(), target.getY(), target.getZ(), 10, 40); + } + + @Override + public void controllerLookAt(LivingEntity entity, Entity target) { + ((ControllerLook) getControllerLook(entity)).a(((CraftEntity) target).getHandle(), 10, 40); + } + + @Override + public void controllerJumpReady(LivingEntity entity) { + ((ControllerJump) getControllerJump(entity)).a(); + } + + @Override + public boolean controllerJumpCurrent(LivingEntity entity) { + try { + return controllerJumpCurrent.getBoolean(getControllerJump(entity)); + } catch (Exception ignored) { + return false; + } + } + + @Override + public void setFollowRange(LivingEntity entity, double value) { + ((EntityInsentient) getEntityInsentient(entity)).getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(value); + } +} diff --git a/src/main/java/me/skymc/taboolib/common/playercontainer/Container.java b/src/main/java/me/skymc/taboolib/common/playercontainer/Container.java new file mode 100644 index 0000000..2d9dcbf --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/playercontainer/Container.java @@ -0,0 +1,23 @@ +package me.skymc.taboolib.common.playercontainer; + +/** + * @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; + } +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/common/playercontainer/PlayerContainer.java b/src/main/java/me/skymc/taboolib/common/playercontainer/PlayerContainer.java new file mode 100644 index 0000000..3f35b81 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/playercontainer/PlayerContainer.java @@ -0,0 +1,18 @@ +package me.skymc.taboolib.common.playercontainer; + +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; + +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/common/playercontainer/PlayerContainerLoader.java b/src/main/java/me/skymc/taboolib/common/playercontainer/PlayerContainerLoader.java new file mode 100644 index 0000000..14d4a87 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/playercontainer/PlayerContainerLoader.java @@ -0,0 +1,91 @@ +package me.skymc.taboolib.common.playercontainer; + +import com.ilummc.tlib.logger.TLogger; +import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.TabooLibLoader; +import me.skymc.taboolib.listener.TListener; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.event.server.PluginEnableEvent; +import org.bukkit.plugin.Plugin; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @Author sky + * @Since 2018-09-14 23:45 + */ +@TListener +public class PlayerContainerLoader implements Listener { + + private static Map> pluginContainer = new ConcurrentHashMap<>(); + + PlayerContainerLoader() { + load(); + } + + public static void load() { + Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(PlayerContainerLoader::load); + } + + public static void load(Plugin plugin) { + if (!(TabooLib.isTabooLib(plugin) || TabooLib.isDependTabooLib(plugin))) { + return; + } + TabooLibLoader.getPluginClasses(plugin).ifPresent(classes -> { + for (Class pluginClass : classes) { + 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) { + } + } + } + }); + } + + public static void unload() { + Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(PlayerContainerLoader::unload); + } + + public static void unload(Plugin plugin) { + pluginContainer.remove(plugin.getName()); + } + + @EventHandler + public void onEnable(PluginEnableEvent e) { + load(e.getPlugin()); + } + + @EventHandler + public void onDisable(PluginDisableEvent e) { + unload(e.getPlugin()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onQuit(PlayerQuitEvent e) { + for (List containers : pluginContainer.values()) { + for (Container container : containers) { + 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()); + } + } + } + } + +} diff --git a/src/main/java/me/skymc/taboolib/common/util/SimpleCounter.java b/src/main/java/me/skymc/taboolib/common/util/SimpleCounter.java new file mode 100644 index 0000000..7955d59 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/util/SimpleCounter.java @@ -0,0 +1,28 @@ +package me.skymc.taboolib.common.util; + +/** + * @Author sky + * @Since 2018-09-25 15:21 + */ +public class SimpleCounter { + + private int timer; + private int limit; + + public SimpleCounter(int limit) { + this.timer = 0; + this.limit = limit; + } + + public boolean next() { + if (--timer <= 0) { + timer = limit; + return true; + } + return false; + } + + public void reset() { + timer = 0; + } +} diff --git a/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleClassVisitor.java b/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleClassVisitor.java new file mode 100644 index 0000000..3be025e --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleClassVisitor.java @@ -0,0 +1,56 @@ +package me.skymc.taboolib.common.versioncontrol; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.stream.IntStream; + +/** + * 我不信 ClassNotFoundException 的邪,自己写了一个发现还是一样。。。 + * + * @Author sky + * @Since 2018-09-19 21:17 + */ +public class SimpleClassVisitor extends ClassVisitor { + + private final SimpleVersionControl simpleVersionControl; + + public SimpleClassVisitor(SimpleVersionControl simpleVersionControl, ClassVisitor classVisitor) { + super(Opcodes.ASM5, classVisitor); + this.simpleVersionControl = simpleVersionControl; + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, name, signature, translate(superName), translate(interfaces)); + } + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + super.visitInnerClass(name, translate(outerName), translate(innerName), access); + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { + return super.visitField(access, name, translate(descriptor), translate(signature), value); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + return new SimpleMethodVisitor(simpleVersionControl, super.visitMethod(access, name, translate(descriptor), translate(signature), translate(exceptions))); + } + + private String translate(String target) { + return target == null ? null : simpleVersionControl.replace(target); + } + + private String[] translate(String[] target) { + if (target == null) { + return target; + } + IntStream.range(0, target.length).forEach(i -> target[i] = translate(target[i])); + return target; + } +} diff --git a/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleMethodVisitor.java b/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleMethodVisitor.java new file mode 100644 index 0000000..c9b6a8c --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleMethodVisitor.java @@ -0,0 +1,60 @@ +package me.skymc.taboolib.common.versioncontrol; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.stream.IntStream; + +/** + * 我不信 ClassNotFound 的邪,自己写了一个发现还是一样。。。 + * + * @Author sky + * @Since 2018-9-19 21:33 + */ +public class SimpleMethodVisitor extends MethodVisitor { + + private final SimpleVersionControl simpleVersionControl; + + public SimpleMethodVisitor(SimpleVersionControl simpleVersionControl, MethodVisitor methodVisitor) { + super(Opcodes.ASM5, methodVisitor); + this.simpleVersionControl = simpleVersionControl; + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { + super.visitMethodInsn(opcode, translate(owner), name, translate(descriptor), isInterface); + } + + @Override + public void visitLdcInsn(Object value) { + super.visitLdcInsn(value instanceof String ? translate((String) value) : value); + } + + @Override + public void visitTypeInsn(int opcode, String type) { + super.visitTypeInsn(opcode, translate(type)); + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + super.visitFieldInsn(opcode, translate(owner), name, translate(descriptor)); + } + + @Override + public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { + super.visitLocalVariable(name, translate(descriptor), translate(signature), start, end, index); + } + + private String translate(String target) { + return target == null ? null : simpleVersionControl.replace(target); + } + + private String[] translate(String[] target) { + if (target == null) { + return target; + } + IntStream.range(0, target.length).forEach(i -> target[i] = translate(target[i])); + return target; + } +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleVersionControl.java b/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleVersionControl.java new file mode 100644 index 0000000..3e2f9bd --- /dev/null +++ b/src/main/java/me/skymc/taboolib/common/versioncontrol/SimpleVersionControl.java @@ -0,0 +1,100 @@ +package me.skymc.taboolib.common.versioncontrol; + +import com.google.common.collect.Lists; +import com.ilummc.tlib.util.asm.AsmClassLoader; +import me.skymc.taboolib.Main; +import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.fileutils.FileUtils; +import org.bukkit.plugin.Plugin; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * 我不信 ClassNotFound 的邪,自己写了一个发现还是一样。。。 + * + * @Author sky + * @Since 2018-09-19 21:05 + */ +public class SimpleVersionControl { + + private String target; + private List from = Lists.newArrayList(); + private String to; + private Plugin plugin; + + SimpleVersionControl() { + } + + public static SimpleVersionControl create() { + return new SimpleVersionControl().to(TabooLib.getVersion()).plugin(Main.getInst()); + } + + public static SimpleVersionControl create(String toVersion) { + return new SimpleVersionControl().to(toVersion).plugin(Main.getInst()); + } + + public SimpleVersionControl target(Class target) { + this.target = target.getName(); + return this; + } + + public SimpleVersionControl target(String target) { + this.target = target; + return this; + } + + public SimpleVersionControl from(String from) { + this.from.add(from.startsWith("v") ? from : "v" + from); + return this; + } + + public SimpleVersionControl to(String to) { + this.to = to.startsWith("v") ? to : "v" + to; + return this; + } + + public SimpleVersionControl plugin(Plugin plugin) { + this.plugin = plugin; + return this; + } + + public Class translate() throws IOException { + ClassReader classReader = new ClassReader(FileUtils.getResource(plugin, target.replace(".", "/") + ".class")); + ClassWriter classWriter = new ClassWriter(0); + ClassVisitor classVisitor = new SimpleClassVisitor(this, classWriter); + classReader.accept(classVisitor, 0); + classWriter.visitEnd(); + classVisitor.visitEnd(); + return AsmClassLoader.createNewClass(target, classWriter.toByteArray()); + } + + // ********************************* + // + // Getter and Setter + // + // ********************************* + + public String getTarget() { + return target; + } + + public List getFrom() { + return from; + } + + public String getTo() { + return to; + } + + public String replace(String origin) { + for (String from : from) { + origin = origin.replace("/" + from + "/", "/" + to + "/"); + } + return origin; + } +} diff --git a/src/main/java/me/skymc/taboolib/damage/DamageUtils.java b/src/main/java/me/skymc/taboolib/damage/DamageUtils.java index a614445..1ffdd99 100644 --- a/src/main/java/me/skymc/taboolib/damage/DamageUtils.java +++ b/src/main/java/me/skymc/taboolib/damage/DamageUtils.java @@ -1,58 +1,44 @@ package me.skymc.taboolib.damage; -import me.skymc.taboolib.TabooLib; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.entity.EntityDamageByEntityEvent; -import java.lang.reflect.InvocationTargetException; - +/** + * @author sky + */ public class DamageUtils { + public static Player getAttackerInDamageEvent(EntityDamageByEntityEvent e) { + if (e.getDamager() instanceof Player) { + return (Player) e.getDamager(); + } else if (e.getDamager() instanceof Projectile && ((Projectile) e.getDamager()).getShooter() instanceof Player) { + return (Player) ((Projectile) e.getDamager()).getShooter(); + } else { + return null; + } + } + + // ********************************* + // + // Deprecated + // + // ********************************* + + @Deprecated public static void damage(Player player, LivingEntity victim, double damage) { dmg(player, victim, damage); } + @Deprecated public static void damage(Player player, Entity victim, double damage) { - if (victim instanceof LivingEntity) { - dmg(player, (LivingEntity) victim, damage); - } + dmg(player, (LivingEntity) victim, damage); } - public static void dmg(LivingEntity paramLivingEntity1, LivingEntity paramLivingEntity2, double paramDouble) { - if ((paramLivingEntity2.hasMetadata("NPC")) || (paramLivingEntity1.hasMetadata("NPC"))) { - return; - } - - Object localObject1; - try { - localObject1 = paramLivingEntity1.getClass().getDeclaredMethod("getHandle").invoke(paramLivingEntity1); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException localIllegalAccessException1) { - return; - } - - Object localObject2; - try { - localObject2 = paramLivingEntity2.getClass().getDeclaredMethod("getHandle").invoke(paramLivingEntity2); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException localIllegalAccessException2) { - return; - } - - try { - Class DamageSource = nmsClass("DamageSource"); - Object localObject3 = DamageSource.getDeclaredMethod("playerAttack", nmsClass("EntityHuman")).invoke(DamageSource, localObject1); - - localObject2.getClass().getDeclaredMethod("damageEntity", new Class[]{DamageSource, Float.TYPE}).invoke(localObject2, localObject3, (float) paramDouble); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException ignored) { - } - } - - private static Class nmsClass(String paramString) { - String str = "net.minecraft.server." + TabooLib.getVersion() + "." + paramString; - try { - return Class.forName(str); - } catch (ClassNotFoundException e) { - return null; - } + @Deprecated + public static void dmg(LivingEntity attacker, LivingEntity victim, double damage) { + attacker.damage(damage, victim); } } diff --git a/src/main/java/me/skymc/taboolib/damage/GetDamager.java b/src/main/java/me/skymc/taboolib/damage/GetDamager.java index aee2773..cb171d3 100644 --- a/src/main/java/me/skymc/taboolib/damage/GetDamager.java +++ b/src/main/java/me/skymc/taboolib/damage/GetDamager.java @@ -4,19 +4,11 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; import org.bukkit.event.entity.EntityDamageByEntityEvent; +@Deprecated public class GetDamager { public static Player get(EntityDamageByEntityEvent e) { - Player p = null; - if (e.getDamager() instanceof Projectile) { - Projectile arrow = (Projectile) e.getDamager(); - if (arrow.getShooter() instanceof Player) { - p = (Player) arrow.getShooter(); - } - } else if (e.getDamager() instanceof Player) { - p = (Player) e.getDamager(); - } - return p; + return DamageUtils.getAttackerInDamageEvent(e); } } diff --git a/src/main/java/me/skymc/taboolib/damage/GetKiller.java b/src/main/java/me/skymc/taboolib/damage/GetKiller.java index 1206c85..0fcc95b 100644 --- a/src/main/java/me/skymc/taboolib/damage/GetKiller.java +++ b/src/main/java/me/skymc/taboolib/damage/GetKiller.java @@ -1,22 +1,13 @@ package me.skymc.taboolib.damage; import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; import org.bukkit.event.entity.EntityDeathEvent; +@Deprecated public class GetKiller { public static Player get(EntityDeathEvent e) { - Player p = null; - if (e.getEntity().getKiller() instanceof Projectile) { - Projectile arrow = (Projectile) e.getEntity().getKiller(); - if (arrow.getShooter() instanceof Player) { - p = (Player) arrow.getShooter(); - } - } else if (e.getEntity().getKiller() != null) { - p = e.getEntity().getKiller(); - } - return p; + return e.getEntity().getKiller(); } } diff --git a/src/main/java/me/skymc/taboolib/entity/VectorUtils.java b/src/main/java/me/skymc/taboolib/entity/VectorUtils.java index 2428757..e174206 100644 --- a/src/main/java/me/skymc/taboolib/entity/VectorUtils.java +++ b/src/main/java/me/skymc/taboolib/entity/VectorUtils.java @@ -18,7 +18,7 @@ public class VectorUtils { /** * 物品丢弃 - * + *

* 常用参数: * itemDrop(player, itemStack, 0.2, 0.5) * @@ -57,7 +57,7 @@ public class VectorUtils { /** * 生物抛射 - * + *

* 常用参数: * entityPush(entity, location, 15) * @@ -69,17 +69,17 @@ public class VectorUtils { Location from = entity.getLocation(); Vector test = to.clone().subtract(from).toVector(); - Double elevation = test.getY(); + double elevation = test.getY(); Double launchAngle = calculateLaunchAngle(from, to, velocity, elevation, 20.0D); - Double distance = Math.sqrt(Math.pow(test.getX(), 2.0D) + Math.pow(test.getZ(), 2.0D)); + double distance = Math.sqrt(Math.pow(test.getX(), 2.0D) + Math.pow(test.getZ(), 2.0D)); if (distance == 0.0D) { return; } if (launchAngle == null) { launchAngle = Math.atan((40.0D * elevation + Math.pow(velocity, 2.0D)) / (40.0D * elevation + 2.0D * Math.pow(velocity, 2.0D))); } - Double hangTime = calculateHangTime(launchAngle, velocity, elevation, 20.0D); + double hangTime = calculateHangTime(launchAngle, velocity, elevation, 20.0D); test.setY(Math.tan(launchAngle) * distance); test = normalizeVector(test); @@ -113,7 +113,7 @@ public class VectorUtils { private static Double calculateLaunchAngle(Location from, Location to, double v, double elevation, double g) { Vector vector = from.clone().subtract(to).toVector(); - Double distance = Math.sqrt(Math.pow(vector.getX(), 2.0D) + Math.pow(vector.getZ(), 2.0D)); + double distance = Math.sqrt(Math.pow(vector.getX(), 2.0D) + Math.pow(vector.getZ(), 2.0D)); double v2 = Math.pow(v, 2.0D); double v4 = Math.pow(v, 4.0D); double check = g * (g * Math.pow(distance, 2.0D) + 2.0D * elevation * v2); diff --git a/src/main/java/me/skymc/taboolib/events/DefaultEvent2.java b/src/main/java/me/skymc/taboolib/events/DefaultEvent2.java deleted file mode 100644 index def7099..0000000 --- a/src/main/java/me/skymc/taboolib/events/DefaultEvent2.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.skymc.taboolib.events; - -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; - -public class DefaultEvent2 extends PlayerEvent { - - private static final HandlerList handlers; - - static { - handlers = new HandlerList(); - } - - private DefaultEvent2(final Player who) { - super(who); - } - - public static HandlerList getHandlerList() { - return DefaultEvent2.handlers; - } - - @Override - public HandlerList getHandlers() { - return DefaultEvent2.handlers; - } - - public static class Pre extends DefaultEvent2 implements Cancellable { - private boolean cancelled; - - public Pre(Player who) { - super(who); - this.cancelled = false; - } - - @Override - public boolean isCancelled() { - return this.cancelled; - } - - @Override - public void setCancelled(final boolean cancelled) { - this.cancelled = cancelled; - } - } - - public static class Post extends DefaultEvent2 { - public Post(Player who) { - super(who); - } - } -} diff --git a/src/main/java/me/skymc/taboolib/fileutils/FileUtils.java b/src/main/java/me/skymc/taboolib/fileutils/FileUtils.java index 57b5046..861223c 100644 --- a/src/main/java/me/skymc/taboolib/fileutils/FileUtils.java +++ b/src/main/java/me/skymc/taboolib/fileutils/FileUtils.java @@ -1,13 +1,15 @@ package me.skymc.taboolib.fileutils; import ch.njol.util.Closeable; +import com.ilummc.eagletdl.EagletTask; +import com.ilummc.eagletdl.ProgressEvent; +import com.ilummc.tlib.resources.TLocale; import com.ilummc.tlib.util.IO; import me.skymc.taboolib.Main; import org.apache.commons.io.IOUtils; import org.bukkit.plugin.Plugin; import java.io.*; -import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; @@ -133,13 +135,9 @@ public class FileUtils { public static InputStream getResource(Plugin plugin, String filename) { try { URL url = plugin.getClass().getClassLoader().getResource(filename); - if (url == null) { - return null; - } else { - URLConnection connection = url.openConnection(); - connection.setUseCaches(false); - return connection.getInputStream(); - } + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + return connection.getInputStream(); } catch (IOException ignored) { return null; } @@ -409,35 +407,38 @@ public class FileUtils { /** * 下载文件 * - * @param downloadURL 下载地址 - * @param file 保存位置 + * @param url 下载地址 + * @param file 下载位置 + * @param async 是否异步 */ - public static void download(String downloadURL, File file) { - HttpURLConnection conn = null; - InputStream inputStream = null; - FileOutputStream fos = null; - try { - URL url = new URL(downloadURL); - conn = (HttpURLConnection) url.openConnection(); - conn.setConnectTimeout(5 * 1000); - conn.setRequestProperty("User-Agent", "Mozilla/31.0 (compatible; MSIE 10.0; Windows NT; DigExt)"); - - inputStream = conn.getInputStream(); - byte[] data = read(inputStream); - - fos = new FileOutputStream(createNewFile(file)); - fos.write(data); - } catch (Exception ignored) { - } finally { - IOUtils.close(conn); - IOUtils.closeQuietly(fos); - IOUtils.closeQuietly(inputStream); + public static void download(String url, File file, boolean async) { + EagletTask eagletTask = new EagletTask() + .url(url) + .file(file) + .setThreads(8) + .setOnError(event -> { + }) + .setOnConnected(event -> TLocale.Logger.info("UTIL.DOWNLOAD-CONNECTED", file.getName(), ProgressEvent.format(event.getContentLength()))) + .setOnProgress(event -> TLocale.Logger.info("UTIL.DOWNLOAD-PROGRESS", event.getSpeedFormatted(), event.getPercentageFormatted())) + .setOnComplete(event -> { + if (event.isSuccess()) { + TLocale.Logger.info("UTIL.DOWNLOAD-SUCCESS", file.getName()); + } else { + TLocale.Logger.error("UTIL.DOWNLOAD-FAILED", file.getName()); + } + }).start(); + if (!async) { + eagletTask.waitUntil(); } } + public static void download(String url, File file) { + download(url, file, false); + } + @Deprecated - public static void download(String downloadURL, String filename, File saveDir) { - download(downloadURL, new File(saveDir, filename)); + public static void download(String url, String filename, File saveDir) { + download(url, new File(saveDir, filename)); } @Deprecated diff --git a/src/main/java/me/skymc/taboolib/inventory/ItemUtils.java b/src/main/java/me/skymc/taboolib/inventory/ItemUtils.java index 2e38d61..5274c5a 100644 --- a/src/main/java/me/skymc/taboolib/inventory/ItemUtils.java +++ b/src/main/java/me/skymc/taboolib/inventory/ItemUtils.java @@ -4,13 +4,13 @@ import com.ilummc.tlib.resources.TLocale; import me.clip.placeholderapi.PlaceholderAPI; import me.skymc.taboolib.Main; import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.common.configuration.TConfiguration; import me.skymc.taboolib.fileutils.ConfigUtils; import me.skymc.taboolib.itemnbtapi.NBTItem; import me.skymc.taboolib.itemnbtapi.NBTList; import me.skymc.taboolib.itemnbtapi.NBTListCompound; import me.skymc.taboolib.itemnbtapi.NBTType; import me.skymc.taboolib.other.NumberUtils; -import me.skymc.taboolib.string.Language; import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -39,74 +39,59 @@ import java.util.stream.IntStream; */ public class ItemUtils { - private static FileConfiguration itemdir = null; - - private static FileConfiguration itemCache = null; - private static File finalItemsFolder; - - private static LinkedHashMap itemlib = new LinkedHashMap<>(); - + private static FileConfiguration itemDir; + private static FileConfiguration itemCache; + private static TConfiguration itemName; + private static LinkedHashMap itemLib = new LinkedHashMap<>(); private static LinkedHashMap itemCaches = new LinkedHashMap<>(); - private static LinkedHashMap itemCachesFinal = new LinkedHashMap<>(); - public static FileConfiguration getItemdir() { - return itemdir; - } - - public static FileConfiguration getItemCache() { - return itemCache; - } - - public static File getFinalItemsFolder() { - return finalItemsFolder; - } - - public static LinkedHashMap getItemlib() { - return itemlib; - } - - public static LinkedHashMap getItemCaches() { - return itemCaches; - } - - public static LinkedHashMap getItemCachesFinal() { - return itemCachesFinal; - } - - /** - * 获取物品缓存 - * 检测顺序: - * 1. 固定物品库 - * 2. 动态物品库 - * - * @param name 物品名称 - * @return - */ - public static ItemStack getCacheItem(String name) { - // 检测固定物品库是否存在该物品 - if (itemCachesFinal.containsKey(name)) { - return itemCachesFinal.get(name); - } - // 返回动态物品库 - return itemCaches.get(name); - } - - public static boolean isExists(String name) { - return itemCachesFinal.containsKey(name) || itemCaches.containsKey(name); - } - - public static void LoadLib() { + public static void init() { try { + reloadItemDir(); reloadItemName(); reloadItemCache(); - itemdir = YamlConfiguration.loadConfiguration(new File(Main.getInst().getConfig().getString("DATAURL.ITEMDIR"))); } catch (Exception e) { TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-ITEMS", e.toString()); } } + public static void reloadItemDir() { + File file = new File(Main.getInst().getConfig().getString("DATAURL.ITEMDIR")); + if (file.exists()) { + itemDir = YamlConfiguration.loadConfiguration(file); + } + } + + public static void reloadItemName() { + itemName = TConfiguration.createInResource(Main.getInst(), "Language/ITEM_NAME.yml"); + itemName.listener(() -> { + itemName.getConfigurationSection("").getKeys(false).forEach(a -> itemLib.put(a, itemName.getString(a))); + TLocale.Logger.info("ITEM-UTILS.SUCCESS-LOAD-NAMES", String.valueOf(itemLib.size())); + }).runListener(); + } + + public static void reloadItemCache() { + itemCaches.clear(); + itemCachesFinal.clear(); + loadItemsFile(getItemCacheFile(), false); + finalItemsFolder = new File(Main.getInst().getDataFolder(), "FinalItems"); + if (!finalItemsFolder.exists()) { + finalItemsFolder.mkdir(); + } + Arrays.stream(finalItemsFolder.listFiles()).forEach(file -> loadItemsFile(file, true)); + TLocale.Logger.info("ITEM-UTILS.SUCCESS-LOAD-CACHES", String.valueOf(itemCaches.size() + itemCachesFinal.size())); + } + + public static File getItemCacheFile() { + File itemCacheFile = new File(Main.getInst().getDataFolder(), "items.yml"); + if (!itemCacheFile.exists()) { + Main.getInst().saveResource("items.yml", true); + } + return itemCacheFile; + } + public static void loadItemsFile(File file, boolean finalFile) { FileConfiguration conf = ConfigUtils.load(Main.getInst(), file); for (String name : conf.getConfigurationSection("").getKeys(false)) { @@ -120,33 +105,22 @@ public class ItemUtils { } } - public static void reloadItemCache() { - itemCaches.clear(); - itemCachesFinal.clear(); - loadItemsFile(getItemCacheFile(), false); - // 创建固定物品库 - finalItemsFolder = new File(Main.getInst().getDataFolder(), "FinalItems"); - if (!finalItemsFolder.exists()) { - finalItemsFolder.mkdir(); - } - // 检查固定物品库中的物品 - Arrays.stream(finalItemsFolder.listFiles()).forEach(file -> loadItemsFile(file, true)); - TLocale.Logger.info("ITEM-UTILS.SUCCESS-LOAD-CACHES", String.valueOf(itemCaches.size() + itemCachesFinal.size())); + // ********************************* + // + // API + // + // ********************************* + + public static boolean isExists(String name) { + return itemCachesFinal.containsKey(name) || itemCaches.containsKey(name); } - public static void reloadItemName() { - FileConfiguration conf = new Language("ITEM_NAME", Main.getInst(), true).getConfiguration(); - itemlib.clear(); - conf.getConfigurationSection("").getKeys(false).forEach(a -> itemlib.put(a, conf.getString(a))); - TLocale.Logger.info("ITEM-UTILS.SUCCESS-LOAD-NAMES", String.valueOf(itemlib.size())); + public static ItemStack getCacheItem(String name) { + return itemCachesFinal.containsKey(name) ? itemCachesFinal.get(name) : itemCaches.get(name); } - public static File getItemCacheFile() { - File itemCacheFile = new File(Main.getInst().getDataFolder(), "items.yml"); - if (!itemCacheFile.exists()) { - Main.getInst().saveResource("items.yml", true); - } - return itemCacheFile; + public static ItemStack getItemFromDir(String name) { + return itemDir != null ? itemDir.getItemStack("item." + name) : null; } public static String getCustomName(ItemStack item) { @@ -154,19 +128,7 @@ public class ItemUtils { return TLocale.asString("ITEM-UTILS.EMPTY-ITEM"); } int data = item.getType().getMaxDurability() == 0 ? item.getDurability() : 0; - return item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : itemlib.get(item.getType() + ":" + data) == null ? item.getType().toString() : itemlib.get(item.getType() + ":" + data); - } - - public static ItemStack getItemFromDir(String name) { - if (itemdir != null) { - return itemdir.getItemStack("item." + name); - } - return null; - } - - @SuppressWarnings("deprecation") - public static ItemStack item(int n, int a, int d) { - return new ItemStack(n, a, (short) d); + return item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : itemLib.get(item.getType() + ":" + data) == null ? item.getType().toString() : itemLib.get(item.getType() + ":" + data); } public static ItemStack setName(ItemStack i, String n) { @@ -176,7 +138,7 @@ public class ItemUtils { return i; } - public static ItemStack Enchant(ItemStack i, Enchantment e, int l) { + public static ItemStack enchant(ItemStack i, Enchantment e, int l) { ItemMeta meta = i.getItemMeta(); meta.addEnchant(e, l, false); i.setItemMeta(meta); @@ -203,10 +165,7 @@ public class ItemUtils { } public static String asString(String args, Player placeholderPlayer) { - if (placeholderPlayer == null) { - return args.replace("&", "§"); - } - return PlaceholderAPI.setPlaceholders(placeholderPlayer, args.replace("&", "§")); + return placeholderPlayer == null ? args.replace("&", "§") : PlaceholderAPI.setPlaceholders(placeholderPlayer, args.replace("&", "§")); } public static List asString(List args, Player placeholderPlayer) { @@ -281,58 +240,30 @@ public class ItemUtils { } } - /** - * 包含介绍 - * - * @param i 物品 - * @param a 关键字 - */ + public static int getLore(ItemStack i, String a) { + return isLored(i) ? IntStream.range(0, i.getItemMeta().getLore().size()).filter(j -> i.getItemMeta().getLore().get(j).contains(a)).findFirst().orElse(0) : 0; + } + public static boolean hasLore(ItemStack i, String a) { return isLored(i) && i.getItemMeta().getLore().toString().contains(a); } - /** - * 如果已描述 - * - * @param i - * @return - */ public static boolean isLored(ItemStack i) { return i != null && i.getItemMeta() != null && i.getItemMeta().getLore() != null; } - /** - * 如果已命名 - * - * @param i - * @return - */ public static boolean isNamed(ItemStack i) { return i != null && i.getItemMeta() != null && i.getItemMeta().getDisplayName() != null; } - /** - * 添加描述 - * - * @param is 物品 - * @param lore 描述 - */ - public static ItemStack addLore(ItemStack is, String lore) { + public static ItemStack addLore(ItemStack is, String line) { ItemMeta meta = is.getItemMeta(); - - List _lore = meta.hasLore() ? meta.getLore() : Collections.emptyList(); - _lore.add(lore.replaceAll("&", "§")); - + List lore = meta.hasLore() ? meta.getLore() : Collections.emptyList(); + lore.add(TLocale.Translate.setColored(line)); is.setItemMeta(meta); return is; } - /** - * 移除描述 - * - * @param is 物品 - * @param line 行数 - */ public static ItemStack delLore(ItemStack is, int line) { ItemMeta meta = is.getItemMeta(); if (meta.hasLore()) { @@ -346,40 +277,7 @@ public class ItemUtils { return is; } - /** - * 获取介绍所在行数 - * - * @param i 物品 - * @param a 关键字 - */ - public static int getLore(ItemStack i, String a) { - return isLored(i) ? IntStream.range(0, i.getItemMeta().getLore().size()).filter(j -> i.getItemMeta().getLore().get(j).contains(a)).findFirst().orElse(0) : 0; - } - - /** - * 添加耐久 - * - * @param i 物品 - * @param d 耐久 - */ - public static ItemStack addDurability(ItemStack i, int d) { - i.setDurability((short) (i.getDurability() + d)); - int min = i.getDurability(); - int max = i.getType().getMaxDurability(); - if (min >= max) { - i.setType(Material.AIR); - } - return i; - } - - /** - * 替换描述 - * - * @param i 物品 - * @param l1 关键字1 - * @param l2 关键字2 - */ - public static ItemStack repalceLore(ItemStack i, String l1, String l2) { + public static ItemStack replaceLore(ItemStack i, String l1, String l2) { if (!isLored(i)) { return i; } else { @@ -392,6 +290,16 @@ public class ItemUtils { return i; } + public static ItemStack addDurability(ItemStack i, int d) { + i.setDurability((short) (i.getDurability() + d)); + int min = i.getDurability(); + int max = i.getType().getMaxDurability(); + if (min >= max) { + i.setType(Material.AIR); + } + return i; + } + public static ItemStack loadItem(FileConfiguration f, String s) { return loadItem(f, s, null); } @@ -552,6 +460,62 @@ public class ItemUtils { return nbt; } + // ********************************* + // + // Getter and Setter + // + // ********************************* + + public static FileConfiguration getItemDir() { + return itemDir; + } + + public static LinkedHashMap getItemLib() { + return itemLib; + } + + public static FileConfiguration getItemCache() { + return itemCache; + } + + public static File getFinalItemsFolder() { + return finalItemsFolder; + } + + public static LinkedHashMap getItemCaches() { + return itemCaches; + } + + public static LinkedHashMap getItemCachesFinal() { + return itemCachesFinal; + } + + // ********************************* + // + // Deprecated + // + // ********************************* + + @Deprecated + public static FileConfiguration getItemdir() { + return itemDir; + } + + @Deprecated + public static LinkedHashMap getItemlib() { + return itemLib; + } + + @Deprecated + public static ItemStack item(int n, int a, int d) { + return new ItemStack(n, a, (short) d); + } + + @Deprecated + public static ItemStack repalceLore(ItemStack i, String l1, String l2) { + return replaceLore(i, l1, l2); + } + @Deprecated public static void putO(ItemStack item, Inventory inv, int i) { inv.setItem(i, item); diff --git a/src/main/java/me/skymc/taboolib/inventory/builder/ItemBuilder.java b/src/main/java/me/skymc/taboolib/inventory/builder/ItemBuilder.java index e727c1c..6e3a7d5 100644 --- a/src/main/java/me/skymc/taboolib/inventory/builder/ItemBuilder.java +++ b/src/main/java/me/skymc/taboolib/inventory/builder/ItemBuilder.java @@ -3,8 +3,10 @@ package me.skymc.taboolib.inventory.builder; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.TabooLib; import me.skymc.taboolib.string.ArrayUtils; +import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Material; +import org.bukkit.OfflinePlayer; import org.bukkit.block.banner.Pattern; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; @@ -20,7 +22,7 @@ import java.util.List; /** * @Author sky * @Since 2018-08-22 11:37 - * @BuilderVersion 1.0 + * @BuilderVersion 1.1 */ public class ItemBuilder { @@ -40,6 +42,11 @@ public class ItemBuilder { itemMeta = itemStack.getItemMeta(); } + public ItemBuilder(OfflinePlayer player) { + this(Material.SKULL_ITEM, 1, 3); + this.skullOwner(player.getName()); + } + public ItemBuilder material(int id) { itemStack.setType(Material.getMaterial(id)); return this; @@ -147,6 +154,13 @@ public class ItemBuilder { return this; } + public ItemBuilder skullOwner(String name) { + if (itemMeta instanceof SkullMeta) { + ((SkullMeta) itemMeta).setOwner(name); + } + return this; + } + public ItemBuilder unbreakable(boolean value) { if (TabooLib.getVersionNumber() >= 12000) { itemMeta.setUnbreakable(value); @@ -173,4 +187,14 @@ public class ItemBuilder { } return buildItem; } + + /** + * 从文本中获取物品(name:名字;lore:描述||描述;material:材质) + * + * @param str + * @return + */ + public static ItemStack fromString(String str) { + return null; + } } diff --git a/src/main/java/me/skymc/taboolib/itagapi/TagDataHandler.java b/src/main/java/me/skymc/taboolib/itagapi/TagDataHandler.java index 4770dbf..aea9ec2 100644 --- a/src/main/java/me/skymc/taboolib/itagapi/TagDataHandler.java +++ b/src/main/java/me/skymc/taboolib/itagapi/TagDataHandler.java @@ -2,6 +2,7 @@ package me.skymc.taboolib.itagapi; import com.google.common.base.Preconditions; import me.skymc.taboolib.Main; +import me.skymc.taboolib.TabooLib; import me.skymc.taboolib.packet.PacketUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -132,7 +133,10 @@ public class TagDataHandler implements Listener { entryTeam.addEntry(playerData.getNameDisplay()); entryTeam.setPrefix(playerData.getPrefix()); entryTeam.setSuffix(playerData.getSuffix()); - TagUtils.cleanEmptyTeamInScoreboard(scoreboard); + // 傻逼 BedWarsRel 我草你妈的 + if (TabooLib.instance().getConfig().getBoolean("TABLIST-AUTO-CLEAN-TEAM", true)) { + TagUtils.cleanEmptyTeamInScoreboard(scoreboard); + } } private void cancelPlayerVariable(Player player, TagPlayerData playerData) { @@ -142,7 +146,10 @@ public class TagDataHandler implements Listener { for (Player online : Bukkit.getOnlinePlayers()) { Scoreboard scoreboard = TagUtils.getScoreboardComputeIfAbsent(player); TagUtils.cleanEntryInScoreboard(scoreboard, playerData.getNameDisplay()); - TagUtils.cleanEmptyTeamInScoreboard(scoreboard); + // 傻逼 BedWarsRel 我草你妈的 + if (TabooLib.instance().getConfig().getBoolean("TABLIST-AUTO-CLEAN-TEAM", true)) { + TagUtils.cleanEmptyTeamInScoreboard(scoreboard); + } } } @@ -157,7 +164,7 @@ public class TagDataHandler implements Listener { downloadPlayerVariable(e.getPlayer()); } - @EventHandler (priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR) public void onQuit(PlayerQuitEvent e) { cancelPlayerVariable(e.getPlayer(), unregisterPlayerData(e.getPlayer())); } diff --git a/src/main/java/me/skymc/taboolib/json/tellraw/TellrawJson.java b/src/main/java/me/skymc/taboolib/json/tellraw/TellrawJson.java index 0e88dd6..ba2e288 100644 --- a/src/main/java/me/skymc/taboolib/json/tellraw/TellrawJson.java +++ b/src/main/java/me/skymc/taboolib/json/tellraw/TellrawJson.java @@ -4,33 +4,30 @@ import com.ilummc.tlib.bungee.api.chat.*; import com.ilummc.tlib.bungee.chat.ComponentSerializer; import com.ilummc.tlib.logger.TLogger; import com.ilummc.tlib.resources.TLocale; -import me.skymc.taboolib.inventory.ItemUtils; import me.skymc.taboolib.methods.ReflectionUtils; import me.skymc.taboolib.nms.NMSUtils; -import me.skymc.taboolib.other.NumberUtils; import me.skymc.taboolib.string.ArrayUtils; -import me.skymc.taboolib.string.VariableFormatter; import org.bukkit.command.CommandSender; import org.bukkit.inventory.ItemStack; -import java.lang.reflect.Array; import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; -import java.util.Map; +import java.util.stream.Collectors; /** * @Author sky * @Since 2018-05-26 14:42json + * @BuilderLevel 1.2 */ public class TellrawJson { - private BaseComponent[] components = TextComponent.fromLegacyText(""); - private final Class craftItemStackClazz = NMSUtils.getOBCClass("inventory.CraftItemStack"); - private final Class nmsItemStackClazz = NMSUtils.getNMSClass("ItemStack"); - private final Class nbtTagCompoundClazz = NMSUtils.getNMSClass("NBTTagCompound"); - private final String INVALID_ITEM = "{id:stone,tag:{display:{Name:§c* Invalid ItemStack *}}}"; + private List components = new ArrayList<>(); + private List componentsLatest = new ArrayList<>(); + private static final Class craftItemStackClazz = NMSUtils.getOBCClass("inventory.CraftItemStack"); + private static final Class nmsItemStackClazz = NMSUtils.getNMSClass("ItemStack"); + private static final Class nbtTagCompoundClazz = NMSUtils.getNMSClass("NBTTagCompound"); + private static final String INVALID_ITEM = "{id:stone,tag:{display:{Name:§c* Invalid ItemStack *}}}"; TellrawJson() { } @@ -39,12 +36,16 @@ public class TellrawJson { return new TellrawJson(); } + public void send(CommandSender sender) { + TLocale.Tellraw.send(sender, toRawMessage()); + } + public String toRawMessage() { - return ComponentSerializer.toString(components); + return ComponentSerializer.toString(getComponentsAll()); } public String toLegacyText() { - return TextComponent.toLegacyText(components); + return TextComponent.toLegacyText(getComponentsAll()); } public TellrawJson newLine() { @@ -52,50 +53,51 @@ public class TellrawJson { } public TellrawJson append(String text) { - Arrays.stream(TextComponent.fromLegacyText(text)).forEach(component -> this.components = ArrayUtils.arrayAppend(this.components, component)); + appendComponents(); + componentsLatest.addAll(ArrayUtils.asList(TextComponent.fromLegacyText(text))); return this; } public TellrawJson append(TellrawJson json) { - BaseComponent[] newArray = new BaseComponent[components.length + json.components.length]; - System.arraycopy(components, 0, newArray, 0, components.length); - System.arraycopy(json.components, 0, newArray, components.length, json.components.length); - components = newArray; + appendComponents(); + componentsLatest.addAll(ArrayUtils.asList(json.getComponentsAll())); return this; } public TellrawJson hoverText(String text) { - getLatestComponent().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(text).create())); + getLatestComponent().forEach(component -> component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(text).create()))); return this; } public TellrawJson hoverItem(ItemStack itemStack) { - getLatestComponent().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new ComponentBuilder(getItemComponent(itemStack)).create())); + getLatestComponent().forEach(component -> component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new ComponentBuilder(getItemComponent(itemStack)).create()))); return this; } public TellrawJson clickCommand(String command) { - getLatestComponent().setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command)); + getLatestComponent().forEach(component -> component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command))); return this; } public TellrawJson clickSuggest(String command) { - getLatestComponent().setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command)); + getLatestComponent().forEach(component -> component.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command))); return this; } public TellrawJson clickOpenURL(String url) { - getLatestComponent().setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)); + getLatestComponent().forEach(component -> component.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))); return this; } public TellrawJson clickChangePage(int page) { - getLatestComponent().setClickEvent(new ClickEvent(ClickEvent.Action.CHANGE_PAGE, String.valueOf(page))); + getLatestComponent().forEach(component -> component.setClickEvent(new ClickEvent(ClickEvent.Action.CHANGE_PAGE, String.valueOf(page)))); return this; } - public void send(CommandSender sender) { - TLocale.Tellraw.send(sender, toRawMessage()); + public BaseComponent[] getComponentsAll() { + List components = this.components.stream().filter(component -> !(component instanceof TextComponent) || !((TextComponent) component).getText().isEmpty()).collect(Collectors.toList()); + this.componentsLatest.stream().filter(component -> !(component instanceof TextComponent) || !((TextComponent) component).getText().isEmpty()).forEach(components::add); + return components.toArray(new BaseComponent[0]); } public String getItemComponent(ItemStack itemStack) { @@ -106,7 +108,7 @@ public class TellrawJson { Object nmsItemStackObj = asNMSCopyMethod.invoke(null, itemStack); return saveNmsItemStackMethod.invoke(nmsItemStackObj, nmsNbtTagCompoundObj).toString(); } catch (Throwable t) { - TLogger.getGlobalLogger().error("failed to serialize itemstack to nms item: " + t.toString()); + TLogger.getGlobalLogger().error("failed to serialize bukkit item to nms item: " + t.toString()); return INVALID_ITEM; } } @@ -117,12 +119,17 @@ public class TellrawJson { // // ********************************* - private BaseComponent getLatestComponent() { - return components[components.length - 1]; + private List getLatestComponent() { + return componentsLatest; } - private void setLatestComponent(BaseComponent component) { - components[components.length - 1] = component; + private void setLatestComponent(BaseComponent... component) { + componentsLatest.addAll(ArrayUtils.asList(component)); + } + + private void appendComponents() { + components.addAll(componentsLatest); + componentsLatest.clear(); } // ********************************* @@ -131,12 +138,11 @@ public class TellrawJson { // // ********************************* - public BaseComponent[] getComponents() { - return components; - } - public void setComponents(BaseComponent[] components) { - this.components = components; + this.components = ArrayUtils.asList(components); } + public BaseComponent[] getComponents() { + return components.toArray(new BaseComponent[0]); + } } diff --git a/src/main/java/me/skymc/taboolib/listener/ListenerPlayerCommand.java b/src/main/java/me/skymc/taboolib/listener/ListenerPlayerCommand.java index e6da994..a417dc4 100644 --- a/src/main/java/me/skymc/taboolib/listener/ListenerPlayerCommand.java +++ b/src/main/java/me/skymc/taboolib/listener/ListenerPlayerCommand.java @@ -1,9 +1,12 @@ package me.skymc.taboolib.listener; +import com.ilummc.tlib.logger.TLogger; import me.skymc.taboolib.Main; import me.skymc.taboolib.TabooLib; import me.skymc.taboolib.database.PlayerDataManager; +import me.skymc.taboolib.inventory.ItemUtils; import me.skymc.taboolib.itemnbtapi.NBTItem; +import me.skymc.taboolib.json.tellraw.TellrawJson; import me.skymc.taboolib.message.MsgUtils; import me.skymc.taboolib.permission.PermissionUtils; import me.skymc.taboolib.playerdata.DataUtils; @@ -13,31 +16,51 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.server.ServerCommandEvent; +/** + * @author sky + */ @TListener public class ListenerPlayerCommand implements Listener { @EventHandler public void cmd(ServerCommandEvent e) { - if ("savefile".equals(e.getCommand())) { + if (e.getCommand().equalsIgnoreCase("saveFiles")) { if (TabooLib.getVerint() > 10700) { e.setCancelled(true); } Bukkit.getScheduler().runTask(Main.getInst(), DataUtils::saveAllCaches); Bukkit.getScheduler().runTask(Main.getInst(), () -> PlayerDataManager.saveAllCaches(true, false)); + TLogger.getGlobalLogger().info("Successfully."); + } else if (e.getCommand().equalsIgnoreCase("tDebug")) { + if (TabooLib.getVerint() > 10700) { + e.setCancelled(true); + } + if (TabooLib.isDebug()) { + TabooLib.setDebug(false); + TLogger.getGlobalLogger().info("&cDisabled."); + } else { + TabooLib.setDebug(true); + TLogger.getGlobalLogger().info("&aEnabled."); + } } } @SuppressWarnings("deprecation") @EventHandler public void cmd(PlayerCommandPreprocessEvent e) { - if ("/unbreakable".equals(e.getMessage()) && PermissionUtils.hasPermission(e.getPlayer(), "taboolib.unbreakable")) { + if (e.getMessage().equals("/unbreakable") && PermissionUtils.hasPermission(e.getPlayer(), "taboolib.unbreakable")) { e.setCancelled(true); - - NBTItem nbti = new NBTItem(e.getPlayer().getItemInHand()); - nbti.setInteger("Unbreakable", 1); - e.getPlayer().setItemInHand(nbti.getItem()); - + NBTItem nbt = new NBTItem(e.getPlayer().getItemInHand()); + nbt.setInteger("Unbreakable", 1); + e.getPlayer().setItemInHand(nbt.getItem()); MsgUtils.send(e.getPlayer(), "Success!"); + } else if (e.getMessage().equals("/tellrawTest") && PermissionUtils.hasPermission(e.getPlayer(), "taboolib.tellraw")) { + e.setCancelled(true); + TellrawJson.create() + .append("§8[§3§lTabooLib§8] §7TellrawJson Test: §f[") + .append(ItemUtils.getCustomName(e.getPlayer().getItemInHand())).hoverItem(e.getPlayer().getItemInHand()) + .append("§f]") + .send(e.getPlayer()); } } } diff --git a/src/main/java/me/skymc/taboolib/listener/ListenerPluginDisable.java b/src/main/java/me/skymc/taboolib/listener/ListenerPluginDisable.java index c1b101b..b4083e1 100644 --- a/src/main/java/me/skymc/taboolib/listener/ListenerPluginDisable.java +++ b/src/main/java/me/skymc/taboolib/listener/ListenerPluginDisable.java @@ -1,9 +1,13 @@ package me.skymc.taboolib.listener; +import com.ilummc.tlib.TLib; +import com.ilummc.tlib.inject.TConfigWatcher; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.Main; -import me.skymc.taboolib.message.MsgUtils; +import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.common.configuration.TConfiguration; import me.skymc.taboolib.mysql.MysqlUtils; +import me.skymc.taboolib.mysql.hikari.HikariHandler; import me.skymc.taboolib.mysql.protect.MySQLConnection; import me.skymc.taboolib.timecycle.TimeCycleManager; import org.bukkit.event.EventHandler; @@ -11,33 +15,48 @@ import org.bukkit.event.Listener; import org.bukkit.event.server.PluginDisableEvent; import org.bukkit.scheduler.BukkitRunnable; +import java.io.File; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Optional; +/** + * @author sky + */ @TListener public class ListenerPluginDisable implements Listener { @EventHandler public void disable(PluginDisableEvent e) { + TabooLib.debug("Plugin \"" + e.getPlugin().getName() + "\" was disabled."); // 注销时间周期 TimeCycleManager.cancel(e.getPlugin()); - + // 注销插件配置 + Optional.ofNullable(TConfiguration.getFiles().get(e.getPlugin().getName())).ifPresent(files -> { + TConfigWatcher tConfigWatcher = TLib.getTLib().getConfigWatcher(); + for (File file : files) { + tConfigWatcher.removeListener(file); + TabooLib.debug("Remove TConfiguration \"" + file.getName() + "\" from Plugin \"" + e.getPlugin().getName() + "\""); + } + }); + // 注销数据库连接 + new HashSet<>(HikariHandler.getDataSource().keySet()).stream().filter(host -> e.getPlugin().equals(host.getPlugin()) && host.isAutoClose()).forEach(HikariHandler::closeDataSource); // 获取连接 - List conns = new ArrayList<>(); + List connection = new ArrayList<>(); for (MySQLConnection conn : MysqlUtils.CONNECTIONS) { if (conn.getPlugin().equals(e.getPlugin())) { - conns.add(conn); + connection.add(conn); MysqlUtils.CONNECTIONS.remove(conn); } } - // 异步注销 BukkitRunnable runnable = new BukkitRunnable() { @Override public void run() { int i = 0; - for (MySQLConnection conn : conns) { + for (MySQLConnection conn : connection) { conn.setFallReconnection(false); conn.closeConnection(); i++; @@ -47,7 +66,6 @@ public class ListenerPluginDisable implements Listener { } } }; - // 如果插件关闭 try { runnable.runTaskLater(Main.getInst(), 40); diff --git a/src/main/java/me/skymc/taboolib/listener/TListenerHandler.java b/src/main/java/me/skymc/taboolib/listener/TListenerHandler.java index 100e8ba..927419e 100644 --- a/src/main/java/me/skymc/taboolib/listener/TListenerHandler.java +++ b/src/main/java/me/skymc/taboolib/listener/TListenerHandler.java @@ -2,7 +2,8 @@ package me.skymc.taboolib.listener; import com.ilummc.tlib.util.Strings; import me.skymc.taboolib.TabooLib; -import me.skymc.taboolib.fileutils.FileUtils; +import me.skymc.taboolib.TabooLibLoader; +import me.skymc.taboolib.methods.ReflectionUtils; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; @@ -28,12 +29,10 @@ public class TListenerHandler implements Listener { */ public static void setupListeners() { for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { - if (plugin.equals(TabooLib.instance()) || plugin.getDescription().getDepend().contains("TabooLib")) { - try { - setupListener(plugin); - } catch (Exception e) { - e.printStackTrace(); - } + try { + setupListener(plugin); + } catch (Exception e) { + e.printStackTrace(); } } } @@ -45,25 +44,27 @@ public class TListenerHandler implements Listener { * @param plugin 插件 */ public static void setupListener(Plugin plugin) { - List classes = FileUtils.getClasses(plugin); - for (Class pluginClass : classes) { - if (Listener.class.isAssignableFrom(pluginClass) && pluginClass.isAnnotationPresent(TListener.class)) { - try { - TListener tListener = pluginClass.getAnnotation(TListener.class); - // 检查注册条件 - if (tListener.depend().length > 0 && !Strings.isBlank(tListener.depend()[0])) { - if (Arrays.stream(tListener.depend()).anyMatch(depend -> Bukkit.getPluginManager().getPlugin(depend) == null)) { - continue; + TabooLibLoader.getPluginClasses(plugin).ifPresent(classes -> { + for (Class pluginClass : classes) { + if (org.bukkit.event.Listener.class.isAssignableFrom(pluginClass) && pluginClass.isAnnotationPresent(TListener.class)) { + try { + TListener tListener = pluginClass.getAnnotation(TListener.class); + // 检查注册条件 + 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) ReflectionUtils.instantiateObject(pluginClass); + listeners.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(listener); + TabooLib.debug("Listener " + listener.getClass().getSimpleName() + " setup successfully. (" + plugin.getName() + ")"); + } catch (Exception e) { + TabooLib.debug("Listener setup failed: " + e.toString()); } - // 实例化监听器 - Listener listener = plugin.getClass().equals(pluginClass) ? (Listener) plugin : (Listener) pluginClass.newInstance(); - listeners.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(listener); - } catch (Exception e) { - e.printStackTrace(); } } - } + }); } /** @@ -113,6 +114,7 @@ public class TListenerHandler implements Listener { } // 注册监听 Bukkit.getPluginManager().registerEvents(listener, plugin); + TabooLib.debug("Listener " + listener.getClass().getSimpleName() + " registered. (" + plugin.getName() + ")"); } }); } @@ -154,6 +156,10 @@ public class TListenerHandler implements Listener { }); } + public static HashMap> getListeners() { + return listeners; + } + @EventHandler public void onPluginEnable(PluginEnableEvent e) { try { @@ -170,14 +176,4 @@ public class TListenerHandler implements Listener { } catch (Exception ignored) { } } - - // ********************************* - // - // Getter and Setter - // - // ********************************* - - public static HashMap> getListeners() { - return listeners; - } } diff --git a/src/main/java/me/skymc/taboolib/message/MsgUtils.java b/src/main/java/me/skymc/taboolib/message/MsgUtils.java index 8692de7..9ed7c56 100644 --- a/src/main/java/me/skymc/taboolib/message/MsgUtils.java +++ b/src/main/java/me/skymc/taboolib/message/MsgUtils.java @@ -5,6 +5,7 @@ import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.plugin.Plugin; +@Deprecated public class MsgUtils { public static void send(CommandSender sender, String s) { diff --git a/src/main/java/me/skymc/taboolib/methods/ReflectionUtils.java b/src/main/java/me/skymc/taboolib/methods/ReflectionUtils.java index 6b2c54a..eede188 100644 --- a/src/main/java/me/skymc/taboolib/methods/ReflectionUtils.java +++ b/src/main/java/me/skymc/taboolib/methods/ReflectionUtils.java @@ -19,582 +19,585 @@ import java.util.Map; *

  • Don't claim this class as your own *
  • Don't remove this disclaimer * - *

    + * * It would be nice if you provide credit to me if you use this class in a published project - * + * * @author DarkBlade12 * @version 1.1 */ public final class ReflectionUtils { - // Prevent accidental construction - private ReflectionUtils() {} + // Prevent accidental construction + private ReflectionUtils() { + } - /** - * Returns the constructor of a given class with the given parameter types - * - * @param clazz Target class - * @param parameterTypes Parameter types of the desired constructor - * @return The constructor of the target class with the specified parameter types - * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found - * @see DataType - * @see DataType#getPrimitive(Class[]) - * @see DataType#compare(Class[], Class[]) - */ - public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { - Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); - for (Constructor constructor : clazz.getConstructors()) { - if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { - continue; - } - return constructor; - } - throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); - } + /** + * Returns the constructor of a given class with the given parameter types + * + * @param clazz Target class + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @see DataType + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Constructor constructor : clazz.getDeclaredConstructors()) { + if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { + continue; + } + constructor.setAccessible(true); + return constructor; + } + throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); + } - /** - * Returns the constructor of a desired class with the given parameter types - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param parameterTypes Parameter types of the desired constructor - * @return The constructor of the desired target class with the specified parameter types - * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found - * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getConstructor(Class, Class...) - */ - public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { - return getConstructor(packageType.getClass(className), parameterTypes); - } + /** + * Returns the constructor of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the desired target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getConstructor(Class, Class...) + */ + public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getConstructor(packageType.getClass(className), parameterTypes); + } - /** - * Returns an instance of a class with the given arguments - * - * @param clazz Target class - * @param arguments Arguments which are used to construct an object of the target class - * @return The instance of the target class with the specified arguments - * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances - * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) - * @throws InvocationTargetException If the desired constructor cannot be invoked - * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found - */ - public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); - } + /** + * Returns an instance of a class with the given arguments + * + * @param clazz Target class + * @param arguments Arguments which are used to construct an object of the target class + * @return The instance of the target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + */ + public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); + } - /** - * Returns an instance of a desired class with the given arguments - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param arguments Arguments which are used to construct an object of the desired target class - * @return The instance of the desired target class with the specified arguments - * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances - * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) - * @throws InvocationTargetException If the desired constructor cannot be invoked - * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #instantiateObject(Class, Object...) - */ - public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { - return instantiateObject(packageType.getClass(className), arguments); - } + /** + * Returns an instance of a desired class with the given arguments + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param arguments Arguments which are used to construct an object of the desired target class + * @return The instance of the desired target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #instantiateObject(Class, Object...) + */ + public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return instantiateObject(packageType.getClass(className), arguments); + } - /** - * Returns a method of a class with the given parameter types - * - * @param clazz Target class - * @param methodName Name of the desired method - * @param parameterTypes Parameter types of the desired method - * @return The method of the target class with the specified name and parameter types - * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found - * @see DataType#getPrimitive(Class[]) - * @see DataType#compare(Class[], Class[]) - */ - public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { - Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); - for (Method method : clazz.getMethods()) { - if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { - continue; - } - return method; - } - throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); - } + /** + * Returns a method of a class with the given parameter types + * + * @param clazz Target class + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Method method : clazz.getDeclaredMethods()) { + if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { + continue; + } + method.setAccessible(true); + return method; + } + throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); + } - /** - * Returns a method of a desired class with the given parameter types - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param methodName Name of the desired method - * @param parameterTypes Parameter types of the desired method - * @return The method of the desired target class with the specified name and parameter types - * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getMethod(Class, String, Class...) - */ - public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { - return getMethod(packageType.getClass(className), methodName, parameterTypes); - } + /** + * Returns a method of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the desired target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getMethod(Class, String, Class...) + */ + public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getMethod(packageType.getClass(className), methodName, parameterTypes); + } - /** - * Invokes a method on an object with the given arguments - * - * @param instance Target object - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found - * @see #getMethod(Class, String, Class...) - * @see DataType#getPrimitive(Object[]) - */ - public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); - } + /** + * Invokes a method on an object with the given arguments + * + * @param instance Target object + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } - /** - * Invokes a method of the target class on an object with the given arguments - * - * @param instance Target object - * @param clazz Target class - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found - * @see #getMethod(Class, String, Class...) - * @see DataType#getPrimitive(Object[]) - */ - public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); - } + /** + * Invokes a method of the target class on an object with the given arguments + * + * @param instance Target object + * @param clazz Target class + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } - /** - * Invokes a method of a desired class on an object with the given arguments - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #invokeMethod(Object, Class, String, Object...) - */ - public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { - return invokeMethod(instance, packageType.getClass(className), methodName, arguments); - } + /** + * Invokes a method of a desired class on an object with the given arguments + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #invokeMethod(Object, Class, String, Object...) + */ + public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return invokeMethod(instance, packageType.getClass(className), methodName, arguments); + } - /** - * Returns a field of the target class with the given name - * - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The field of the target class with the specified name - * @throws NoSuchFieldException If the desired field of the given class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - */ - public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { - Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); - field.setAccessible(true); - return field; - } + /** + * Returns a field of the target class with the given name + * + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the target class with the specified name + * @throws NoSuchFieldException If the desired field of the given class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + */ + public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { + Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); + field.setAccessible(true); + return field; + } - /** - * Returns a field of a desired class with the given name - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The field of the desired target class with the specified name - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getField(Class, boolean, String) - */ - public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { - return getField(packageType.getClass(className), declared, fieldName); - } + /** + * Returns a field of a desired class with the given name + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the desired target class with the specified name + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getField(Class, boolean, String) + */ + public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { + return getField(packageType.getClass(className), declared, fieldName); + } - /** - * Returns the value of a field of the given class of an object - * - * @param instance Target object - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @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); - } + /** + * Returns the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @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); + } - /** - * Returns the value of a field of a desired class of an object - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getValue(Object, Class, boolean, String) - */ - public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { - return getValue(instance, packageType.getClass(className), declared, fieldName); - } + /** + * Returns the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + return getValue(instance, packageType.getClass(className), declared, fieldName); + } - /** - * Returns the value of a field with the given name of an object - * - * @param instance Target object - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target object cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getValue(Object, Class, boolean, String) - */ - public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - return getValue(instance, instance.getClass(), declared, fieldName); - } + /** + * Returns the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getValue(instance, instance.getClass(), declared, fieldName); + } - /** - * Sets the value of a field of the given class of an object - * - * @param instance Target object - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @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); - } + /** + * Sets the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @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); + } - /** - * Sets the value of a field of a desired class of an object - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #setValue(Object, Class, boolean, String, Object) - */ - public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { - setValue(instance, packageType.getClass(className), declared, fieldName, value); - } + /** + * Sets the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + setValue(instance, packageType.getClass(className), declared, fieldName, value); + } - /** - * Sets the value of a field with the given name of an object - * - * @param instance Target object - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target object cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #setValue(Object, Class, boolean, String, Object) - */ - public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - setValue(instance, instance.getClass(), declared, fieldName, value); - } + /** + * Sets the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + setValue(instance, instance.getClass(), declared, fieldName, value); + } - /** - * Represents an enumeration of dynamic packages of NMS and CraftBukkit - *

    - * This class is part of the ReflectionUtils and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.0 - */ - public enum PackageType { - MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), - CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), - CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), - CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), - CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), - CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), - CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), - CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), - CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), - CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), - CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), - CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), - CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), - CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), - CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), - CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), - CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), - CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), - CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), - CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); + /** + * Represents an enumeration of dynamic packages of NMS and CraftBukkit + *

    + * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum PackageType { + MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), + CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), + CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), + CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), + CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), + CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), + CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), + CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), + CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), + CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), + CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), + CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), + CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), + CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), + CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), + CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), + CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), + CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), + CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), + CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); - private final String path; + private final String path; - /** - * Construct a new package type - * - * @param path Path of the package - */ - PackageType(String path) { - this.path = path; - } + /** + * Construct a new package type + * + * @param path Path of the package + */ + PackageType(String path) { + this.path = path; + } - /** - * Construct a new package type - * - * @param parent Parent package of the package - * @param path Path of the package - */ - PackageType(PackageType parent, String path) { - this(parent + "." + path); - } + /** + * Construct a new package type + * + * @param parent Parent package of the package + * @param path Path of the package + */ + PackageType(PackageType parent, String path) { + this(parent + "." + path); + } - /** - * Returns the path of this package type - * - * @return The path - */ - public String getPath() { - return path; - } + /** + * Returns the path of this package type + * + * @return The path + */ + public String getPath() { + return path; + } - /** - * Returns the class with the given name - * - * @param className Name of the desired class - * @return The class with the specified name - * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found - */ - public Class getClass(String className) throws ClassNotFoundException { - return Class.forName(this + "." + className); - } + /** + * Returns the class with the given name + * + * @param className Name of the desired class + * @return The class with the specified name + * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found + */ + public Class getClass(String className) throws ClassNotFoundException { + return Class.forName(this + "." + className); + } - // Override for convenience - @Override - public String toString() { - return path; - } + // Override for convenience + @Override + public String toString() { + return path; + } - /** - * Returns the version of your server - * - * @return The server version - */ - public static String getServerVersion() { - return Bukkit.getServer().getClass().getPackage().getName().substring(23); - } - } + /** + * Returns the version of your server + * + * @return The server version + */ + public static String getServerVersion() { + return Bukkit.getServer().getClass().getPackage().getName().substring(23); + } + } - /** - * Represents an enumeration of Java data types with corresponding classes - *

    - * This class is part of the ReflectionUtils and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.0 - */ - public enum DataType { - BYTE(byte.class, Byte.class), - SHORT(short.class, Short.class), - INTEGER(int.class, Integer.class), - LONG(long.class, Long.class), - CHARACTER(char.class, Character.class), - FLOAT(float.class, Float.class), - DOUBLE(double.class, Double.class), - BOOLEAN(boolean.class, Boolean.class); + /** + * Represents an enumeration of Java data types with corresponding classes + *

    + * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum DataType { + BYTE(byte.class, Byte.class), + SHORT(short.class, Short.class), + INTEGER(int.class, Integer.class), + LONG(long.class, Long.class), + CHARACTER(char.class, Character.class), + FLOAT(float.class, Float.class), + DOUBLE(double.class, Double.class), + BOOLEAN(boolean.class, Boolean.class); - private static final Map, DataType> CLASS_MAP = new HashMap<>(); - private final Class primitive; - private final Class reference; + private static final Map, DataType> CLASS_MAP = new HashMap<>(); + private final Class primitive; + private final Class reference; - // Initialize map for quick class lookup - static { - for (DataType type : values()) { - CLASS_MAP.put(type.primitive, type); - CLASS_MAP.put(type.reference, type); - } - } + // Initialize map for quick class lookup + static { + for (DataType type : values()) { + CLASS_MAP.put(type.primitive, type); + CLASS_MAP.put(type.reference, type); + } + } - /** - * Construct a new data type - * - * @param primitive Primitive class of this data type - * @param reference Reference class of this data type - */ - DataType(Class primitive, Class reference) { - this.primitive = primitive; - this.reference = reference; - } + /** + * Construct a new data type + * + * @param primitive Primitive class of this data type + * @param reference Reference class of this data type + */ + DataType(Class primitive, Class reference) { + this.primitive = primitive; + this.reference = reference; + } - /** - * Returns the primitive class of this data type - * - * @return The primitive class - */ - public Class getPrimitive() { - return primitive; - } + /** + * Returns the primitive class of this data type + * + * @return The primitive class + */ + public Class getPrimitive() { + return primitive; + } - /** - * Returns the reference class of this data type - * - * @return The reference class - */ - public Class getReference() { - return reference; - } + /** + * Returns the reference class of this data type + * + * @return The reference class + */ + public Class getReference() { + return reference; + } - /** - * Returns the data type with the given primitive/reference class - * - * @param clazz Primitive/Reference class of the data type - * @return The data type - */ - public static DataType fromClass(Class clazz) { - return CLASS_MAP.get(clazz); - } + /** + * Returns the data type with the given primitive/reference class + * + * @param clazz Primitive/Reference class of the data type + * @return The data type + */ + public static DataType fromClass(Class clazz) { + return CLASS_MAP.get(clazz); + } - /** - * Returns the primitive class of the data type with the given reference class - * - * @param clazz Reference class of the data type - * @return The primitive class - */ - public static Class getPrimitive(Class clazz) { - DataType type = fromClass(clazz); - return type == null ? clazz : type.getPrimitive(); - } + /** + * Returns the primitive class of the data type with the given reference class + * + * @param clazz Reference class of the data type + * @return The primitive class + */ + public static Class getPrimitive(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getPrimitive(); + } - /** - * Returns the reference class of the data type with the given primitive class - * - * @param clazz Primitive class of the data type - * @return The reference class - */ - public static Class getReference(Class clazz) { - DataType type = fromClass(clazz); - return type == null ? clazz : type.getReference(); - } + /** + * Returns the reference class of the data type with the given primitive class + * + * @param clazz Primitive class of the data type + * @return The reference class + */ + public static Class getReference(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getReference(); + } - /** - * Returns the primitive class array of the given class array - * - * @param classes Given class array - * @return The primitive class array - */ - public static Class[] getPrimitive(Class[] classes) { - int length = classes == null ? 0 : classes.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getPrimitive(classes[index]); - } - return types; - } + /** + * Returns the primitive class array of the given class array + * + * @param classes Given class array + * @return The primitive class array + */ + public static Class[] getPrimitive(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(classes[index]); + } + return types; + } - /** - * Returns the reference class array of the given class array - * - * @param classes Given class array - * @return The reference class array - */ - public static Class[] getReference(Class[] classes) { - int length = classes == null ? 0 : classes.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getReference(classes[index]); - } - return types; - } + /** + * Returns the reference class array of the given class array + * + * @param classes Given class array + * @return The reference class array + */ + public static Class[] getReference(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(classes[index]); + } + return types; + } - /** - * Returns the primitive class array of the given object array - * - * @return The primitive class array - */ - public static Class[] getPrimitive(Object[] objects) { - int length = objects == null ? 0 : objects.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getPrimitive(objects[index].getClass()); - } - return types; - } + /** + * Returns the primitive class array of the given object array + * + * @return The primitive class array + */ + public static Class[] getPrimitive(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(objects[index].getClass()); + } + return types; + } - /** - * Returns the reference class array of the given object array - * - * @return The reference class array - */ - public static Class[] getReference(Object[] objects) { - int length = objects == null ? 0 : objects.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getReference(objects[index].getClass()); - } - return types; - } + /** + * Returns the reference class array of the given object array + * + * @return The reference class array + */ + public static Class[] getReference(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(objects[index].getClass()); + } + return types; + } - /** - * Compares two class arrays on equivalence - * - * @param primary Primary class array - * @param secondary Class array which is compared to the primary array - * @return Whether these arrays are equal or not - */ - public static boolean compare(Class[] primary, Class[] secondary) { - if (primary == null || secondary == null || primary.length != secondary.length) { - return false; - } - for (int index = 0; index < primary.length; index++) { - Class primaryClass = primary[index]; - Class secondaryClass = secondary[index]; - if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { - continue; - } - return false; - } - return true; - } - } + /** + * Compares two class arrays on equivalence + * + * @param primary Primary class array + * @param secondary Class array which is compared to the primary array + * @return Whether these arrays are equal or not + */ + public static boolean compare(Class[] primary, Class[] secondary) { + if (primary == null || secondary == null || primary.length != secondary.length) { + return false; + } + for (int index = 0; index < primary.length; index++) { + Class primaryClass = primary[index]; + Class secondaryClass = secondary[index]; + if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { + continue; + } + return false; + } + return true; + } + } } \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/mysql/builder/SQLColumn.java b/src/main/java/me/skymc/taboolib/mysql/builder/SQLColumn.java index cf7ce3f..dd6463f 100644 --- a/src/main/java/me/skymc/taboolib/mysql/builder/SQLColumn.java +++ b/src/main/java/me/skymc/taboolib/mysql/builder/SQLColumn.java @@ -22,7 +22,7 @@ public class SQLColumn { private SQLColumnOption[] columnOptions; /** - * 文本类型常用构造器 + * 文本 类型常用构造器 * new SQLColumn(SQLColumnType.TEXT, "username"); */ public SQLColumn(SQLColumnType columnType, String columnName) { @@ -30,7 +30,17 @@ public class SQLColumn { } /** - * 主键类型常用构造器 + * CHAR 类型常用构造器 + * + * @param columnType + * @param columnName + */ + public SQLColumn(SQLColumnType columnType, int m, String columnName) { + this(columnType, m, 0, columnName, null); + } + + /** + * 主键 类型常用构造器 * new SQLColumn(SQLColumnType.TEXT, "username", SQLColumnOption.PRIMARY_KEY, SQLColumnOption.AUTO_INCREMENT); */ public SQLColumn(SQLColumnType columnType, String columnName, SQLColumnOption... columnOptions) { @@ -38,7 +48,7 @@ public class SQLColumn { } /** - * 数据类型常用构造器 + * 数据 类型常用构造器 * new SQLColumn(SQLColumnType.TEXT, "player_group", "PLAYER"); */ public SQLColumn(SQLColumnType columnType, String columnName, Object defaultValue) { @@ -99,25 +109,25 @@ public class SQLColumn { for (SQLColumnOption options : columnOptions) { switch (options) { case NOTNULL: - builder.append(" not null"); + builder.append(" NOT NULL"); break; case PRIMARY_KEY: - builder.append(" primary key"); + builder.append(" PRIMARY KEY"); break; case AUTO_INCREMENT: - builder.append(" auto_increment"); + builder.append(" AUTO_INCREMENT"); break; case UNIQUE_KEY: - builder.append(" unique key"); + builder.append(" UNIQUE KEY"); break; default: } } if (defaultValue != null) { if (defaultValue instanceof String) { - builder.append(" default '").append(defaultValue).append("'"); + builder.append(" DEFAULT '").append(defaultValue).append("'"); } else { - builder.append(" default ").append(defaultValue); + builder.append(" DEFAULT ").append(defaultValue); } } return builder.toString(); diff --git a/src/main/java/me/skymc/taboolib/mysql/builder/SQLExample.java b/src/main/java/me/skymc/taboolib/mysql/builder/SQLExample.java deleted file mode 100644 index e6dc79a..0000000 --- a/src/main/java/me/skymc/taboolib/mysql/builder/SQLExample.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.skymc.taboolib.mysql.builder; - -import com.zaxxer.hikari.HikariDataSource; -import org.bukkit.plugin.java.JavaPlugin; - -/** - * @Author sky - * @Since 2018-07-02 23:43 - */ -public class SQLExample extends JavaPlugin { - - private SQLHost sqlHost; - private SQLTable sqlTable; - private HikariDataSource dataSource; - - @Override - public void onEnable() { - int value = sqlTable.executeQuery("select * from table where username = ?") - .dataSource(dataSource) - .statement(statement -> statement.setString(1, "BlackSKY")) - .resultNext(result -> result.getInt("value")) - .run(0, 0); - - sqlTable.executeUpdate("statement table set value = ? where username = ?") - .dataSource(dataSource) - .statement(statement -> { - statement.setInt(1, 999); - statement.setString(2, "BlackSKY"); - }).run(); - } -} diff --git a/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java b/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java index 13e9c15..a0195bb 100644 --- a/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java +++ b/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java @@ -4,7 +4,6 @@ import com.ilummc.tlib.util.Strings; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.plugin.Plugin; -import java.text.MessageFormat; import java.util.Objects; /** @@ -19,18 +18,28 @@ public class SQLHost { private String password; private String database; private Plugin plugin; + private boolean autoClose; public SQLHost(ConfigurationSection section, Plugin plugin) { + this(section, plugin, false); + } + + public SQLHost(ConfigurationSection section, Plugin plugin, boolean autoClose) { this(section.getString("host", "localhost"), section.getString("user", "root"), section.getString("port", "3306"), section.getString("password", ""), section.getString("database", "test"), plugin); } public SQLHost(String host, String user, String port, String password, String database, Plugin plugin) { + this(host, user, port, password, database, plugin, false); + } + + public SQLHost(String host, String user, String port, String password, String database, Plugin plugin, boolean autoClose) { this.host = host; this.user = user; this.port = port; this.password = password; this.database = database; this.plugin = plugin; + this.autoClose = false; } public String getHost() { @@ -57,6 +66,10 @@ public class SQLHost { return plugin; } + public boolean isAutoClose() { + return autoClose; + } + public String getConnectionUrl() { return Strings.replaceWithOrder("jdbc:mysql://{0}:{1}/{2}?characterEncoding=utf-8&useSSL=false", this.host, this.port, this.database); } @@ -74,16 +87,18 @@ public class SQLHost { return false; } SQLHost sqlHost = (SQLHost) o; - return Objects.equals(getHost(), sqlHost.getHost()) && + return autoClose == sqlHost.autoClose && + Objects.equals(getHost(), sqlHost.getHost()) && Objects.equals(getUser(), sqlHost.getUser()) && Objects.equals(getPort(), sqlHost.getPort()) && Objects.equals(getPassword(), sqlHost.getPassword()) && - Objects.equals(getDatabase(), sqlHost.getDatabase()); + Objects.equals(getDatabase(), sqlHost.getDatabase()) && + Objects.equals(getPlugin(), sqlHost.getPlugin()); } @Override public int hashCode() { - return Objects.hash(getHost(), getUser(), getPort(), getPassword(), getDatabase()); + return Objects.hash(getHost(), getUser(), getPort(), getPassword(), getDatabase(), getPlugin(), autoClose); } @Override @@ -95,6 +110,7 @@ public class SQLHost { ", password='" + password + '\'' + ", database='" + database + '\'' + ", plugin=" + plugin + + ", autoClose=" + autoClose + '}'; } } diff --git a/src/main/java/me/skymc/taboolib/mysql/builder/SQLTable.java b/src/main/java/me/skymc/taboolib/mysql/builder/SQLTable.java index ed2e5f5..d61e5fd 100644 --- a/src/main/java/me/skymc/taboolib/mysql/builder/SQLTable.java +++ b/src/main/java/me/skymc/taboolib/mysql/builder/SQLTable.java @@ -26,11 +26,7 @@ public class SQLTable { } public SQLTable addColumn(SQLColumn sqlColumn) { - if (columns == null) { - columns = new SQLColumn[] {sqlColumn}; - } else { - columns = ArrayUtils.arrayAppend(columns, sqlColumn); - } + columns = columns == null ? new SQLColumn[] {sqlColumn} : ArrayUtils.arrayAppend(columns, sqlColumn); return this; } @@ -52,6 +48,22 @@ public class SQLTable { return Strings.replaceWithOrder("truncate table `{0}`", tableName); } + public RunnableUpdate executeInsert(String values) { + return executeUpdate("insert into " + tableName + " values(" + values + ")"); + } + + public RunnableQuery executeSelect(String where) { + return executeQuery("select * from " + tableName + " where " + where); + } + + public RunnableQuery executeSelect() { + return executeQuery("select * from " + tableName); + } + + public RunnableUpdate executeUpdate(String update, String where) { + return executeUpdate("update " + tableName + " set " + update + " where " + where); + } + public RunnableUpdate executeUpdate(String query) { return new RunnableUpdate(query); } diff --git a/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java b/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java index 410c3f5..a422313 100644 --- a/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java +++ b/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java @@ -6,10 +6,8 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import me.skymc.taboolib.Main; import me.skymc.taboolib.fileutils.ConfigUtils; -import me.skymc.taboolib.fileutils.FileUtils; import me.skymc.taboolib.mysql.builder.SQLHost; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import javax.sql.DataSource; import java.util.concurrent.ConcurrentHashMap; @@ -91,4 +89,18 @@ public class HikariHandler { } return config; } + + // ********************************* + // + // Getter and Setter + // + // ********************************* + + public static ConcurrentHashMap getDataSource() { + return dataSource; + } + + public static FileConfiguration getSettings() { + return settings; + } } diff --git a/src/main/java/me/skymc/taboolib/object/Instantiable.java b/src/main/java/me/skymc/taboolib/object/Instantiable.java new file mode 100644 index 0000000..fb7e32e --- /dev/null +++ b/src/main/java/me/skymc/taboolib/object/Instantiable.java @@ -0,0 +1,18 @@ +package me.skymc.taboolib.object; + +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-27 10:04 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Instantiable { + + String value(); + +} diff --git a/src/main/java/me/skymc/taboolib/object/InstantiableLoader.java b/src/main/java/me/skymc/taboolib/object/InstantiableLoader.java new file mode 100644 index 0000000..45e7c0d --- /dev/null +++ b/src/main/java/me/skymc/taboolib/object/InstantiableLoader.java @@ -0,0 +1,82 @@ +package me.skymc.taboolib.object; + +import com.ilummc.tlib.util.Ref; +import me.skymc.taboolib.TabooLibLoader; +import me.skymc.taboolib.listener.TListener; +import me.skymc.taboolib.methods.ReflectionUtils; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.event.server.PluginEnableEvent; +import org.bukkit.plugin.Plugin; + +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @Author sky + * @Since 2018-08-27 10:04 + */ +@TListener +public class InstantiableLoader implements Listener { + + private static ConcurrentHashMap instance = new ConcurrentHashMap<>(); + + public InstantiableLoader() { + loadInstantiable(); + } + + @EventHandler + public void onEnable(PluginEnableEvent e) { + loadInstantiable(e.getPlugin()); + } + + @EventHandler + public void onDisable(PluginDisableEvent e) { + clear(e.getPlugin()); + } + + public static void clear(Plugin plugin) { + instance.entrySet().stream().filter(entry -> Ref.getCallerPlugin(entry.getValue().getClass()).equals(plugin)).forEach(entry -> instance.remove(entry.getKey())); + } + + public static void loadInstantiable() { + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + try { + loadInstantiable(plugin); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static void loadInstantiable(Plugin plugin) { + TabooLibLoader.getPluginClasses(plugin).ifPresent(classes -> { + for (Class pluginClass : classes) { + if (pluginClass.isAnnotationPresent(Instantiable.class)) { + Instantiable instantiable = (Instantiable) pluginClass.getAnnotation(Instantiable.class); + try { + instance.put(instantiable.value(), ReflectionUtils.instantiateObject(pluginClass)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }); + } + + // ********************************* + // + // Getter and Setter + // + // ********************************* + + public static ConcurrentHashMap getInstance() { + return instance; + } + + public static Optional getInstance(String name) { + return Optional.ofNullable(instance.get(name)); + } +} diff --git a/src/main/java/me/skymc/taboolib/other/NumberUtils.java b/src/main/java/me/skymc/taboolib/other/NumberUtils.java index 988dd4c..f811baa 100644 --- a/src/main/java/me/skymc/taboolib/other/NumberUtils.java +++ b/src/main/java/me/skymc/taboolib/other/NumberUtils.java @@ -3,6 +3,9 @@ package me.skymc.taboolib.other; import java.text.DecimalFormat; import java.util.Random; +/** + * @author sky + */ public class NumberUtils { private static Random random = new Random(); @@ -52,6 +55,22 @@ public class NumberUtils { } } + public static Boolean getBooleanAbbreviation(String str) { + if (str == null || str.isEmpty()) { + return false; + } + if (str.length() < 4) { + char var = str.charAt(0); + if (var == 'y' || var == 'Y' || var == 't' || var == 'T' || var == '1') { + return true; + } + if (var == 'n' || var == 'N' || var == 'f' || var == 'F' || var == '0') { + return false; + } + } + return getBoolean(str); + } + @Deprecated public static Random getRand() { return random; diff --git a/src/main/java/me/skymc/taboolib/plugin/PluginUtils.java b/src/main/java/me/skymc/taboolib/plugin/PluginUtils.java index dafbbd6..b1fb0a3 100644 --- a/src/main/java/me/skymc/taboolib/plugin/PluginUtils.java +++ b/src/main/java/me/skymc/taboolib/plugin/PluginUtils.java @@ -30,7 +30,7 @@ public class PluginUtils { } public static File getPluginFile(Plugin plugin) { - for (File pluginFile : Objects.requireNonNull(new File("plugins").listFiles())) { + for (File pluginFile : new File("plugins").listFiles()) { if (pluginFile.getName().endsWith(".jar")) { try { PluginDescriptionFile desc = Main.getInst().getPluginLoader().getPluginDescription(pluginFile); @@ -44,6 +44,21 @@ public class PluginUtils { return null; } + public static boolean isPluginExists(String name) { + for (File pluginFile : new File("plugins").listFiles()) { + if (pluginFile.getName().endsWith(".jar")) { + try { + PluginDescriptionFile desc = Main.getInst().getPluginLoader().getPluginDescription(pluginFile); + if (desc.getName().equalsIgnoreCase(name)) { + return true; + } + } catch (Exception ignored) { + } + } + } + return false; + } + public static void enable(Plugin plugin) { if (plugin != null && !plugin.isEnabled()) { Bukkit.getPluginManager().enablePlugin(plugin); diff --git a/src/main/java/me/skymc/taboolib/skull/SkullUtils.java b/src/main/java/me/skymc/taboolib/skull/SkullUtils.java index 569048f..7ce4239 100644 --- a/src/main/java/me/skymc/taboolib/skull/SkullUtils.java +++ b/src/main/java/me/skymc/taboolib/skull/SkullUtils.java @@ -1,36 +1,19 @@ package me.skymc.taboolib.skull; -import org.bukkit.Bukkit; +import me.skymc.taboolib.inventory.builder.ItemBuilder; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.SkullMeta; +@Deprecated public class SkullUtils { - - public static ItemStack getItme(OfflinePlayer p ) { - SkullMeta s = (SkullMeta) Bukkit.getItemFactory().getItemMeta(Material.SKULL_ITEM); - s.setOwner(p.getName()); - - ItemStack i = new ItemStack(Material.SKULL_ITEM); - i.setDurability((short) 3); - i.setItemMeta(s); - - return i; - } - - public static ItemStack getOnlineItem(OfflinePlayer p ) { - if (p.isOnline()) - { - SkullMeta s = (SkullMeta) Bukkit.getItemFactory().getItemMeta(Material.SKULL_ITEM); - s.setOwner(p.getName()); - - ItemStack i = new ItemStack(Material.SKULL_ITEM); - i.setDurability((short) 3); - i.setItemMeta(s); - return i; - } - return new ItemStack(Material.SKULL_ITEM); - } + + public static ItemStack getItme(OfflinePlayer p) { + return new ItemBuilder(p).build(); + } + + public static ItemStack getOnlineItem(OfflinePlayer p) { + return p.isOnline() ? new ItemBuilder(p).build() : new ItemStack(Material.SKULL_ITEM); + } } diff --git a/src/main/java/me/skymc/taboolib/socket/TabooLibClient.java b/src/main/java/me/skymc/taboolib/socket/TabooLibClient.java index d6a9a66..2706db7 100644 --- a/src/main/java/me/skymc/taboolib/socket/TabooLibClient.java +++ b/src/main/java/me/skymc/taboolib/socket/TabooLibClient.java @@ -2,9 +2,13 @@ package me.skymc.taboolib.socket; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.commands.builder.SimpleCommandBuilder; import me.skymc.taboolib.other.NumberUtils; import me.skymc.taboolib.socket.packet.Packet; import me.skymc.taboolib.socket.packet.PacketSerializer; +import me.skymc.taboolib.socket.packet.impl.PacketCommand; +import me.skymc.taboolib.socket.packet.impl.PacketMessage; +import me.skymc.taboolib.string.ArrayUtils; import org.bukkit.Bukkit; import java.io.*; @@ -83,6 +87,23 @@ public class TabooLibClient { TLocale.sendToConsole("COMMUNICATION.FAILED-READING-PACKET", e.getMessage()); } }); + + SimpleCommandBuilder.create("TabooLibClient", TabooLib.instance()) + .aliases("tclient") + .permission("*") + .execute((sender, args) -> { + if (args.length == 0) { + sender.sendMessage("§c[TabooLibClient] §f/tclient message §7[TEXT] §8- §7发送测试信息"); + sender.sendMessage("§c[TabooLibClient] §f/tclient command §7[TEXT] §8- §7发送测试命令"); + } else if (args[0].equalsIgnoreCase("message") && args.length > 1) { + sendPacket(new PacketMessage(ArrayUtils.arrayJoin(args, 1))); + } else if (args[0].equalsIgnoreCase("command") && args.length > 1) { + sendPacket(new PacketCommand(ArrayUtils.arrayJoin(args, 1))); + } else { + sender.sendMessage("§c[TabooLibClient] §7指令错误."); + } + return true; + }).build(); } // ********************************* diff --git a/src/main/java/me/skymc/taboolib/socket/TabooLibServer.java b/src/main/java/me/skymc/taboolib/socket/TabooLibServer.java index 57a30ef..ed2e92a 100644 --- a/src/main/java/me/skymc/taboolib/socket/TabooLibServer.java +++ b/src/main/java/me/skymc/taboolib/socket/TabooLibServer.java @@ -1,5 +1,6 @@ package me.skymc.taboolib.socket; +import me.skymc.taboolib.TabooLib; import me.skymc.taboolib.other.NumberUtils; import me.skymc.taboolib.socket.packet.Packet; import me.skymc.taboolib.socket.packet.PacketSerializer; @@ -55,20 +56,25 @@ public class TabooLibServer { /* 检测无效的客户端连接,如果超过 5000 毫秒没有收到客户端的回应(上一次心跳包的回应)则注销链接 */ - client.entrySet().stream().filter(connection -> connection.getValue().isAlive()).map(connection -> new PacketQuit(connection.getKey(), "Lost connection")).forEach(TabooLibServer::sendPacket); + client.entrySet().stream().filter(connection -> !connection.getValue().isAlive()).map(connection -> new PacketQuit(connection.getKey(), "Lost connection")).forEach(TabooLibServer::sendPacket); }, 0, 1, TimeUnit.SECONDS); - while (true) { - try { - Socket socket = server.accept(); - ClientConnection connection = new ClientConnection(socket); - client.put(socket.getPort(), connection); - executorService.execute(connection); - println("Client accepted: " + socket.getPort() + " online: " + client.size()); - } catch (Exception e) { - println("Client accept failed: " + e.toString()); + /* + 异步接收连接请求 + */ + Executors.newSingleThreadScheduledExecutor().execute(() -> { + while (true) { + try { + Socket socket = server.accept(); + ClientConnection connection = new ClientConnection(socket); + client.put(socket.getPort(), connection); + executorService.execute(connection); + println("Client accepted: " + socket.getPort() + " online: " + client.size()); + } catch (Exception e) { + println("Client accept failed: " + e.toString()); + } } - } + }); } public static void sendPacket(Packet packet) { @@ -76,7 +82,6 @@ public class TabooLibServer { } public static void sendPacket(String origin) { - println("Packet sending: " + origin + ", online: " + client.size()); // 在服务端尝试解析动作并运行 Optional.ofNullable(PacketSerializer.unSerialize(origin)).ifPresent(Packet::readOnServer); // 将动作发送至所有客户端 @@ -90,10 +95,9 @@ public class TabooLibServer { } public static void println(Object obj) { - System.out.println("[" + infoFormat.format(System.currentTimeMillis()) + " INFO]: " + obj); + System.out.println(TabooLib.isSpigot() ? obj : "[" + infoFormat.format(System.currentTimeMillis()) + " INFO]: " + obj); } - public static Optional> getConnection(int port) { return client.entrySet().stream().filter(entry -> entry.getKey().equals(port)).findFirst(); } diff --git a/src/main/java/me/skymc/taboolib/socket/packet/PacketParser.java b/src/main/java/me/skymc/taboolib/socket/packet/PacketParser.java index 0f733fd..c77cd31 100644 --- a/src/main/java/me/skymc/taboolib/socket/packet/PacketParser.java +++ b/src/main/java/me/skymc/taboolib/socket/packet/PacketParser.java @@ -4,6 +4,7 @@ import com.google.gson.JsonObject; import me.skymc.taboolib.fileutils.FileUtils; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -31,6 +32,43 @@ public class PacketParser { try { Packet packetObject = (Packet) packetFind.get().getConstructor(Integer.TYPE).newInstance(json.get("port").getAsInt()); packetObject.unSerialize(json); + Arrays.stream(packetObject.getClass().getDeclaredFields()).filter(field -> field.isAnnotationPresent(PacketValue.class)).forEach(field -> { + field.setAccessible(true); + try { + switch (field.getType().getSimpleName().toLowerCase()) { + case "double": + field.set(packetObject, json.get(field.getName()).getAsDouble()); + break; + case "long": + field.set(packetObject, json.get(field.getName()).getAsLong()); + break; + case "short": + field.set(packetObject, json.get(field.getName()).getAsShort()); + break; + case "boolean": + field.set(packetObject, json.get(field.getName()).getAsBoolean()); + break; + case "string": + field.set(packetObject, json.get(field.getName()).getAsString()); + break; + case "number": + field.set(packetObject, json.get(field.getName()).getAsNumber()); + break; + case "int": + case "integer": + field.set(packetObject, json.get(field.getName()).getAsInt()); + break; + case "char": + case "character": + field.set(packetObject, json.get(field.getName()).getAsCharacter()); + break; + default: + System.out.println("UnSerialize: Invalid packet value: " + field.getName()); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); return packetObject; } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/me/skymc/taboolib/socket/packet/PacketSerializer.java b/src/main/java/me/skymc/taboolib/socket/packet/PacketSerializer.java index 2ec3b94..ddd5aeb 100644 --- a/src/main/java/me/skymc/taboolib/socket/packet/PacketSerializer.java +++ b/src/main/java/me/skymc/taboolib/socket/packet/PacketSerializer.java @@ -3,22 +3,88 @@ package me.skymc.taboolib.socket.packet; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; +import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.TabooLibLoader; +import me.skymc.taboolib.listener.TListener; import me.skymc.taboolib.socket.packet.impl.PacketEmpty; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.event.server.PluginEnableEvent; +import org.bukkit.plugin.Plugin; + +import java.lang.reflect.Field; +import java.util.Arrays; /** * @Author sky * @Since 2018-08-22 23:32 */ -public class PacketSerializer { +@TListener +public class PacketSerializer implements Listener { private static PacketParser parser = new PacketParser(); + public PacketSerializer() { + loadPacket(); + } + + @EventHandler + public void onEnable(PluginEnableEvent e) { + loadPacket(e.getPlugin()); + } + + @EventHandler + public void onDisable(PluginDisableEvent e) { + unloadPacket(e.getPlugin()); + } + + public static void loadPacket() { + Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(PacketSerializer::loadPacket); + } + + public static void loadPacket(Plugin plugin) { + if (TabooLib.isTabooLib(plugin) || TabooLib.isDependTabooLib(plugin)) { + TabooLibLoader.getPluginClasses(plugin).ifPresent(classes -> classes.stream().filter(pluginClass -> pluginClass.isAnnotationPresent(PacketType.class)).forEach(pluginClass -> parser.getPackets().add(pluginClass))); + } + } + + public static void unloadPacket() { + Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(PacketSerializer::unloadPacket); + } + + public static void unloadPacket(Plugin plugin) { + if (TabooLib.isTabooLib(plugin) || TabooLib.isDependTabooLib(plugin)) { + TabooLibLoader.getPluginClasses(plugin).ifPresent(classes -> classes.stream().filter(pluginClass -> pluginClass.isAnnotationPresent(PacketType.class)).forEach(pluginClass -> parser.getPackets().remove(pluginClass))); + } + } + public static String serialize(Packet packet) { JsonObject json = new JsonObject(); + packet.serialize(json); json.addProperty("uid", packet.getUid()); json.addProperty("port", packet.getPort()); json.addProperty("packet", packet.getClass().getAnnotation(PacketType.class).name()); - packet.serialize(json); + Arrays.stream(packet.getClass().getDeclaredFields()).filter(field -> field.isAnnotationPresent(PacketValue.class)).forEach(field -> { + field.setAccessible(true); + try { + Object obj = field.get(packet); + if (obj instanceof Number) { + json.addProperty(field.getName(), (Number) obj); + } else if (obj instanceof Boolean) { + json.addProperty(field.getName(), (Boolean) obj); + } else if (obj instanceof String) { + json.addProperty(field.getName(), (String) obj); + } else if (obj instanceof Character) { + json.addProperty(field.getName(), (Character) obj); + } else { + System.out.println("Serialize: Invalid packet value: " + field.getName()); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); return json.toString(); } diff --git a/src/main/java/me/skymc/taboolib/socket/packet/PacketValue.java b/src/main/java/me/skymc/taboolib/socket/packet/PacketValue.java new file mode 100644 index 0000000..c3166ea --- /dev/null +++ b/src/main/java/me/skymc/taboolib/socket/packet/PacketValue.java @@ -0,0 +1,25 @@ +package me.skymc.taboolib.socket.packet; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 使用该注解的成员变量 + * 将会被自动序列化 + * + * 仅限以下类型: + * - Number + * - String + * - Boolean + * - Character + * + * @Author sky + * @Since 2018-08-22 23:09 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface PacketValue { + +} \ No newline at end of file diff --git a/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketCommand.java b/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketCommand.java new file mode 100644 index 0000000..ac1bcb4 --- /dev/null +++ b/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketCommand.java @@ -0,0 +1,37 @@ +package me.skymc.taboolib.socket.packet.impl; + +import me.skymc.taboolib.socket.TabooLibServer; +import me.skymc.taboolib.socket.packet.Packet; +import me.skymc.taboolib.socket.packet.PacketType; +import me.skymc.taboolib.socket.packet.PacketValue; +import org.bukkit.Bukkit; + +/** + * @Author sky + * @Since 2018-08-22 23:01 + */ +@PacketType(name = "command") +public class PacketCommand extends Packet { + + @PacketValue + private String command; + + public PacketCommand(int port) { + super(port); + } + + public PacketCommand(String command) { + super(Bukkit.getPort()); + this.command = command; + } + + @Override + public void readOnServer() { + String[] args = command.split(" "); + if (args[0].equalsIgnoreCase("online")) { + TabooLibServer.sendPacket(new PacketMessage(0, "Online: " + TabooLibServer.getClient().size())); + } else { + TabooLibServer.sendPacket(new PacketMessage(0, "Invalid arguments.")); + } + } +} diff --git a/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketHeartbeat.java b/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketHeartbeat.java index 346e26f..e28d06c 100644 --- a/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketHeartbeat.java +++ b/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketHeartbeat.java @@ -3,6 +3,7 @@ package me.skymc.taboolib.socket.packet.impl; import me.skymc.taboolib.socket.TabooLibClient; import me.skymc.taboolib.socket.packet.Packet; import me.skymc.taboolib.socket.packet.PacketType; +import org.bukkit.Bukkit; /** * @Author sky diff --git a/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketMessage.java b/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketMessage.java index a2f8927..9cc9698 100644 --- a/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketMessage.java +++ b/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketMessage.java @@ -5,6 +5,8 @@ import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.socket.TabooLibServer; import me.skymc.taboolib.socket.packet.Packet; import me.skymc.taboolib.socket.packet.PacketType; +import me.skymc.taboolib.socket.packet.PacketValue; +import org.bukkit.Bukkit; /** * @Author sky @@ -13,6 +15,7 @@ import me.skymc.taboolib.socket.packet.PacketType; @PacketType(name = "message") public class PacketMessage extends Packet { + @PacketValue private String message; public PacketMessage(int port) { @@ -24,23 +27,18 @@ public class PacketMessage extends Packet { this.message = message; } + public PacketMessage(String message) { + super(Bukkit.getPort()); + this.message = message; + } + @Override public void readOnServer() { - TabooLibServer.println(message); + TabooLibServer.println(getPort() + ": " + message); } @Override public void readOnClient() { TLocale.sendToConsole("COMMUNICATION.PACKET-MESSAGE", String.valueOf(getPort()), message); } - - @Override - public void serialize(JsonObject json) { - json.addProperty("message", message); - } - - @Override - public void unSerialize(JsonObject json) { - message = json.get("message").getAsString(); - } } diff --git a/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketQuit.java b/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketQuit.java index cdb740c..fcb46fd 100644 --- a/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketQuit.java +++ b/src/main/java/me/skymc/taboolib/socket/packet/impl/PacketQuit.java @@ -1,10 +1,10 @@ package me.skymc.taboolib.socket.packet.impl; -import com.google.gson.JsonObject; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.socket.TabooLibServer; import me.skymc.taboolib.socket.packet.Packet; import me.skymc.taboolib.socket.packet.PacketType; +import me.skymc.taboolib.socket.packet.PacketValue; /** * @Author sky @@ -13,6 +13,7 @@ import me.skymc.taboolib.socket.packet.PacketType; @PacketType(name = "quit") public class PacketQuit extends Packet { + @PacketValue private String message; public PacketQuit(int port) { @@ -43,14 +44,4 @@ public class PacketQuit extends Packet { public void readOnClient() { TLocale.sendToConsole("COMMUNICATION.CLIENT-QUITED", String.valueOf(getPort())); } - - @Override - public void serialize(JsonObject json) { - json.addProperty("message", message); - } - - @Override - public void unSerialize(JsonObject json) { - message = json.get("message").getAsString(); - } } diff --git a/src/main/java/me/skymc/taboolib/socket/server/ClientConnection.java b/src/main/java/me/skymc/taboolib/socket/server/ClientConnection.java index 997d1ab..6c8a4a6 100644 --- a/src/main/java/me/skymc/taboolib/socket/server/ClientConnection.java +++ b/src/main/java/me/skymc/taboolib/socket/server/ClientConnection.java @@ -46,7 +46,7 @@ public class ClientConnection implements Runnable { /* 连接丢失,客户端退出 */ - TabooLibServer.sendPacket(new PacketQuit(socket.getPort(), e.getMessage())); + TabooLibServer.sendPacket(new PacketQuit(socket.getPort(), "SocketException: " + e.getMessage())); } catch (Exception e) { TabooLibServer.println("Client running failed: " + e.toString()); } diff --git a/src/main/java/me/skymc/taboolib/string/ArrayUtils.java b/src/main/java/me/skymc/taboolib/string/ArrayUtils.java index 8b16548..40fee02 100644 --- a/src/main/java/me/skymc/taboolib/string/ArrayUtils.java +++ b/src/main/java/me/skymc/taboolib/string/ArrayUtils.java @@ -2,7 +2,6 @@ package me.skymc.taboolib.string; import com.ilummc.tlib.util.Strings; -import javax.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; @@ -20,15 +19,21 @@ import java.util.stream.IntStream; */ public class ArrayUtils { - public static String arrayJoin(String[] args, int start) { - return IntStream.range(start, args.length).mapToObj(i -> args[i] + " ").collect(Collectors.joining()).trim(); + public static int indexOf(T[] array, T obj) { + return array == null || array.length == 0 ? -1 : IntStream.range(0, array.length).filter(i -> array[i] != null && array[i].equals(obj)).findFirst().orElse(-1); + } + + public static boolean contains(T[] array, T obj) { + return indexOf(array, obj) != -1; } @SafeVarargs - public static List asList(T... args) { - List list = new ArrayList<>(); - Collections.addAll(list, args); - return list; + public static T[] asArray(T... args) { + return args; + } + + public static String arrayJoin(String[] args, int start) { + return IntStream.range(start, args.length).mapToObj(i -> args[i] + " ").collect(Collectors.joining()).trim(); } public static T[] arrayAppend(T[] array, T obj) { @@ -88,6 +93,13 @@ public class ArrayUtils { return firstElement == null ? def : obj; } + @SafeVarargs + public static List asList(T... args) { + List list = new ArrayList<>(); + Collections.addAll(list, args); + return list; + } + // ********************************* // // Deprecated diff --git a/src/main/java/me/skymc/taboolib/support/SupportWorldGuard.java b/src/main/java/me/skymc/taboolib/support/SupportWorldGuard.java index 241bba6..11141b5 100644 --- a/src/main/java/me/skymc/taboolib/support/SupportWorldGuard.java +++ b/src/main/java/me/skymc/taboolib/support/SupportWorldGuard.java @@ -1,5 +1,6 @@ package me.skymc.taboolib.support; +import com.google.common.base.Preconditions; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedRegion; @@ -9,60 +10,59 @@ import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +/** + * @Author AgarthaLib + */ public class SupportWorldGuard { - String Source_code_from_AgarthaLib; private WorldGuardPlugin worldGuard; public SupportWorldGuard() { - final Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"); - if (plugin != null) { - this.worldGuard = (WorldGuardPlugin) plugin; - } + Preconditions.checkNotNull(Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"), "WorldGuard was not found."); + worldGuard = WorldGuardPlugin.inst(); } - public final WorldGuardPlugin getWorldGuard() { + public WorldGuardPlugin getWorldGuard() { return this.worldGuard; } - public final RegionManager getRegionManager(final World world) { + public RegionManager getRegionManager(World world) { return this.worldGuard.getRegionManager(world); } - public final boolean isRegionManagerExists(final World world) { + public boolean isRegionManagerExists(World world) { return this.getRegionManager(world) != null; } - public final Collection getRegionIDs(final World world) { - final RegionManager regionManager = this.getRegionManager(world); - return regionManager.getRegions().keySet(); + public Collection getRegionIDs(World world) { + return getRegionManager(world).getRegions().keySet(); } - public final Collection getRegions(final World world) { - final RegionManager regionManager = this.getRegionManager(world); - return regionManager.getRegions().values(); + public Collection getRegions(World world) { + return getRegionManager(world).getRegions().values(); } - public final ProtectedRegion getRegion(final World world, final String id) { - final RegionManager regionManager = this.getRegionManager(world); - if (regionManager != null) { - for (final String key : regionManager.getRegions().keySet()) { - if (key.equalsIgnoreCase(id)) { - return regionManager.getRegion(key); - } - } - } - return null; + public List getRegionsAtLocation(World world, Location location) { + return getRegions(world).stream().filter(protectedRegion -> protectedRegion.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ())).map(ProtectedRegion::getId).collect(Collectors.toList()); } - public final boolean isRegionExists(final World world, final String id) { + public ProtectedRegion getRegion(World world, String id) { + RegionManager regionManager = this.getRegionManager(world); + return regionManager != null ? regionManager.getRegions().keySet().stream().filter(key -> key.equalsIgnoreCase(id)).findFirst().map(regionManager::getRegion).orElse(null) : null; + } + + public boolean isRegionExists(World world, String id) { return this.getRegion(world, id) != null; } - public final boolean isPlayerInsideRegion(final ProtectedRegion region, final Player player) { - final Location location = player.getLocation(); + public boolean isPlayerInsideRegion(ProtectedRegion region, Player player) { + Location location = player.getLocation(); return region.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ()); } } diff --git a/src/main/java/me/skymc/taboolib/update/UpdateTask.java b/src/main/java/me/skymc/taboolib/update/UpdateTask.java index 0bb475f..0536cef 100644 --- a/src/main/java/me/skymc/taboolib/update/UpdateTask.java +++ b/src/main/java/me/skymc/taboolib/update/UpdateTask.java @@ -1,32 +1,26 @@ package me.skymc.taboolib.update; import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.Main; import me.skymc.taboolib.TabooLib; import me.skymc.taboolib.fileutils.FileUtils; +import me.skymc.taboolib.player.PlayerUtils; +import me.skymc.taboolib.plugin.PluginUtils; import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; +import java.io.File; + /** * @author sky * @since 2018年2月23日 下午10:39:14 */ public class UpdateTask { - private static boolean haveUpdate = false; private static double newVersion = 0; - public static boolean isHaveUpdate() { - return haveUpdate; - } - - public static double getNewVersion() { - return newVersion; - } - public UpdateTask() { new BukkitRunnable() { @@ -35,34 +29,53 @@ public class UpdateTask { if (!Main.getInst().getConfig().getBoolean("UPDATE-CHECK")) { return; } - String value = FileUtils.getStringFromURL("https://api.github.com/repos/Bkm016/TabooLib/tags", null); if (value == null) { TLocale.Logger.error("UPDATETASK.VERSION-FAIL"); return; } - JsonElement json = new JsonParser().parse(value); if (json.isJsonArray()) { - JsonObject latestObject = json.getAsJsonArray().get(0).getAsJsonObject(); - newVersion = latestObject.get("name").getAsDouble(); + newVersion = json.getAsJsonArray().get(0).getAsJsonObject().get("name").getAsDouble(); if (TabooLib.getPluginVersion() >= newVersion) { TLocale.Logger.info("UPDATETASK.VERSION-LATEST"); } else { - haveUpdate = true; TLocale.Logger.info("UPDATETASK.VERSION-OUTDATED", String.valueOf(TabooLib.getPluginVersion()), String.valueOf(newVersion)); - - new BukkitRunnable() { - @Override - public void run() { - if (Main.getInst().getConfig().getBoolean("UPDATE-DOWNLOAD", false)) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "taboolib updatePlugin"); - } - } - }.runTask(Main.getInst()); + Bukkit.getScheduler().runTask(TabooLib.instance(), () -> updatePlugin(true)); } } } }.runTaskTimerAsynchronously(Main.getInst(), 100, 20 * 60 * 60 * 6); } + + public static boolean isHaveUpdate() { + return newVersion > 0; + } + + public static double getNewVersion() { + return newVersion; + } + + public static void updatePlugin(boolean shutdown) { + if (!UpdateTask.isHaveUpdate()) { + TLocale.Logger.info("COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-NOT-FOUND"); + return; + } + if (PlayerUtils.getOnlinePlayers().size() > 0) { + TLocale.Logger.info("COMMANDS.TABOOLIB.UPDATEPLUGIN.PLAYER-ONLINE"); + return; + } + File pluginFile = PluginUtils.getPluginFile(Main.getInst()); + if (pluginFile == null) { + TLocale.Logger.info("COMMANDS.TABOOLIB.UPDATEPLUGIN.FILE-NOT-FOUND"); + return; + } + Bukkit.getScheduler().runTaskAsynchronously(TabooLib.instance(), () -> { + FileUtils.download("https://github.com/Bkm016/TabooLib/releases/download/" + newVersion + "/TabooLib-" + newVersion + ".jar", pluginFile); + TLocale.Logger.info("COMMANDS.TABOOLIB.UPDATEPLUGIN.UPDATE-SUCCESS"); + if (shutdown) { + Bukkit.shutdown(); + } + }); + } } diff --git a/src/main/java/me/skymc/tlm/command/TLMCommands.java b/src/main/java/me/skymc/tlm/command/TLMCommands.java index 5ef1819..99b6393 100644 --- a/src/main/java/me/skymc/tlm/command/TLMCommands.java +++ b/src/main/java/me/skymc/tlm/command/TLMCommands.java @@ -1,63 +1,68 @@ package me.skymc.tlm.command; +import me.skymc.taboolib.TabooLib; +import me.skymc.taboolib.commands.builder.SimpleCommandBuilder; +import me.skymc.taboolib.object.Instantiable; import me.skymc.tlm.TLM; import me.skymc.tlm.command.sub.TLMInvCommand; import me.skymc.tlm.command.sub.TLMKitCommand; import me.skymc.tlm.command.sub.TLMListCommand; import me.skymc.tlm.command.sub.TLMReloadCommand; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; /** * @author sky * @since 2018年2月18日 上午12:02:08 */ -public class TLMCommands implements CommandExecutor { +@Instantiable("TLMCommands") +public class TLMCommands { - @Override - public boolean onCommand(CommandSender sender, Command arg1, String arg2, String[] args) { - if (args.length == 0 || "help".equalsIgnoreCase(args[0])) { - if (sender.hasPermission("taboolib.admin")) { - TLM.getInst().getLanguage().get("COMMAND-HELP").send(sender); - } else { - TLM.getInst().getLanguage().get("NOPERMISSION-HELP").send(sender); - } - } + public TLMCommands() { + SimpleCommandBuilder.create("taboolibrarymodule", TabooLib.instance()) + .aliases("tlm") + .permission("tlm.use") + .execute((sender, args) -> { + if (args.length == 0 || "help".equalsIgnoreCase(args[0])) { + if (sender.hasPermission("taboolib.admin")) { + TLM.getInst().getLanguage().get("COMMAND-HELP").send(sender); + } else { + TLM.getInst().getLanguage().get("NOPERMISSION-HELP").send(sender); + } + } - // 重载 - else if ("reload".equalsIgnoreCase(args[0])) { - if (sender.hasPermission("taboolib.admin")) { - new TLMReloadCommand(sender, args); - } else { - TLM.getInst().getLanguage().get("NOPERMISSION-RELOAD").send(sender); - } - } + // 重载 + else if ("reload".equalsIgnoreCase(args[0])) { + if (sender.hasPermission("taboolib.admin")) { + new TLMReloadCommand(sender, args); + } else { + TLM.getInst().getLanguage().get("NOPERMISSION-RELOAD").send(sender); + } + } - // 列出 - else if ("list".equalsIgnoreCase(args[0])) { - if (sender.hasPermission("taboolib.admin")) { - new TLMListCommand(sender, args); - } else { - TLM.getInst().getLanguage().get("NOPERMISSION-LIST").send(sender); - } - } + // 列出 + else if ("list".equalsIgnoreCase(args[0])) { + if (sender.hasPermission("taboolib.admin")) { + new TLMListCommand(sender, args); + } else { + TLM.getInst().getLanguage().get("NOPERMISSION-LIST").send(sender); + } + } - // InventorySave 模块 - else if ("inv".equalsIgnoreCase(args[0])) { - if (sender.hasPermission("taboolib.admin")) { - new TLMInvCommand(sender, args); - } else { - TLM.getInst().getLanguage().get("NOPERMISSION-INV").send(sender); - } - } + // InventorySave 模块 + else if ("inv".equalsIgnoreCase(args[0])) { + if (sender.hasPermission("taboolib.admin")) { + new TLMInvCommand(sender, args); + } else { + TLM.getInst().getLanguage().get("NOPERMISSION-INV").send(sender); + } + } - // Kit 模块 - else if ("kit".equalsIgnoreCase(args[0])) { - new TLMKitCommand(sender, args); - } else { - TLM.getInst().getLanguage().get("COMMAND-ERROR").send(sender); - } - return true; + // Kit 模块 + else if ("kit".equalsIgnoreCase(args[0])) { + new TLMKitCommand(sender, args); + } else { + TLM.getInst().getLanguage().get("COMMAND-ERROR").send(sender); + } + return true; + }).build(); } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 72b53ab..77e539f 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -12,16 +12,6 @@ DATAURL: SERVER-DATA: 'plugins/TabooLib/serverdata/' # 物品数据(来自 ItemSave 插件) ITEMDIR: 'plugins/Skript/scripts/config/item.yml' - -# 是否启用调试模式 -# 启用后将收到来自其他插件的调试信息 -DEBUG: false - -# 网络连接测试地址 -TEST-URL: 'aliyun.com' - -# 下载依赖时启用的线程数 -DOWNLOAD-POOL-SIZE: 4 # 语言文件相关设置 LOCALE: @@ -33,10 +23,29 @@ LOCALE: # 关闭可提升性能 # 如果需要开启仍然可以在语言文件中加入 papi: true USE_PAPI: false - -# 玩家列表(TAB)是否根据前缀排序 -# 启用后将会导致部分通过计分板获取玩家数据的插件出错(BedwarsRel、SkyWars) -TABLIST-SORT: false + +# 是否注入 PluginManager,关闭后可能会导致部分功能出错。 +PLUGIN-INJECTOR: + ENABLE: true + # 检测下面的插件并自动关闭注入 + DISABLE-ON-PLUGIN-EXISTS: + - LuckPerms + +# 是否在当前服务器启用交流网终端 +# 启用后将会收到大量调试信息, 不建议使用 +SERVER: false + +# 网络连接测试地址 +TEST-URL: 'aliyun.com' + +# 下载依赖时启用的线程数 +DOWNLOAD-POOL-SIZE: 4 + +# 玩家列表(TAB-API)是否根据前缀排序 +TABLIST-SORT: true + +# 玩家列表(TAB-API)是否自动清理没有成员的队伍 +TABLIST-AUTO-CLEAN-TEAM: true # 是否启用更新检测 UPDATE-CHECK: true @@ -62,6 +71,7 @@ ENABLE-UUID: false HIDE-NOTIFY: true # 数据库信息 +# 该功能在当前版本下无法使用,请勿启用 MYSQL: # 是否启用数据库 ENABLE: false @@ -77,7 +87,7 @@ MYSQL: DATABASE: 'test' # 数据表前缀 PREFIX: 'taboolib' - + # 全局变量信息 PluginData: # 检查更新间隔(单位:秒) diff --git a/src/main/resources/lang/zh_CN.yml b/src/main/resources/lang/zh_CN.yml index 2684f3a..8fc0a19 100644 --- a/src/main/resources/lang/zh_CN.yml +++ b/src/main/resources/lang/zh_CN.yml @@ -1,8 +1,11 @@ TLIB: INJECTION-SUCCESS: '注入成功' INJECTION-FAILED: - - '注入失败' - - '&c提前加载依赖于 TabooLib 的所有插件的相关功能' + - '注入失败' + - '&c提前加载依赖于 TabooLib 的所有插件的相关功能' + INJECTION-DISABLED: + - '关闭注入' + - '&c提前加载依赖于 TabooLib 的所有插件的相关功能' LOAD-FAIL-OFFLINE: - '**********************************************' - '** TabooLib-{0} 无法在您的服务器上使用' @@ -12,15 +15,15 @@ TLIB: - '**' - '** 详情查阅: https://github.com/Bkm016/TabooLib' - '**********************************************' - + DEPENDENCY: DOWNLOAD-OFFLINE: '已启用离线模式, 将不会下载第三方依赖库' DOWNLOAD-CONNECTED: ' 正在下载 {0} 大小 {1}' DOWNLOAD-PROGRESS: ' 下载速度 {0} 进度 {1}' DOWNLOAD-SUCCESS: ' 下载 {0} 完成' DOWNLOAD-FAILED: - - ' 下载 {0} 失败' - - ' 请手动下载 {1} 并重命名为 {2} 后放在 /{0}/libs 文件夹内' + - ' 下载 {0} 失败' + - ' 请手动下载 {1} 并重命名为 {2} 后放在 /{0}/libs 文件夹内' PLUGIN-AUTOLOAD-FAIL: '{0} 所依赖的插件 {1} 尝试自动加载失败,请尝试手动下载' PLUGIN-LOAD-SUCCESS: ' {0} 请求的插件 {1} 加载成功' PLUGIN-LOAD-FAIL: ' {0} 请求的插件 {1} 加载失败' @@ -28,7 +31,8 @@ DEPENDENCY: LIBRARY-LOAD-SUCCESS: ' {0} 请求的库文件 {1} 加载成功' LIBRARY-LOAD-FAIL: ' {0} 请求的库文件 {1} 加载失败' LOAD-COMPLETE: '依赖加载完成' - + LOAD-CLASSES: '&7缓存 &f{0} &7插件的 &f{1} &7个类耗时&f {2} &7毫秒.' + CONFIG: LOAD-FAIL-NO-ANNOTATION: '插件 {0} 的配置类 {1} 加载失败:没有 @Config 注解' LOAD-FAIL: '插件 {0} 的配置类 {1} 加载失败:没有 @Config 注解' @@ -40,7 +44,7 @@ CONFIG: RELOAD-SUCCESS: '插件 {0} 的配置 {1} 成功重载' RELOAD-FAIL: '插件 {0} 的配置 {1} 成功重载' LISTEN-START: '开始监听 {0} 插件的 {1} 配置文件' - + NOTIFY: ERROR-SERVER-KEY: '&4检测到本服序列号与其他服务器相同, 已重新生成!' ERROR-CONNECTION-FAIL: '&4数据库连接失败, 请检查配置是否正确!' @@ -55,7 +59,7 @@ NOTIFY: FAIL-DISABLE: - '&c插件尚未启动完成, 已跳过卸载代码' - '&c插件作者: &4坏黑' - + LOCALE: TITLE-SEND-TO-NON-PLAYER: '该语言类型只能发送给玩家:{0}' PLUGIN-NOT-FOUND: '无效的语言文件发送形式: &4{0}' @@ -65,36 +69,36 @@ LOCALE: BAR-PLUGIN-NOT-FOUND: 'TLocaleBossBar 的依赖插件 BossBarAPI 不存在' CALLER-PLUGIN-NOT-FOUND: '{0} 不是一个由插件加载的类' STATIC-CLASS-LOADER: '{0} 由静态类加载器初始化,无法获得其从属的插件' - + MISC: FIELD-COPY-FAILED: '拷贝 {0} 对象失败' FIELD-COPY-ERROR: '拷贝 {0} 对象出错:{1}' - + COOLDOWNPACK: PACK-REGISTER: '注册冷却包: {0}, 时间: {1} 秒 ({2})' PACK-REGISTER-ANONYMOUS: '注册冷却包: {0}, 时间: {1} 秒 (匿名注册)' PACK-UNREGISTER: '注销冷却包: {0} (主动注销)' PACK-UNREGISTER-AUTO: '注销冷却包: {0} (自动注销)' - + GLOBAL-DATAMANAGER: ERROR-CHECK-VARIABLE: '&4变量 &c{0} &4载入异常: &c{1}' SUCCESS-LOADED-VARIABLE: '&7从数据库中获取 &f{0} &7个变量, 耗时: &f{1} &7(ms)' - + PLAYER-DATAMANAGER: ERROR-STORAGE-SQL: '不允许在储存模式为数据库的情况下获取离线玩家数据' ERROR-PLAYER-DATA: '&4玩家 &c{0} &4的数据载入出现异常: &c{1}' SUCCESS-SAVE-DATA: '&7保存 &f{0} &7条玩家数据, 耗时: &f{1} &7(ms)' - + ENTITY-UTILS: NOTFOUND-PROTOCOLLIB: '缺少前置插件 ProtocolLib' - + FILE-UTILS: FAIL-LOAD-CONFIGURATION: '&4配置文件载入失败!, 插件: &c{0}&4, 文件: &c{1}' - + DATA-UTILS: SUCCESS-SAVE-DATA: '&7保存 &f{0} &7条插件数据, 耗时: &f{1} &7(ms)' FAIL-SAVE-FILE: '&4文件 &c{0}&4 保存失败, 原因: &c{1}' - + ITEM-UTILS: FAIL-LOAD-ITEMS: '物品库载入失败: &4{0}' FAIL-LOAD-ATTRIBUTE: '&c{0} &4不是一个有效的属性名称, 输入 &c/tlib attributes&4 查看所有属性' @@ -105,20 +109,13 @@ ITEM-UTILS: SUCCESS-LOAD-CACHES: '&7载入 &f{0} &7项缓存物品' SUCCESS-LOAD-NAMES: '&7载入 &f{0} &7项物品名称' EMPTY-ITEM: '空' - + LANGUAGE2: FAIL-NOTFOUND-FILE: '语言文件 {0} 不存在' - + TIMECYCLE: FAIL-CYCLE-EXISTS: '注册周期管理器 &8{0}&c 失败, 原因: &4名称重复' - -ANVIL-CONTAINER: - NAME-EXAMPLE: '在这里输入文本' - LORE-NORMAL: - - '' - - '&7在上方文本框内输入信息' - - '&7随后点击右侧输出物品' - + UPDATETASK: VERSION-FAIL: '&4更新记录获取失败, 请检查网络连接!' VERSION-LATEST: '&7插件已是最新版, 无需更新!' @@ -130,7 +127,7 @@ UPDATETASK: - '&7 下载地址: &fhttp://www.mcbbs.net/thread-773065-1-1.html' - '&7 开源地址: &fhttps://github.com/Bkm016/TabooLib/' - '&8####################################################' - + MYSQL-CONNECTION: FAIL-CONNECT: '&4数据库 &c{0} &4连接失败, 原因: &c{0}' FAIL-NOTFOUND-DRIVE: '&7驱动器获取失败, 无法连接到数据库' @@ -144,26 +141,26 @@ MYSQL-CONNECTION: SUCCESS-CONNECTION-CANCEL: '已停止插件 &f{0}&7 的 &f{1}&7 条数据库连接' NOTIFY-CONNECTING: '&7正在连接数据库, 地址: &f{0}' NOTIFY-CONNECTED: '&7数据库连接成功 ({0}ms)' - + MYSQL-HIKARI: CREATE-SUCCESS: '&7插件 &f{0}&7 注册新的数据库连接: &f{1}' CREATE-EXISTS: '&7插件 &f{0}&7 引用插件 &f{1}&7 注册的数据库连接' CLOSE-SUCCESS: '&7插件 &f{0} &7注册的数据库连接 &f{1} &7已被注销!' CLOSE-FAIL: '&7插件 &f{0} &7注册的数据库连接正在被 &f{1} &7个插件使用, 无法注销!' - + TABOOLIB-MODULE: SUCCESS-LOADED: '&7载入 &f{0} &7个 &fTLM &7模块' FAIL-LOADED: '&4模块载入异常: &c{0}&4, 模块: &c{1}&4, 位于: &c{2}' FAIL-RUNTIME: '&4模块运行异常: &c{0}&4, 模块: &c{1}&4, 位于: &c{2}' - + COMMANDS: GLOBAL: ONLY-PLAYER: '&8[&3&lTabooLib&8] &4控制台无法这么做' ONLY-STORAGE-SQL: '&8[&3&lTabooLib&8] &4只有启用数据库储存时才能这么做' INTERNAL: TYPE-ERROR: '&8[&3&lTabooLib&8] &7指令 &f{0} &7只能由 &f{1} &7执行' - TYPE-PLAYER: 玩家 - TYPE-CONSOLE: 控制台 + TYPE-PLAYER: '玩家' + TYPE-CONSOLE: '控制台' ERROR-USAGE: - '&8[&3&lTabooLib&8] &7指令 &f{0} &7参数不足' - '&8[&3&lTabooLib&8] &7正确用法:' @@ -240,10 +237,9 @@ COMMANDS: DESCRIPTION: '&4更新插件 &8(谨防非正规途径的插件获取方式)' UPDATE-NOT-FOUND: '&8[&3&lTabooLib&8] &7插件已是最新版, 无需更新!' UPDATE-NOT-SUPPORT: '&8[&3&lTabooLib&8] &4您的服务器不支持在线更新!' + UPDATE-SUCCESS: '&8[&3&lTabooLib&8] &7最新版下载完成, 服务器即将重启!' FILE-NOT-FOUND: '&8[&3&lTabooLib&8] &4尚未寻找到插件文件' PLAYER-ONLINE: '&8[&3&lTabooLib&8] &4服务器有玩家在线无法更新插件.' - UPDATE-START: '&8[&3&lTabooLib&8] &7开始下载:&f {0}' - UPDATE-SUCCESS: '&8[&3&lTabooLib&8] &7最新版下载完成, 服务器即将重启!' PLAYERTAG: DESCRIPTION: DISPLAY: '设置玩家展示名称' @@ -385,7 +381,7 @@ COMMANDS: hover: '&f点击复制' suggest: '{0}' FOOT: - - '' + - '' ENCHANTS: DESCRIPTION: '查看所有附魔' HEAD: @@ -430,7 +426,7 @@ COMMANDS: hover: '&f点击复制' suggest: '{0}' FOOT: - - '' + - '' SLOTS: DESCRIPTION: '查看所有部位' HEAD: @@ -473,7 +469,7 @@ COMMANDS: COMMAND-TITLE: '&e&l----- &6&lTabooLibPlugin Commands &e&l-----' LIST: DESCRIPTION: '列出插件' - LIST-PLUGIN: + LIST-PLUGIN: - '&8[&3&lTabooLib&8] &7插件总数: &f{0}' - '&8[&3&lTabooLib&8] &7插件列表: &f{1}' INFO: @@ -533,7 +529,13 @@ COMMANDS: 1: '内容' INVALID-PLAYER-OFFLINE: '&8[&3&lTabooLib&8] &4玩家 &c{0} &4不在线.' COMMAND: - DESCRIPTION: '使目标输入执行指令' + DESCRIPTION: '使目标执行指令' + ARGUMENTS: + 0: '目标' + 1: '内容' + INVALID-TARGET-NOT-FOUND: '&8[&3&lTabooLib&8] &4目标 &c{0} &4不存在.' + COMMAND-AS-OP: + DESCRIPTION: '使目标以管理员身份执行指令' ARGUMENTS: 0: '目标' 1: '内容' @@ -562,13 +564,20 @@ COMMANDS: DATABASE: CONNECTION-ESTABLISHED: '成功连接到 {0} 数据库,连接池大小 {1}' CONNECTION-ERROR: '连接到数据库错误:{0}' - + COMMUNICATION: FAILED-LOAD-SETTINGS: '§8[§3§lTabooLibClient§8] &4配置载入失败: {0}' FAILED-CONNECT-SERVER: '§8[§3§lTabooLibClient§8] &4本地通讯网络连接失败.' FAILED-CONNECT-CLIENT: '§8[§3§lTabooLibClient§8] &4本地通讯网络连接出错: {0}' FAILED-READING-PACKET: '§8[§3§lTabooLibClient§8] &4本地通讯网络数据包读取失败: {0}' SUCCESS-CONNECTED: '§8[§3§lTabooLibClient§8] &7本地通讯网络连接成功.' - CLIENT-JOINED: '§8[§3§lTabooLibClient§8] &7服务器 &flocalhost:{0} &7加入本地通讯网络.' - CLIENT-QUITED: '§8[§3§lTabooLibClient§8] &7服务器 &flocalhost:{0} &7退出本地通讯网络.' - PACKET-MESSAGE: '§8[§3§lTabooLibClient§8] &7服务器 &flocalhost:{0} &7发送信息: &f{1}' \ No newline at end of file + CLIENT-JOINED: '§8[§3§lTabooLibClient§8] &7服务器 &f{0} &7加入本地通讯网络.' + CLIENT-QUITED: '§8[§3§lTabooLibClient§8] &7服务器 &f{0} &7退出本地通讯网络.' + PACKET-MESSAGE: '§8[§3§lTabooLibClient§8] &7服务器 &f{0} &7发送信息: &f{1}' + PACKET-COMMAND: '§8[§3§lTabooLibClient§8] &7服务器 &f{0} &7运行命令: &f{1}' + +UTIL: + DOWNLOAD-CONNECTED: '开始下载文件 {0} 大小 {1}' + DOWNLOAD-PROGRESS: ' 下载速度 {0} 进度 {1}' + DOWNLOAD-SUCCESS: '下载 {0} 完成!' + DOWNLOAD-FAILED: '下载 {0} 失败!' \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c3521d8..611eebb 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,12 +4,4 @@ version: ${project.version} author: [lzzelAliz, 坏黑] depend: [Vault] -softdepend: [PlaceholderAPI, Skript, MassiveLag] - -# 两个命令删除预定 -commands: - language2: - aliases: [lang2] - permission: taboolib.admin - taboolibrarymodule: - aliases: [tlm] \ No newline at end of file +softdepend: [PlaceholderAPI, Skript, MassiveLag] \ No newline at end of file