From 787f48b9127c0c421714fd2c639c96c7906b96f3 Mon Sep 17 00:00:00 2001 From: xjboss Date: Sun, 23 Jul 2017 12:45:13 +0800 Subject: [PATCH 1/2] Modify statistics system --- src/main/java/org/spigotmc/Metrics.java | 5 +- src/main/java/org/spigotmc/SpigotConfig.java | 6 + src/main/java/pw/yumc/KCXStatistics.java | 296 +++++++++++++++++++ 3 files changed, 305 insertions(+), 2 deletions(-) create mode 100644 src/main/java/pw/yumc/KCXStatistics.java diff --git a/src/main/java/org/spigotmc/Metrics.java b/src/main/java/org/spigotmc/Metrics.java index b7debd1..1dc2852 100644 --- a/src/main/java/org/spigotmc/Metrics.java +++ b/src/main/java/org/spigotmc/Metrics.java @@ -27,6 +27,7 @@ */ package org.spigotmc; +import kcauldron.KCauldron; import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.InvalidConfigurationException; @@ -343,10 +344,10 @@ public class Metrics { */ private void postPlugin(final boolean isPing) throws IOException { // Server software specific section - String pluginName = "Spigot"; + String pluginName = "KCauldronX"; boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled String pluginVersion = (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown"; - String serverVersion = Bukkit.getVersion(); + String serverVersion = KCauldron.getCurrentVersion(); int playersOnline = Bukkit.getServer().getOnlinePlayers().size(); // END server software specific section -- all code below does not use any code outside of this class / Java diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java index 69dde75..471b17d 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java @@ -20,6 +20,7 @@ import com.google.common.base.Throwables; import gnu.trove.map.hash.TObjectIntHashMap; import net.minecraft.server.MinecraftServer; +import pw.yumc.KCXStatistics; public class SpigotConfig { @@ -42,6 +43,7 @@ public class SpigotConfig static Map commands; /*========================================================================*/ private static Metrics metrics; + private static KCXStatistics yumc_statistics; public static void init() { @@ -74,6 +76,10 @@ public class SpigotConfig Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); } } + if(yumc_statistics==null){ + yumc_statistics=new KCXStatistics(); + yumc_statistics.start(); + } } static void readConfig(Class clazz, Object instance) diff --git a/src/main/java/pw/yumc/KCXStatistics.java b/src/main/java/pw/yumc/KCXStatistics.java new file mode 100644 index 0000000..7d64e50 --- /dev/null +++ b/src/main/java/pw/yumc/KCXStatistics.java @@ -0,0 +1,296 @@ +/* + * Copyright 2011-2015 喵♂呜. All rights reserved. + */ +package pw.yumc; + +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 cpw.mods.fml.common.eventhandler.EventPriority; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import kcauldron.KCauldron; +import net.minecraftforge.common.MinecraftForge; +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 KCXStatistics { + /** + * 统计系统版本 + */ + private final static int REVISION = 10; + + /** + * 统计插件基础配置文件 + */ + private final static File configfile = new File("plugins" + File.separatorChar + "PluginHelper", "config.yml"); + + /** + * UTF-8编码 + */ + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + /** + * 统计插件基础配置文件 + */ + private YamlConfiguration config; + + /** + * 调试模式 + */ + private final boolean debug; + + /** + * 唯一服务器编码 + */ + private final String guid; + + /** + * 线程任务 + */ + private volatile Thread task = null; + + /** + * 统计线程 + */ + private volatile StatisticsTimer timer = null; + + /** + * 插件使用数据统计 + * + * @throws IOException + * IO异常 + */ + public KCXStatistics() { + try { + if (!configfile.exists()) { + configfile.getParentFile().mkdirs(); + configfile.createNewFile(); + } + config = YamlConfiguration.loadConfiguration(configfile); + initFile(config); + } catch (final IOException e) { + } + this.guid = config.getString("guid"); + this.debug = config.getBoolean("debug", false); + start(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数 + * @return 所代表远程资源的响应结果 + */ + public static String postData(final String url, final String param) { + PrintWriter out = null; + String result = ""; + try { + final URL realUrl = new URL(url); + // 打开和URL之间的连接 + final 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 = ""; + final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), UTF_8)); + while ((response = reader.readLine()) != null) { + result += response; + } + reader.close(); + } catch (final Exception e) { + } finally { + if (out != null) { + out.close(); + } + } + return result; + } + + /** + * 初始化配置文件 + * + * @param config + * 配置文件 + * @throws IOException + */ + private static void initFile(final 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("debug", 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(final String msg) { + if (debug) { + System.out.println("[KCXStatistics] " + msg); + } + } + + /** + * 开启数据统计 这将会在异步执行 + * + * @return 是否运行成功. + */ + public boolean start() { + if (task != null) { + return true; + } + timer = new StatisticsTimer(); + // 开启TPS统计线程 + MinecraftForge.EVENT_BUS.register(timer); + // 开启发送数据线程 + task = new Thread(new Runnable() { + @Override + public void run() { + try { + postPlugin(); + } catch (final Throwable e) { + if (debug) { + e.printStackTrace(); + } + } + } + }); + task.start(); + return true; + } + + /** + * 获得在线玩家人数 + * + * @return 在线玩家人数 + */ + private int getOnlinePlayerNumber() { + return Bukkit.getOnlinePlayers().size(); + } + + /** + * 发送服务器数据到统计网页 + */ + private void postPlugin() throws IOException { + // 服务器数据获取 + final String pluginname = "KCauldronX"; + final String tmposarch = System.getProperty("os.arch"); + + final 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", KCauldron.getCurrentVersion()); + 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")); + + final String jsondata = "Info=" + JSONValue.toJSONString(data); + + final 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); + // 发送数据 + final 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(); + int t=0; + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onServerTick(TickEvent.ServerTickEvent event) { + if(++t==20){ + t=0; + run(); + } + } + /** + * @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 From e5dae008efad62f9042612f61656759cd972be16 Mon Sep 17 00:00:00 2001 From: xjboss Date: Sun, 23 Jul 2017 13:20:29 +0800 Subject: [PATCH 2/2] move yumc statistics to DedicatedServer --- .../dedicated/DedicatedServer.java.patch | 30 +++++++++++-------- src/main/java/org/spigotmc/SpigotConfig.java | 5 ---- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/patches/net/minecraft/server/dedicated/DedicatedServer.java.patch b/patches/net/minecraft/server/dedicated/DedicatedServer.java.patch index 1465b4a..557fc68 100644 --- a/patches/net/minecraft/server/dedicated/DedicatedServer.java.patch +++ b/patches/net/minecraft/server/dedicated/DedicatedServer.java.patch @@ -8,7 +8,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.io.BufferedReader; -@@ -34,9 +35,23 @@ +@@ -34,9 +35,24 @@ import net.minecraft.world.World; import net.minecraft.world.WorldSettings; import net.minecraft.world.WorldType; @@ -27,12 +27,13 @@ +import org.bukkit.craftbukkit.SpigotTimings; // Spigot +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.server.ServerCommandEvent; ++import pw.yumc.KCXStatistics; +// CraftBukkit end + @SideOnly(Side.SERVER) public class DedicatedServer extends MinecraftServer implements IServer { -@@ -44,7 +59,7 @@ +@@ -44,18 +60,21 @@ public final List pendingCommandList = Collections.synchronizedList(new ArrayList()); private RConThreadQuery theRConThreadQuery; private RConThreadMain theRConThreadMain; @@ -41,11 +42,12 @@ private ServerEula field_154332_n; private boolean canSpawnStructures; private WorldSettings.GameType gameType; -@@ -52,10 +67,13 @@ + private boolean guiIsEnabled; public static boolean allowPlayerLogins = false; private static final String __OBFID = "CL_00001784"; - +- - public DedicatedServer(File p_i1508_1_) ++ private KCXStatistics yumc_statistics; + // CraftBukkit start - Signature changed + public DedicatedServer(joptsimple.OptionSet options) { @@ -58,7 +60,7 @@ { private static final String __OBFID = "CL_00001787"; { -@@ -82,31 +100,77 @@ +@@ -82,31 +101,77 @@ }; } @@ -143,7 +145,7 @@ field_155771_h.info("Starting minecraft server version 1.7.10"); if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L) -@@ -117,7 +181,7 @@ +@@ -117,7 +182,7 @@ FMLCommonHandler.instance().onServerStart(this); field_155771_h.info("Loading properties"); @@ -152,7 +154,7 @@ this.field_154332_n = new ServerEula(new File("eula.txt")); if (!this.field_154332_n.func_154346_a()) -@@ -172,6 +236,18 @@ +@@ -172,6 +237,18 @@ this.setServerPort(this.settings.getIntProperty("server-port", 25565)); } @@ -171,7 +173,7 @@ field_155771_h.info("Generating keypair"); this.setKeyPair(CryptManager.createNewKeyPair()); field_155771_h.info("Starting Minecraft server on " + (this.getServerHostname().length() == 0 ? "*" : this.getServerHostname()) + ":" + this.getServerPort()); -@@ -180,7 +256,7 @@ +@@ -180,7 +257,7 @@ { this.func_147137_ag().addLanEndpoint(inetaddress, this.getServerPort()); } @@ -180,7 +182,7 @@ { field_155771_h.warn("**** FAILED TO BIND TO PORT!"); field_155771_h.warn("The exception was: {}", new Object[] {ioexception.toString()}); -@@ -196,10 +272,17 @@ +@@ -196,10 +273,17 @@ field_155771_h.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); } @@ -200,7 +202,7 @@ if (!PreYggdrasilConverter.func_152714_a(this.settings)) { -@@ -208,7 +291,8 @@ +@@ -208,7 +292,8 @@ else { FMLCommonHandler.instance().onServerStarted(); @@ -210,7 +212,7 @@ long j = System.nanoTime(); if (this.getFolderName() == null) -@@ -274,11 +358,36 @@ +@@ -274,11 +359,40 @@ this.theRConThreadMain.startThread(); } @@ -231,6 +233,10 @@ + } + FakePlayer.fakePlayers=null; + FakePlayer.BukkitInited=true; ++ //Yumc Statistcs start ++ yumc_statistics=new KCXStatistics(); ++ yumc_statistics.start(); ++ //Yumc Statistcs end + // KCauldronX end return FMLCommonHandler.instance().handleServerStarting(this); } @@ -247,7 +253,7 @@ public boolean canStructuresSpawn() { return this.canSpawnStructures; -@@ -364,11 +473,19 @@ +@@ -364,11 +478,19 @@ public void executePendingCommands() { diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java index 471b17d..904ddf5 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java @@ -43,7 +43,6 @@ public class SpigotConfig static Map commands; /*========================================================================*/ private static Metrics metrics; - private static KCXStatistics yumc_statistics; public static void init() { @@ -76,10 +75,6 @@ public class SpigotConfig Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); } } - if(yumc_statistics==null){ - yumc_statistics=new KCXStatistics(); - yumc_statistics.start(); - } } static void readConfig(Class clazz, Object instance)