From 300dc0d6071d6f76b3f070c314b580754f9ec1d3 Mon Sep 17 00:00:00 2001 From: MiaoWoo Date: Thu, 24 Oct 2019 17:20:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=A2=E9=98=85=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E4=B8=BAtencent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MiaoWoo --- pom.xml | 2 +- .../yumc/YumCore/commands/CommandParse.java | 67 +- .../pw/yumc/YumCore/statistic/Statistics.java | 609 +++++++------- .../pw/yumc/YumCore/update/SubscribeTask.java | 795 +++++++++--------- 4 files changed, 741 insertions(+), 732 deletions(-) diff --git a/pom.xml b/pom.xml index e995165..a89a665 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 pw.yumc YumCore - 1.8.8 + 1.8.9 ${project.artifactId} diff --git a/src/main/java/pw/yumc/YumCore/commands/CommandParse.java b/src/main/java/pw/yumc/YumCore/commands/CommandParse.java index 5517ea2..b3128f8 100644 --- a/src/main/java/pw/yumc/YumCore/commands/CommandParse.java +++ b/src/main/java/pw/yumc/YumCore/commands/CommandParse.java @@ -25,10 +25,10 @@ import pw.yumc.YumCore.commands.exception.ParseException; * @since 2016年10月5日 下午4:02:04 */ public class CommandParse { - private static Map allparses = new HashMap<>(); + private static Map allParse = new HashMap<>(); private static Map primitiveMap = new HashMap<>(); private boolean isMain; - private List parses = new LinkedList<>(); + private List pars = new LinkedList<>(); static { register(File.class, FileParse.class); @@ -44,7 +44,7 @@ public class CommandParse { primitiveMap.put("double", Double.class); } - public CommandParse(Class[] classes, Annotation[][] annons, boolean isMain) { + private CommandParse(Class[] classes, Annotation[][] annons, boolean isMain) { this.isMain = isMain; // 第一个参数实现了CommandSender忽略 for (int i = 1; i < classes.length; i++) { @@ -54,22 +54,22 @@ public class CommandParse { clazz = primitiveMap.get(clazz.getName()); } Annotation[] annotations = annons[i]; - Parse parse = null; - if (allparses.containsKey(clazz)) { + BaseParse baseParse = null; + if (allParse.containsKey(clazz)) { try { - parse = (Parse) allparses.get(clazz).newInstance(); + baseParse = (BaseParse) allParse.get(clazz).newInstance(); } catch (InstantiationException | IllegalAccessException | NullPointerException ignored) { } } else { try { - parse = new ValueOfParse(clazz, clazz.getDeclaredMethod("valueOf", String.class)); + baseParse = new ValueOfParse(clazz, clazz.getDeclaredMethod("valueOf", String.class)); } catch (NoSuchMethodException ignored) { } } - if (parse == null) { throw new ParseException(String.format("存在无法解析的参数类型 %s", clazz.getName())); } - this.parses.add(parse.parseAnnotation(annotations).handleAttrs()); + if (baseParse == null) { throw new ParseException(String.format("存在无法解析的参数类型 %s", clazz.getName())); } + this.pars.add(baseParse.parseAnnotation(annotations).handleAttrs()); } - Log.d("命令解析器 %s", Log.getSimpleNames(parses.toArray())); + Log.d("命令解析器 %s", Log.getSimpleNames(pars.toArray())); } public static CommandParse get(Method method) { @@ -81,34 +81,32 @@ public class CommandParse { * * @param arr * 数组 - * @param split - * 分割符 * @return 字符串 */ - public static String join(Object[] arr, String split) { + private static String join(Object[] arr) { StringBuilder str = new StringBuilder(); for (Object s : arr) { str.append(s.toString()); - str.append(split); + str.append(" "); } - return str.length() > split.length() ? str.toString().substring(0, str.length() - split.length()) : str.toString(); + return str.length() > " ".length() ? str.toString().substring(0, str.length() - " ".length()) : str.toString(); } public static void register(Class clazz, Class parse) { - allparses.put(clazz, parse); + allParse.put(clazz, parse); } public Object[] parse(CommandSender sender, String label, String[] args) { List pobjs = new LinkedList<>(); pobjs.add(sender); - for (int i = 0; i < parses.size(); i++) { + for (int i = 0; i < pars.size(); i++) { try { - Parse p = parses.get(i); + BaseParse p = pars.get(i); String param = i < args.length ? args[i] : null; param = param == null ? p.getDefault(sender) : param; // 参数大于解析器 并且为最后一个参数 - if (i + 1 == parses.size() && args.length >= parses.size()) { - param = join(Arrays.copyOfRange(args, i, args.length), " "); + if (i + 1 == pars.size() && args.length >= pars.size()) { + param = join(Arrays.copyOfRange(args, i, args.length)); } // 尝试让解析器解析Null参数 try { pobjs.add(p.parse(sender, param)); } catch (NullPointerException npe) { pobjs.add(null); } @@ -121,7 +119,7 @@ public class CommandParse { return pobjs.toArray(); } - public static abstract class Parse { + public static abstract class BaseParse { protected Map attrs = new HashMap<>(); protected String def; protected int max = Integer.MAX_VALUE; @@ -131,9 +129,20 @@ public class CommandParse { return def; } + /** + * 解析参数 + * + * @param sender + * 发送者 + * @param arg + * 命令参数 + * @return 解析后的数据 + * @throws ParseException + * 解析异常 + */ public abstract RT parse(CommandSender sender, String arg) throws ParseException; - public Parse parseAnnotation(Annotation[] annotations) { + public BaseParse parseAnnotation(Annotation[] annotations) { for (Annotation annotation : annotations) { if (annotation.annotationType() == Option.class) { String value = ((Option) annotation).value(); @@ -153,7 +162,7 @@ public class CommandParse { return this; } - public Parse handleAttrs() { + public BaseParse handleAttrs() { if (attrs.containsKey("def")) { def = String.valueOf(attrs.get("def")); } @@ -179,7 +188,7 @@ public class CommandParse { } } - public static class ValueOfParse extends Parse { + public static class ValueOfParse extends BaseParse { private Class eType; private Enum[] eList; private Method method; @@ -218,7 +227,7 @@ public class CommandParse { } } - public static class FileParse extends Parse { + public static class FileParse extends BaseParse { @Override public File parse(CommandSender sender, String arg) throws ParseException { File file = new File(arg); @@ -227,7 +236,7 @@ public class CommandParse { } } - public static class PlayerParse extends Parse { + public static class PlayerParse extends BaseParse { boolean sender = false; boolean check = false; @@ -239,7 +248,7 @@ public class CommandParse { } @Override - public Parse handleAttrs() { + public BaseParse handleAttrs() { super.handleAttrs(); sender = attrs.containsKey("sender"); check = attrs.containsKey("check"); @@ -252,7 +261,7 @@ public class CommandParse { } } - public static class StringParse extends Parse { + public static class StringParse extends BaseParse { List options; @Override @@ -263,7 +272,7 @@ public class CommandParse { } @Override - public Parse handleAttrs() { + public BaseParse handleAttrs() { super.handleAttrs(); if (attrs.containsKey("option")) { options = Arrays.asList(attrs.get("option").split(",")); diff --git a/src/main/java/pw/yumc/YumCore/statistic/Statistics.java b/src/main/java/pw/yumc/YumCore/statistic/Statistics.java index 5366a0c..83d9fd2 100644 --- a/src/main/java/pw/yumc/YumCore/statistic/Statistics.java +++ b/src/main/java/pw/yumc/YumCore/statistic/Statistics.java @@ -1,305 +1,306 @@ -/* - * Copyright 2011-2015 喵♂呜. All rights reserved. - */ -package pw.yumc.YumCore.statistic; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.scheduler.BukkitTask; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; - -/** - * Yum数据中心 数据统计类 - * - * @since 2015年12月14日 下午1:36:42 - * @author 喵♂呜 - */ -public class Statistics { - /** - * 统计系统版本 - */ - private static int REVISION = 10; - - /** - * 统计插件基础配置文件 - */ - private static File configfile = new File(String.format("plugins%1$sPluginHelper%1$sconfig.yml", File.separatorChar)); - - /** - * UTF-8编码 - */ - private static Charset UTF_8 = Charset.forName("UTF-8"); - - /** - * getOnlinePlayers方法 - */ - private static Method getOnlinePlayers; - - /** - * 插件实体 - */ - private static Plugin plugin; - - static { - try { - getOnlinePlayers = Bukkit.class.getDeclaredMethod("getOnlinePlayers"); - if (getOnlinePlayers.getReturnType() != Player[].class) { - for (Method method : Bukkit.class.getDeclaredMethods()) { - if (method.getReturnType() == Player[].class && method.getName().endsWith("getOnlinePlayers")) { - getOnlinePlayers = method; - } - } - } - Object pluginClassLoader = Statistics.class.getClassLoader(); - Field field = pluginClassLoader.getClass().getDeclaredField("plugin"); - field.setAccessible(true); - plugin = (JavaPlugin) field.get(pluginClassLoader); - } catch (NoSuchMethodException | SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) { - } - } - - /** - * 统计插件基础配置文件 - */ - private YamlConfiguration config; - - /** - * 调试模式 - */ - private boolean debug; - - /** - * 唯一服务器编码 - */ - private String guid; - - /** - * 线程任务 - */ - private volatile BukkitTask task = null; - - /** - * 统计线程 - */ - private volatile StatisticsTimer timer = null; - - /** - * 插件使用数据统计 - */ - public Statistics() { - try { - if (!configfile.exists()) { - configfile.getParentFile().mkdirs(); - configfile.createNewFile(); - } - config = YamlConfiguration.loadConfiguration(configfile); - initFile(config); - } catch (IOException ignored) { - } - this.guid = config.getString("guid"); - this.debug = config.getBoolean("d", false); - start(); - } - - /** - * 向指定 URL 发送POST方法的请求 - * - * @param url - * 发送请求的 URL - * @param param - * 请求参数 - * @return 所代表远程资源的响应结果 - * @throws IOException - * IO异常 - */ - public static String postData(String url, String param) throws IOException { - PrintWriter out; - String result = ""; - URL realUrl = new URL(url); - // 打开和URL之间的连接 - URLConnection conn = realUrl.openConnection(); - // 设置通用的请求属性 - conn.setRequestProperty("Accept", "*/*"); - conn.setRequestProperty("Connection", "Keep-Alive"); - conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"); - // 设置超时时间 10秒 - conn.setReadTimeout(10000); - // 发送POST请求必须设置如下两行 - conn.setDoOutput(true); - conn.setDoInput(true); - // 获取URLConnection对象对应的输出流 - out = new PrintWriter(conn.getOutputStream()); - // 发送请求参数 - out.write(param); - // flush输出流的缓冲 - out.flush(); - String response; - BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), UTF_8)); - while ((response = reader.readLine()) != null) { - result += response; - } - reader.close(); - out.close(); - return result; - } - - /** - * 初始化配置文件 - * - * @param config - * 配置文件 - * @throws IOException - * IO异常 - */ - private static void initFile(YamlConfiguration config) throws IOException { - if (config.getString("guid") == null) { - config.options().header("YUMC数据中心 http://www.yumc.pw 收集的数据仅用于统计插件使用情况").copyDefaults(true); - config.set("guid", UUID.randomUUID().toString()); - config.set("d", false); - config.save(configfile); - } - if (!config.contains("YumAccount")) { - config.set("YumAccount.username", "Username Not Set"); - config.set("YumAccount.password", "Password NotSet"); - config.save(configfile); - } - if (!config.contains("TellrawManualHandle")) { - config.set("TellrawManualHandle", false); - config.save(configfile); - } - } - - /** - * 简化输出 - * - * @param msg - * 输出对象 - */ - public void print(String msg) { - if (debug) { - System.out.println("[Statistics] " + msg); - } - } - - /** - * 开启数据统计 这将会在异步执行 - * - * @return 是否运行成功. - */ - public boolean start() { - if (task != null || !plugin.isEnabled()) { return true; } - timer = new StatisticsTimer(); - // 开启TPS统计线程 - Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, timer, 0, 20); - // 开启发送数据线程 - task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, () -> { - try { - postPlugin(); - } catch (Throwable e) { - if (debug) { - e.printStackTrace(); - } - } - }, 50, 25 * 1200); - return true; - } - - /** - * 获得在线玩家人数 - * - * @return 在线玩家人数 - */ - private int getOnlinePlayerNumber() { - try { - return ((Player[]) getOnlinePlayers.invoke(Bukkit.getServer())).length; - } catch (Exception ex) { - return Bukkit.getOnlinePlayers().size(); - } - } - - /** - * 发送服务器数据到统计网页 - */ - private void postPlugin() throws IOException { - // 服务器数据获取 - PluginDescriptionFile description = plugin.getDescription(); - String pluginname = description.getName(); - String tmposarch = System.getProperty("os.arch"); - - Map data = new HashMap<>(); - data.put("guid", guid); - data.put("server_version", Bukkit.getVersion()); - data.put("server_port", Bukkit.getServer().getPort()); - data.put("server_tps", timer.getAverageTPS()); - data.put("plugin_version", description.getVersion()); - data.put("players_online", getOnlinePlayerNumber()); - data.put("os_name", System.getProperty("os.name")); - data.put("os_arch", tmposarch.equalsIgnoreCase("amd64") ? "x86_64" : tmposarch); - data.put("os_version", System.getProperty("os.version")); - data.put("os_usemem", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024); - data.put("os_cores", Runtime.getRuntime().availableProcessors()); - data.put("auth_mode", Bukkit.getServer().getOnlineMode() ? 1 : 0); - data.put("java_version", System.getProperty("java.version")); - - String jsondata = "Info=" + JSONValue.toJSONString(data); - - String url = String.format("http://api.yumc.pw/I/P/S/V/%s/P/%s", REVISION, URLEncoder.encode(pluginname, "UTF-8")); - print("Plugin: " + pluginname + " Send Data To CityCraft Data Center"); - print("Address: " + url); - print("Data: " + jsondata); - // 发送数据 - JSONObject result = (JSONObject) JSONValue.parse(postData(url, jsondata)); - print("Plugin: " + pluginname + " Recover Data From CityCraft Data Center: " + result.get("info")); - } - - public class StatisticsTimer implements Runnable { - private LinkedList history = new LinkedList<>(); - private transient long lastPoll = System.nanoTime(); - - /** - * @return 获得TPS - */ - public double getAverageTPS() { - double avg = 0.0D; - for (Double f : history) { - avg += f; - } - return avg / history.size(); - } - - @Override - public void run() { - long startTime = System.nanoTime(); - long timeSpent = (startTime - lastPoll) / 1000; - if (history.size() > 10) { - history.removeFirst(); - } - double ttps = 2.0E7D / (timeSpent == 0 ? 1 : timeSpent); - if (ttps <= 21.0D) { - history.add(ttps); - } - lastPoll = startTime; - } - } +/* + * Copyright 2011-2015 喵♂呜. All rights reserved. + */ +package pw.yumc.YumCore.statistic; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; + +/** + * Yum数据中心 数据统计类 + * + * @since 2015年12月14日 下午1:36:42 + * @author 喵♂呜 + */ +public class Statistics { + /** + * 统计系统版本 + */ + private static int REVISION = 10; + + /** + * 统计插件基础配置文件 + */ + private static File configfile = new File(String.format("plugins%1$sPluginHelper%1$sconfig.yml", File.separatorChar)); + + /** + * UTF-8编码 + */ + private static Charset UTF_8 = StandardCharsets.UTF_8; + + /** + * getOnlinePlayers方法 + */ + private static Method getOnlinePlayers; + + /** + * 插件实体 + */ + private static Plugin plugin; + + static { + try { + getOnlinePlayers = Bukkit.class.getDeclaredMethod("getOnlinePlayers"); + if (getOnlinePlayers.getReturnType() != Player[].class) { + for (Method method : Bukkit.class.getDeclaredMethods()) { + if (method.getReturnType() == Player[].class && method.getName().endsWith("getOnlinePlayers")) { + getOnlinePlayers = method; + } + } + } + Object pluginClassLoader = Statistics.class.getClassLoader(); + Field field = pluginClassLoader.getClass().getDeclaredField("plugin"); + field.setAccessible(true); + plugin = (JavaPlugin) field.get(pluginClassLoader); + } catch (NoSuchMethodException | SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) { + } + } + + /** + * 统计插件基础配置文件 + */ + private YamlConfiguration config; + + /** + * 调试模式 + */ + private boolean debug; + + /** + * 唯一服务器编码 + */ + private String guid; + + /** + * 线程任务 + */ + private volatile BukkitTask task = null; + + /** + * 统计线程 + */ + private volatile StatisticsTimer timer = null; + + /** + * 插件使用数据统计 + */ + public Statistics() { + try { + if (!configfile.exists()) { + configfile.getParentFile().mkdirs(); + configfile.createNewFile(); + } + config = YamlConfiguration.loadConfiguration(configfile); + initFile(config); + } catch (IOException ignored) { + } + this.guid = config.getString("guid"); + this.debug = config.getBoolean("d", false); + start(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数 + * @return 所代表远程资源的响应结果 + * @throws IOException + * IO异常 + */ + public static String postData(String url, String param) throws IOException { + PrintWriter out; + String result = ""; + URL realUrl = new URL(url); + // 打开和URL之间的连接 + URLConnection conn = realUrl.openConnection(); + // 设置通用的请求属性 + conn.setRequestProperty("Accept", "*/*"); + conn.setRequestProperty("Connection", "Keep-Alive"); + conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"); + // 设置超时时间 10秒 + conn.setReadTimeout(10000); + // 发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + // 获取URLConnection对象对应的输出流 + out = new PrintWriter(conn.getOutputStream()); + // 发送请求参数 + out.write(param); + // flush输出流的缓冲 + out.flush(); + String response; + BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), UTF_8)); + while ((response = reader.readLine()) != null) { + result += response; + } + reader.close(); + out.close(); + return result; + } + + /** + * 初始化配置文件 + * + * @param config + * 配置文件 + * @throws IOException + * IO异常 + */ + private static void initFile(YamlConfiguration config) throws IOException { + if (config.getString("guid") == null) { + config.options().header("YUMC数据中心 http://www.yumc.pw 收集的数据仅用于统计插件使用情况").copyDefaults(true); + config.set("guid", UUID.randomUUID().toString()); + config.set("d", false); + config.save(configfile); + } + if (!config.contains("YumAccount")) { + config.set("YumAccount.username", "Username Not Set"); + config.set("YumAccount.password", "Password NotSet"); + config.save(configfile); + } + if (!config.contains("TellrawManualHandle")) { + config.set("TellrawManualHandle", false); + config.save(configfile); + } + } + + /** + * 简化输出 + * + * @param msg + * 输出对象 + */ + public void print(String msg) { + if (debug) { + System.out.println("[Statistics] " + msg); + } + } + + /** + * 开启数据统计 这将会在异步执行 + * + * @return 是否运行成功. + */ + public boolean start() { + if (task != null || !plugin.isEnabled()) { return true; } + timer = new StatisticsTimer(); + // 开启TPS统计线程 + Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, timer, 0, 20); + // 开启发送数据线程 + task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, () -> { + try { + postPlugin(); + } catch (Throwable e) { + if (debug) { + e.printStackTrace(); + } + } + }, 50, 25 * 1200); + return true; + } + + /** + * 获得在线玩家人数 + * + * @return 在线玩家人数 + */ + private int getOnlinePlayerNumber() { + try { + return ((Player[]) getOnlinePlayers.invoke(Bukkit.getServer())).length; + } catch (Exception ex) { + return Bukkit.getOnlinePlayers().size(); + } + } + + /** + * 发送服务器数据到统计网页 + */ + private void postPlugin() throws IOException { + // 服务器数据获取 + PluginDescriptionFile description = plugin.getDescription(); + String pluginname = description.getName(); + String tmposarch = System.getProperty("os.arch"); + + Map data = new HashMap<>(); + data.put("guid", guid); + data.put("server_version", Bukkit.getVersion()); + data.put("server_port", Bukkit.getServer().getPort()); + data.put("server_tps", timer.getAverageTPS()); + data.put("plugin_version", description.getVersion()); + data.put("players_online", getOnlinePlayerNumber()); + data.put("os_name", System.getProperty("os.name")); + data.put("os_arch", "amd64".equalsIgnoreCase(tmposarch) ? "x86_64" : tmposarch); + data.put("os_version", System.getProperty("os.version")); + data.put("os_usemem", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024); + data.put("os_cores", Runtime.getRuntime().availableProcessors()); + data.put("auth_mode", Bukkit.getServer().getOnlineMode() ? 1 : 0); + data.put("java_version", System.getProperty("java.version")); + + String jsondata = "Info=" + JSONValue.toJSONString(data); + + String url = String.format("http://api.yumc.pw/I/P/S/V/%s/P/%s", REVISION, URLEncoder.encode(pluginname, "UTF-8")); + print("Plugin: " + pluginname + " Send Data To CityCraft Data Center"); + print("Address: " + url); + print("Data: " + jsondata); + // 发送数据 + JSONObject result = (JSONObject) JSONValue.parse(postData(url, jsondata)); + print("Plugin: " + pluginname + " Recover Data From CityCraft Data Center: " + result.get("info")); + } + + public class StatisticsTimer implements Runnable { + private LinkedList history = new LinkedList<>(); + private transient long lastPoll = System.nanoTime(); + + /** + * @return 获得TPS + */ + public double getAverageTPS() { + double avg = 0.0D; + for (Double f : history) { + avg += f; + } + return avg / history.size(); + } + + @Override + public void run() { + long startTime = System.nanoTime(); + long timeSpent = (startTime - lastPoll) / 1000; + if (history.size() > 10) { + history.removeFirst(); + } + double ttps = 2.0E7D / (timeSpent == 0 ? 1 : timeSpent); + if (ttps <= 21.0D) { + history.add(ttps); + } + lastPoll = startTime; + } + } } \ No newline at end of file diff --git a/src/main/java/pw/yumc/YumCore/update/SubscribeTask.java b/src/main/java/pw/yumc/YumCore/update/SubscribeTask.java index 1cbe30c..5568716 100644 --- a/src/main/java/pw/yumc/YumCore/update/SubscribeTask.java +++ b/src/main/java/pw/yumc/YumCore/update/SubscribeTask.java @@ -1,398 +1,397 @@ -package pw.yumc.YumCore.update; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLDecoder; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.plugin.java.JavaPlugin; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import pw.yumc.YumCore.bukkit.Log; -import pw.yumc.YumCore.bukkit.P; -import pw.yumc.YumCore.tellraw.Tellraw; -import pw.yumc.YumCore.text.Encrypt; - -/** - * 自动更新程序 - * - * @author 喵♂呜 - * @since 2016年8月3日 上午11:20:21 - */ -public class SubscribeTask implements Runnable, Listener { - /** - * 插件实例 - */ - private static JavaPlugin instance = P.instance; - - /** - * 检查间隔 - */ - private static int interval = 25; - - private UpdateType updateType; - /** - * 更新文件 - */ - private UpdateFile updateFile; - /** - * 版本信息 - */ - private VersionInfo versionInfo; - - /** - * 自动更新 - */ - public SubscribeTask() { - this(UpdateType.DIRECT); - } - - /** - * 自动更新 - * - * @param type - * 是否为Maven - */ - public SubscribeTask(UpdateType type) { - this(false, type); - } - - /** - * 自动更新 - * - * @param isSecret - * 是否为私有 - * @param type - * 更新类型 - */ - public SubscribeTask(boolean isSecret, UpdateType type) { - this("master", isSecret, type); - } - - /** - * 自动更新 - * - * @param branch - * 更新分支 - * @param isSecret - * 是否为私有 - * @param type - * 更新类型 - */ - public SubscribeTask(String branch, boolean isSecret, UpdateType type) { - Log.d("订阅更新 分支 %s 是否加密 %s 更新类型 %s", branch, isSecret, type.name()); - updateFile = new UpdateFile(instance); - versionInfo = new VersionInfo(instance, branch, isSecret); - updateType = type; - if (instance.isEnabled()) { - Bukkit.getPluginManager().registerEvents(this, instance); - Bukkit.getScheduler().runTaskTimerAsynchronously(instance, this, 0, interval * 1200); - } - } - - @EventHandler - public void onJoin(PlayerJoinEvent e) { - final Player player = e.getPlayer(); - if (player.isOp() && updateFile.isUpdated()) { - Bukkit.getScheduler().runTaskLater(instance, () -> versionInfo.notify(player), 10); - } - } - - @Override - public void run() { - update(); - } - - public void update() { - try { - versionInfo.update(); - String result = versionInfo.getNewVersion(); - if (result != null) { - if (updateFile.target.exists()) { - try { - PluginDescriptionFile desc = instance.getPluginLoader().getPluginDescription(updateFile.target); - if (!versionInfo.needUpdate(result, desc.getVersion().split("-")[0])) { return; } - updateFile.target.delete(); - } catch (Exception e) { - Log.d(e); - } - } - updateFile.update(updateType.getDownloadUrl(instance, result)); - Log.d(Encrypt.decode("嘊⚲哀嘖⚶哅嘣⚩咖嗕♧哏嗕⚸咁嘨♢咰嘤♢哒嗚⚵呼嗣♰咊"), instance.getName(), versionInfo.getVersion(), result); - versionInfo.notify(Bukkit.getConsoleSender()); - } - } catch (Exception e) { - Log.d(e); - } - } - - public enum UpdateType { - /** - * 下载直连 - */ - DIRECT(Encrypt.decode("嘝⚶哐嘥♼咋嗤⚥哅嗣⚻哑嘢⚥咊嘥⚹咋嘟⚱咾嗤♧咍嗙⚵咋嘡⚣哏嘩⚕哑嘘⚥品嘨⚵哂嘪⚮咞嘪⚫哈嘙♱咽嘧⚶哅嘛⚣咿嘩♱哐嘖⚴哃嘚⚶咋嗚♳咀嘨♰哆嘖⚴")), - // "http://ci.yumc.pw/job/%1$s/lastSuccessfulBuild/artifact/target/%1$s.jar"; - /** - * Maven下载 - */ - MAVEN(Encrypt.decode("嘝⚶哐嘥♼咋嗤⚥哅嗣⚻哑嘢⚥咊嘥⚹咋嘥⚮哑嘜⚫哊嗤⚴品嘥⚱哏嘞⚶哋嘧⚻咋嘚⚸品嘧⚻哐嘝⚫哊嘜♱咁嗦♦哏嗤♧咎嗙⚵咋嗚♵咀嘨♯咁嗧♦哏嗣⚬咽嘧")), - // "http://ci.yumc.pw/plugin/repository/everything/%1$s/%2$s/%3$s-%2$s.jar"; - /** - * 工作区下载 - */ - WS(Encrypt.decode("嘝⚶哐嘥♼咋嗤⚥哅嗣⚻哑嘢⚥咊嘥⚹咋嘟⚱咾嗤♧咍嗙⚵咋嘬⚵咋嘩⚣哎嘜⚧哐嗤♧咍嗙⚵咊嘟⚣哎")); - // "http://ci.yumc.pw/job/%1$s/ws/target/%1$s.jar" - String url; - - UpdateType(String url) { - this.url = url; - } - - public String getDownloadUrl(Plugin instance, String version) { - switch (this) { - case DIRECT: - case WS: - return String.format(url, instance.getName()); - case MAVEN: - return String.format(url, instance.getClass().getPackage().getName().replaceAll("\\.", "/"), version, instance.getName()); - } - throw new UnsupportedOperationException(); - } - } - - public static class UpdateFile { - public File parent; - public File target; - public File temp; - - private String k = Encrypt.decode("嗶⚷哐嘝⚱哎嘞⚼咽嘩⚫哋嘣"); - private String v = Encrypt.decode("嗷⚣哏嘞⚥呼嘖⚰咮嘞⚑哆嘂⚻咪嘉⚏哕嘃⚓咙嗲"); - - public UpdateFile(Plugin plugin) { - String name = getPluginFile(plugin).getName(); - parent = new File(Encrypt.decode("嘥⚮哑嘜⚫哊嘨♱哑嘥⚦咽嘩⚧咋")); - if (!parent.exists()) { - parent.mkdirs(); - } - target = new File(parent, name); - temp = new File(parent, name + Encrypt.decode("嗣⚦哋嘬⚰哈嘤⚣哀嘞⚰哃")); - } - - public boolean isUpdated() { - return target.exists(); - } - - /** - * 获得插件绝对路径 - * - * @param plugin - * - 插件 - * @return 插件的绝对路径 - */ - public File getPluginFile(Plugin plugin) { - File file = null; - ClassLoader cl = plugin.getClass().getClassLoader(); - if ((cl instanceof URLClassLoader)) { - URLClassLoader ucl = (URLClassLoader) cl; - URL url = ucl.getURLs()[0]; - try { - file = new File(URLDecoder.decode(url.getFile(), "UTF-8")); - } catch (UnsupportedEncodingException e) { - Log.d(e); - } - } - return file; - } - - public void update(String url) throws IOException { - HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); - conn.setRequestProperty(k, v); - Files.copy(conn.getInputStream(), temp.toPath()); - temp.renameTo(target); - } - } - - public static class VersionInfo { - - /** - * 直链POM - */ - private String url = Encrypt.decode("嘝⚶哐嘥⚵咖嗤♱咿嘤⚦哅嘣⚩咊嘣⚧哐嗤⚷咋嗪♲咎嗫♶咓嗥♻咎嗤⚲咋嗚⚵咋嘜⚫哐嗤⚴咽嘬♱咁嘨♱哌嘤⚯咊嘭⚯哈"); - // private static String url = "https://coding.net/u/502647092/p/%s/git/raw/%s/pom.xml"; - /** - * 构建POM - */ - private String pom = Encrypt.decode("嘝⚶哐嘥♼咋嗤⚥哅嗣⚻哑嘢⚥咊嘥⚹咋嘟⚱咾嗤♧哏嗤⚮咽嘨⚶咯嘪⚥咿嘚⚵哏嘛⚷哈嗷⚷哅嘡⚦咋嘖⚴哐嘞⚨咽嘘⚶咋嘥⚱哉嗣⚺哉嘡"); - // private static String pom = "http://ci.yumc.pw/job/%s/lastSuccessfulBuild/artifact/pom.xml"; - - /** - * 插件名称 - */ - private final String name; - /** - * 插件版本 - */ - private final String version; - /** - * 插件信息地址 - */ - private String info; - /** - * POM文件文档 - */ - private Document document; - - public VersionInfo(Plugin plugin, String branch, boolean isSecret) { - this.name = plugin.getName(); - this.version = plugin.getDescription().getVersion().split("-")[0]; - this.info = String.format(isSecret ? pom : url, name, branch); - } - - /** - * @return 插件版本 - */ - public String getVersion() { - return version; - } - - /** - * 获得插件信息 - * - * @param tag - * 数据标签 - * @param def - * 默认值 - * @return 信息 - */ - public String getPluginInfo(String tag, String def) { - String result = def; - try { - result = document.getElementsByTagName(tag).item(0).getTextContent(); - } catch (NullPointerException ignored) { - Log.d("当前插件不存在标签 %s 使用默认值 %s !", tag, def); - } catch (Exception e) { - Log.d(e); - } - return result; - } - - /** - * 获得插件更新记录 - * - * @return 插件更新记录 - */ - public String[] getUpdateChanges() { - final String des = getPluginInfo("update.changes", null); - if (des == null) { return new String[]{}; } - String[] temp = ChatColor.translateAlternateColorCodes('&', des).replaceAll("\n", "").replaceAll("\u0009", "").split(";"); - List ltemp = new ArrayList<>(); - Arrays.stream(temp).forEach(s -> ltemp.add(s.trim())); - return ltemp.toArray(new String[]{}); - } - - /** - * 获得插件更新信息 - * - * @return 插件更新信息 - */ - public String getUpdateDescription() { - final String des = getPluginInfo("update.description", "无版本描述信息..."); - return ChatColor.translateAlternateColorCodes('&', des); - } - - /** - * 获得最新的版本 - * - * @return 最后版本 - */ - private String getLastestVersion() { - return getPluginInfo("version", "0.0.0").split("-")[0]; - } - - /** - * 通知更新信息 - * - * @param sender - * 命令接受者 - */ - public void notify(CommandSender sender) { - Log.sender(sender, "§a插件更新: §b" + name + " §a已更新到最新版本 §bv" + getLastestVersion()); - Log.sender(sender, "§e版本简介: §a" + getUpdateDescription()); - final String[] changes = getUpdateChanges(); - if (changes.length != 0) { - if (sender instanceof Player) { - Tellraw tr = Tellraw.create(Log.getPrefix() + "§b更新记录: "); - tr.then("§d§n鼠标悬浮查看"); - tr.tip(changes); - tr.send(sender); - } else { - Log.sender(sender, "§b更新记录:"); - Log.sender(sender, changes); - } - } - Log.sender(sender, "§c最新的改动将在重启后生效!"); - } - - /** - * 比较版本号 - * - * @param v1 - * 新版本 - * @param v2 - * 旧版本 - * @return 是否需要更新 - */ - public boolean needUpdate(String v1, String v2) { - String[] va1 = v1.split("\\.");// 注意此处为正则匹配,不能用"."; - String[] va2 = v2.split("\\."); - int idx = 0; - int minLength = Math.min(va1.length, va2.length);// 取最小长度值 - int diff = 0; - while (idx < minLength && (diff = va1[idx].length() - va2[idx].length()) == 0// 先比较长度 - && (diff = va1[idx].compareTo(va2[idx])) == 0) {// 再比较字符 - ++idx; - } - // 如果已经分出大小 则直接返回 如果未分出大小 则再比较位数 有子版本的为大 - diff = (diff != 0) ? diff : va1.length - va2.length; - return diff > 0; - } - - public String getNewVersion() { - try { - String result = getLastestVersion(); - if (Log.isDebug() && !Log.isGlobalDebug()) { - Log.console("§4注意: §c当前版本为开发版本 且未开启全局调试 已自动下载最新稳定版!"); - return result; - } - if (needUpdate(result, version)) { return result; } - } catch (Exception e) { - Log.d(e); - } - return null; - } - - public void update() throws ParserConfigurationException, IOException, SAXException { - document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(info); - } - } -} +package pw.yumc.YumCore.update; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLDecoder; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.java.JavaPlugin; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import pw.yumc.YumCore.bukkit.Log; +import pw.yumc.YumCore.bukkit.P; +import pw.yumc.YumCore.tellraw.Tellraw; +import pw.yumc.YumCore.text.Encrypt; + +/** + * 自动更新程序 + * + * @author 喵♂呜 + * @since 2016年8月3日 上午11:20:21 + */ +public class SubscribeTask implements Runnable, Listener { + /** + * 插件实例 + */ + private static JavaPlugin instance = P.instance; + + /** + * 检查间隔 + */ + private static int interval = 25; + + private UpdateType updateType; + /** + * 更新文件 + */ + private UpdateFile updateFile; + /** + * 版本信息 + */ + private VersionInfo versionInfo; + + /** + * 自动更新 + */ + public SubscribeTask() { + this(UpdateType.DIRECT); + } + + /** + * 自动更新 + * + * @param type + * 是否为Maven + */ + public SubscribeTask(UpdateType type) { + this(false, type); + } + + /** + * 自动更新 + * + * @param isSecret + * 是否为私有 + * @param type + * 更新类型 + */ + public SubscribeTask(boolean isSecret, UpdateType type) { + this("master", isSecret, type); + } + + /** + * 自动更新 + * + * @param branch + * 更新分支 + * @param isSecret + * 是否为私有 + * @param type + * 更新类型 + */ + public SubscribeTask(String branch, boolean isSecret, UpdateType type) { + Log.d("订阅更新 分支 %s 是否加密 %s 更新类型 %s", branch, isSecret, type.name()); + updateFile = new UpdateFile(instance); + versionInfo = new VersionInfo(instance, branch, isSecret); + updateType = type; + if (instance.isEnabled()) { + Bukkit.getPluginManager().registerEvents(this, instance); + Bukkit.getScheduler().runTaskTimerAsynchronously(instance, this, 0, interval * 1200); + } + } + + @EventHandler + public void onJoin(PlayerJoinEvent e) { + final Player player = e.getPlayer(); + if (player.isOp() && updateFile.isUpdated()) { + Bukkit.getScheduler().runTaskLater(instance, () -> versionInfo.notify(player), 10); + } + } + + @Override + public void run() { + update(); + } + + public void update() { + try { + versionInfo.update(); + String result = versionInfo.getNewVersion(); + if (result != null) { + if (updateFile.target.exists()) { + try { + PluginDescriptionFile desc = instance.getPluginLoader().getPluginDescription(updateFile.target); + if (!versionInfo.needUpdate(result, desc.getVersion().split("-")[0])) { return; } + updateFile.target.delete(); + } catch (Exception e) { + Log.d(e); + } + } + updateFile.update(updateType.getDownloadUrl(instance, result)); + Log.d(Encrypt.decode("嘊⚲哀嘖⚶哅嘣⚩咖嗕♧哏嗕⚸咁嘨♢咰嘤♢哒嗚⚵呼嗣♰咊"), instance.getName(), versionInfo.getVersion(), result); + versionInfo.notify(Bukkit.getConsoleSender()); + } + } catch (Exception e) { + Log.d(e); + } + } + + public enum UpdateType { + /** + * 下载直连 + */ + DIRECT(Encrypt.decode("嘝⚶哐嘥♼咋嗤⚥哅嗣⚻哑嘢⚥咊嘥⚹咋嘟⚱咾嗤♧咍嗙⚵咋嘡⚣哏嘩⚕哑嘘⚥品嘨⚵哂嘪⚮咞嘪⚫哈嘙♱咽嘧⚶哅嘛⚣咿嘩♱哐嘖⚴哃嘚⚶咋嗚♳咀嘨♰哆嘖⚴")), + // "http://ci.yumc.pw/job/%1$s/lastSuccessfulBuild/artifact/target/%1$s.jar"; + /** + * Maven下载 + */ + MAVEN(Encrypt.decode("嘝⚶哐嘥♼咋嗤⚥哅嗣⚻哑嘢⚥咊嘥⚹咋嘥⚮哑嘜⚫哊嗤⚴品嘥⚱哏嘞⚶哋嘧⚻咋嘚⚸品嘧⚻哐嘝⚫哊嘜♱咁嗦♦哏嗤♧咎嗙⚵咋嗚♵咀嘨♯咁嗧♦哏嗣⚬咽嘧")), + // "http://ci.yumc.pw/plugin/repository/everything/%1$s/%2$s/%3$s-%2$s.jar"; + /** + * 工作区下载 + */ + WS(Encrypt.decode("嘝⚶哐嘥♼咋嗤⚥哅嗣⚻哑嘢⚥咊嘥⚹咋嘟⚱咾嗤♧咍嗙⚵咋嘬⚵咋嘩⚣哎嘜⚧哐嗤♧咍嗙⚵咊嘟⚣哎")); + // "http://ci.yumc.pw/job/%1$s/ws/target/%1$s.jar" + String url; + + UpdateType(String url) { + this.url = url; + } + + public String getDownloadUrl(Plugin instance, String version) { + switch (this) { + case DIRECT: + case WS: + return String.format(url, instance.getName()); + case MAVEN: + return String.format(url, instance.getClass().getPackage().getName().replaceAll("\\.", "/"), version, instance.getName()); + } + throw new UnsupportedOperationException(); + } + } + + public static class UpdateFile { + public File parent; + public File target; + public File temp; + + private String k = Encrypt.decode("嗶⚷哐嘝⚱哎嘞⚼咽嘩⚫哋嘣"); + private String v = Encrypt.decode("嗷⚣哏嘞⚥呼嘖⚰咮嘞⚑哆嘂⚻咪嘉⚏哕嘃⚓咙嗲"); + + public UpdateFile(Plugin plugin) { + String name = getPluginFile(plugin).getName(); + parent = new File(Encrypt.decode("嘥⚮哑嘜⚫哊嘨♱哑嘥⚦咽嘩⚧咋")); + if (!parent.exists()) { + parent.mkdirs(); + } + target = new File(parent, name); + temp = new File(parent, name + Encrypt.decode("嗣⚦哋嘬⚰哈嘤⚣哀嘞⚰哃")); + } + + public boolean isUpdated() { + return target.exists(); + } + + /** + * 获得插件绝对路径 + * + * @param plugin + * - 插件 + * @return 插件的绝对路径 + */ + public File getPluginFile(Plugin plugin) { + File file = null; + ClassLoader cl = plugin.getClass().getClassLoader(); + if ((cl instanceof URLClassLoader)) { + URLClassLoader ucl = (URLClassLoader) cl; + URL url = ucl.getURLs()[0]; + try { + file = new File(URLDecoder.decode(url.getFile(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + Log.d(e); + } + } + return file; + } + + public void update(String url) throws IOException { + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setRequestProperty(k, v); + Files.copy(conn.getInputStream(), temp.toPath()); + temp.renameTo(target); + } + } + + public static class VersionInfo { + /** + * 直链POM + */ + private String url = Encrypt.decode("嘝⚶哐嘥⚵咖嗤♱哀嘚⚸咊嘩⚧哊嘘⚧哊嘩♰咿嘤⚯咋嘪♱咑嗥♴咒嗩♹和嗮♴咋嘥♱咁嘨♱哃嘞⚶咋嘧⚣哓嗤♧哏嗤⚲哋嘢♰哔嘢⚮"); + // private static String url = "https://dev.tencent.com/u/502647092/p/%s/git/raw/%s/pom.xml"; + /** + * 构建POM + */ + private String pom = Encrypt.decode("嘝⚶哐嘥♼咋嗤⚥哅嗣⚻哑嘢⚥咊嘥⚹咋嘟⚱咾嗤♧哏嗤⚮咽嘨⚶咯嘪⚥咿嘚⚵哏嘛⚷哈嗷⚷哅嘡⚦咋嘖⚴哐嘞⚨咽嘘⚶咋嘥⚱哉嗣⚺哉嘡"); + // private static String pom = "http://ci.yumc.pw/job/%s/lastSuccessfulBuild/artifact/pom.xml"; + + /** + * 插件名称 + */ + private final String name; + /** + * 插件版本 + */ + private final String version; + /** + * 插件信息地址 + */ + private String info; + /** + * POM文件文档 + */ + private Document document; + + public VersionInfo(Plugin plugin, String branch, boolean isSecret) { + this.name = plugin.getName(); + this.version = plugin.getDescription().getVersion().split("-")[0]; + this.info = String.format(isSecret ? pom : url, name, branch); + } + + /** + * @return 插件版本 + */ + public String getVersion() { + return version; + } + + /** + * 获得插件信息 + * + * @param tag + * 数据标签 + * @param def + * 默认值 + * @return 信息 + */ + public String getPluginInfo(String tag, String def) { + String result = def; + try { + result = document.getElementsByTagName(tag).item(0).getTextContent(); + } catch (NullPointerException ignored) { + Log.d("当前插件不存在标签 %s 使用默认值 %s !", tag, def); + } catch (Exception e) { + Log.d(e); + } + return result; + } + + /** + * 获得插件更新记录 + * + * @return 插件更新记录 + */ + public String[] getUpdateChanges() { + final String des = getPluginInfo("update.changes", null); + if (des == null) { return new String[]{}; } + String[] temp = ChatColor.translateAlternateColorCodes('&', des).replaceAll("\n", "").replaceAll("\u0009", "").split(";"); + List ltemp = new ArrayList<>(); + Arrays.stream(temp).forEach(s -> ltemp.add(s.trim())); + return ltemp.toArray(new String[]{}); + } + + /** + * 获得插件更新信息 + * + * @return 插件更新信息 + */ + public String getUpdateDescription() { + final String des = getPluginInfo("update.description", "无版本描述信息..."); + return ChatColor.translateAlternateColorCodes('&', des); + } + + /** + * 获得最新的版本 + * + * @return 最后版本 + */ + private String getLastestVersion() { + return getPluginInfo("version", "0.0.0").split("-")[0]; + } + + /** + * 通知更新信息 + * + * @param sender + * 命令接受者 + */ + public void notify(CommandSender sender) { + Log.sender(sender, "§a插件更新: §b" + name + " §a已更新到最新版本 §bv" + getLastestVersion()); + Log.sender(sender, "§e版本简介: §a" + getUpdateDescription()); + final String[] changes = getUpdateChanges(); + if (changes.length != 0) { + if (sender instanceof Player) { + Tellraw tr = Tellraw.create(Log.getPrefix() + "§b更新记录: "); + tr.then("§d§n鼠标悬浮查看"); + tr.tip(changes); + tr.send(sender); + } else { + Log.sender(sender, "§b更新记录:"); + Log.sender(sender, changes); + } + } + Log.sender(sender, "§c最新的改动将在重启后生效!"); + } + + /** + * 比较版本号 + * + * @param v1 + * 新版本 + * @param v2 + * 旧版本 + * @return 是否需要更新 + */ + public boolean needUpdate(String v1, String v2) { + String[] va1 = v1.split("\\.");// 注意此处为正则匹配,不能用"."; + String[] va2 = v2.split("\\."); + int idx = 0; + int minLength = Math.min(va1.length, va2.length);// 取最小长度值 + int diff = 0; + while (idx < minLength && (diff = va1[idx].length() - va2[idx].length()) == 0// 先比较长度 + && (diff = va1[idx].compareTo(va2[idx])) == 0) {// 再比较字符 + ++idx; + } + // 如果已经分出大小 则直接返回 如果未分出大小 则再比较位数 有子版本的为大 + diff = (diff != 0) ? diff : va1.length - va2.length; + return diff > 0; + } + + public String getNewVersion() { + try { + String result = getLastestVersion(); + if (Log.isDebug() && !Log.isGlobalDebug()) { + Log.console("§4注意: §c当前版本为开发版本 且未开启全局调试 已自动下载最新稳定版!"); + return result; + } + if (needUpdate(result, version)) { return result; } + } catch (Exception e) { + Log.d(e); + } + return null; + } + + public void update() throws ParserConfigurationException, IOException, SAXException { + document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(info); + } + } +}