From dbf319addbfab3bcd17fbbc9ba0b0808a3210429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9D=8F=E9=BB=91?= Date: Fri, 14 Sep 2018 20:39:49 +0800 Subject: [PATCH] + update --- pom.xml | 2 +- src/main/java/com/ilummc/tlib/TLib.java | 44 +++-- .../me/skymc/taboolib/TabooLibLoader.java | 1 - .../me/skymc/taboolib/bstats/Metrics.java | 171 +++++++++--------- .../listener/ListenerPluginDisable.java | 11 +- .../skymc/taboolib/mysql/builder/SQLHost.java | 23 ++- .../taboolib/mysql/builder/SQLTable.java | 6 +- .../taboolib/mysql/hikari/HikariHandler.java | 14 ++ .../me/skymc/taboolib/plugin/PluginUtils.java | 17 +- .../me/skymc/taboolib/string/ArrayUtils.java | 26 ++- src/main/resources/config.yml | 13 +- src/main/resources/lang/zh_CN.yml | 57 +++--- 12 files changed, 231 insertions(+), 154 deletions(-) diff --git a/pom.xml b/pom.xml index c45afe4..7a424a0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.skymc TabooLib - 4.27 + 4.28 UTF-8 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/me/skymc/taboolib/TabooLibLoader.java b/src/main/java/me/skymc/taboolib/TabooLibLoader.java index 108a652..4348b67 100644 --- a/src/main/java/me/skymc/taboolib/TabooLibLoader.java +++ b/src/main/java/me/skymc/taboolib/TabooLibLoader.java @@ -165,6 +165,5 @@ public class TabooLibLoader implements Listener { 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)))); } } 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/listener/ListenerPluginDisable.java b/src/main/java/me/skymc/taboolib/listener/ListenerPluginDisable.java index c1b101b..ef90a14 100644 --- a/src/main/java/me/skymc/taboolib/listener/ListenerPluginDisable.java +++ b/src/main/java/me/skymc/taboolib/listener/ListenerPluginDisable.java @@ -2,8 +2,8 @@ package me.skymc.taboolib.listener; import com.ilummc.tlib.resources.TLocale; import me.skymc.taboolib.Main; -import me.skymc.taboolib.message.MsgUtils; 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; @@ -12,6 +12,7 @@ import org.bukkit.event.server.PluginDisableEvent; import org.bukkit.scheduler.BukkitRunnable; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; @TListener @@ -21,12 +22,14 @@ public class ListenerPluginDisable implements Listener { public void disable(PluginDisableEvent e) { // 注销时间周期 TimeCycleManager.cancel(e.getPlugin()); + // 注销数据库连接 + 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); } } @@ -37,7 +40,7 @@ public class ListenerPluginDisable implements Listener { @Override public void run() { int i = 0; - for (MySQLConnection conn : conns) { + for (MySQLConnection conn : connection) { conn.setFallReconnection(false); conn.closeConnection(); i++; 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 961985d..a0195bb 100644 --- a/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java +++ b/src/main/java/me/skymc/taboolib/mysql/builder/SQLHost.java @@ -18,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() { @@ -56,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); } @@ -73,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 @@ -94,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 5cdb888..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; } 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 0e5f900..a422313 100644 --- a/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java +++ b/src/main/java/me/skymc/taboolib/mysql/hikari/HikariHandler.java @@ -89,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/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/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/resources/config.yml b/src/main/resources/config.yml index 3fad166..01fa46a 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -12,7 +12,7 @@ DATAURL: SERVER-DATA: 'plugins/TabooLib/serverdata/' # 物品数据(来自 ItemSave 插件) ITEMDIR: 'plugins/Skript/scripts/config/item.yml' - + # 语言文件相关设置 LOCALE: # 加载语言文件的顺序 @@ -23,7 +23,14 @@ LOCALE: # 关闭可提升性能 # 如果需要开启仍然可以在语言文件中加入 papi: true USE_PAPI: false - + +# 是否注入 PluginManager,关闭后可能会导致部分功能出错。 +PLUGIN-INJECTOR: + ENABLE: true + # 检测下面的插件并自动关闭注入 + DISABLE-ON-PLUGIN-EXISTS: + - LuckPerms + # 是否启用调试模式 # 启用后将收到来自其他插件的调试信息 DEBUG: false @@ -83,7 +90,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 2a157ca..6fc3c0b 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} 加载失败' @@ -29,7 +32,7 @@ DEPENDENCY: 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 注解' @@ -41,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数据库连接失败, 请检查配置是否正确!' @@ -56,7 +59,7 @@ NOTIFY: FAIL-DISABLE: - '&c插件尚未启动完成, 已跳过卸载代码' - '&c插件作者: &4坏黑' - + LOCALE: TITLE-SEND-TO-NON-PLAYER: '该语言类型只能发送给玩家:{0}' PLUGIN-NOT-FOUND: '无效的语言文件发送形式: &4{0}' @@ -66,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 查看所有属性' @@ -106,13 +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名称重复' - + UPDATETASK: VERSION-FAIL: '&4更新记录获取失败, 请检查网络连接!' VERSION-LATEST: '&7插件已是最新版, 无需更新!' @@ -124,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驱动器获取失败, 无法连接到数据库' @@ -138,18 +141,18 @@ 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控制台无法这么做' @@ -379,7 +382,7 @@ COMMANDS: hover: '&f点击复制' suggest: '{0}' FOOT: - - '' + - '' ENCHANTS: DESCRIPTION: '查看所有附魔' HEAD: @@ -424,7 +427,7 @@ COMMANDS: hover: '&f点击复制' suggest: '{0}' FOOT: - - '' + - '' SLOTS: DESCRIPTION: '查看所有部位' HEAD: @@ -467,7 +470,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: @@ -562,7 +565,7 @@ 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本地通讯网络连接失败.'