package com.mengcraft.protect; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import com.mengcraft.common.util.OptionParser; import com.mengcraft.common.util.OptionParser.FilterMode; import com.mengcraft.common.util.OptionParser.ParsedOption; import com.mengcraft.protect.manager.EntityManager; import com.mengcraft.protect.manager.PlayerRecordManager; import com.mengcraft.protect.manager.SegmentManager; import com.mengcraft.protect.manager.TickManager; import com.mengcraft.protect.util.TimeUtils; public class Commands implements CommandExecutor { private final Protect plugin; private final static int SIZE_MB_INT = 1048576; private final static byte BYTE_ZERO = 0; private long memory = 0L; private long cpu = 0L; private final ExecutorService pool = Executors.newCachedThreadPool(); public Commands(Protect protect) { this.plugin = protect; } private String[] getPluginInfo() { String[] strings = new String[] { ChatColor.GOLD + "/protect entity [world STRING]", ChatColor.GOLD + "/protect entity purge <TYPE|all> [world STR] [rate INT]", ChatColor.GOLD + "/protect chunk", ChatColor.GOLD + "/protect chunk unload", ChatColor.GOLD + "/protect ips", ChatColor.GOLD + "/protect ips ban PLAYER [rate INT] [time INT_DAY]", ChatColor.GOLD + "/protect ips unban IP_SEGMENT", ChatColor.GOLD + "/protect system", ChatColor.GOLD + "/protect system test <mem|cpu>" }; return strings; } @Override public boolean onCommand(CommandSender sender, Command arg1, String arg2, String[] args) { if (args.length < 1) { sender.sendMessage(getPluginInfo()); } else if (args[0].equals("entity")) { OptionParser parser = new OptionParser(); parser.addFilter("purge", FilterMode.WITH_ARGUMENT); parser.addFilter("world", FilterMode.WITH_ARGUMENT); parser.addFilter("rate", FilterMode.WITH_ARGUMENT); ParsedOption option = parser.parse(Arrays.copyOfRange(args, 1, args.length)); if (option.getSingleList().size() > 0) { sender.sendMessage(ChatColor.RED + "不正确的参数"); } else if (option.has("purge")) { int rate = 16; if (option.has("rate") && option.isInteger("rate")) { rate = option.getInteger("rate"); } else if (option.has("rate")) { rate = -1; } if (rate < -1) { sender.sendMessage(ChatColor.RED + "不正确的限制值"); } else if (option.has("world") && Bukkit.getWorld(option.getString("world")) != null) { sender.sendMessage(purgeEntity(Bukkit.getWorld(option.getString("world")), option.getString("purge"), rate)); } else if (option.has("world")) { sender.sendMessage(ChatColor.RED + "错误的世界名"); } else { sender.sendMessage(purgeEntity(option.getString("purge"), rate)); } } else if (option.has("world") && Bukkit.getWorld(option.getString("world")) != null) { sender.sendMessage(getEntityInfo(this.plugin.getServer().getWorld(option.getString("world")))); } else if (option.has("world")) { sender.sendMessage(ChatColor.RED + "错误的世界名"); } else { sender.sendMessage(getEntityInfo()); } } else if (args[0].equals("chunk")) { if (args.length < 2) { sender.sendMessage(getChunkInfo()); } else if (args.length < 3) { if (args[1].equals("unload")) { sender.sendMessage(unloadChunk()); } } else { sender.sendMessage(getPluginInfo()); } } else if (args[0].equals("ips")) { OptionParser parser = new OptionParser(); parser.addFilter("ban", FilterMode.WITH_ARGUMENT); parser.addFilter("unban", FilterMode.WITH_ARGUMENT); parser.addFilter("rate", FilterMode.WITH_ARGUMENT); parser.addFilter("time", FilterMode.WITH_ARGUMENT); ParsedOption option = parser.parse(Arrays.copyOfRange(args, 1, args.length)); if (option.getSingleList().size() > 0) { sender.sendMessage(ChatColor.RED + "错误的参数"); } else if (option.has("ban") && option.has("unban")) { sender.sendMessage(ChatColor.RED + "错误的参数"); } else if (option.has("ban") && PlayerRecordManager.getManager().hasPlayer(option.getString("ban"))) { int rate = 2; if (option.has("rate") && option.isInteger("rate")) { rate = option.getInteger("rate"); } else if (option.has("rate")) { rate = -1; } int time = 7; if (option.has("time") && option.isInteger("time")) { time = option.getInteger("time"); } else if (option.has("time")) { time = -1; } if (rate > 3 || rate < 1) { sender.sendMessage(ChatColor.RED + "错误的网段参数"); } else if (time < 0) { sender.sendMessage(ChatColor.RED + "错误的时间参数"); } else { sender.sendMessage(ban(option.getString("ban"), rate, time)); } } else if (option.has("ban")) { sender.sendMessage(ChatColor.RED + "玩家不存在"); } else if (option.has("unban")) { sender.sendMessage(unban(option.getString("unban"))); } else { sender.sendMessage(getBannedInfo()); } } else if (args[0].equals("system")) { OptionParser parser = new OptionParser(); parser.addFilter("test", FilterMode.WITH_ARGUMENT); ParsedOption option = parser.parse(Arrays.copyOfRange(args, 1, args.length)); if (option.getSingleList().size() > 0) { sender.sendMessage(ChatColor.RED + "错误的参数"); } else if (option.has("test") && option.getString("test").equals("mem")) { sender.sendMessage(testMemory()); } else if (option.has("test") && option.getString("test").equals("cpu")) { sender.sendMessage(testProcessors()); } else { sender.sendMessage(getSystemInfo()); } } return true; } private String[] getEntityInfo() { List<World> worlds = this.plugin.getServer().getWorlds(); return getEntityInfo(EntityManager.getManager().getEntityInfo(worlds)); } private String[] getEntityInfo(World world) { return getEntityInfo(EntityManager.getManager().getEntityInfo(world)); } private String[] getEntityInfo(Map<String, Integer> map) { List<String> list = new ArrayList<>(); int count = 0; for (Entry<String, Integer> entry : map.entrySet()) { list.add(ChatColor.GOLD + entry.getKey() + ": " + entry.getValue()); count += entry.getValue(); } list.add(ChatColor.RED + "TATOL: " + count); return list.toArray(new String[] {}); } private String purgeEntity(String type, int rate) { List<World> worlds = this.plugin.getServer().getWorlds(); int count = EntityManager.getManager().purgeEntity(worlds, type.toUpperCase(), rate); return ChatColor.GOLD + "Purge done: " + count; } private String purgeEntity(World world, String type, int rate) { int count = EntityManager.getManager().purgeEntity(world, type.toUpperCase(), rate); return ChatColor.GOLD + "Purge done: " + count; } private String[] testMemory() { List<String> strings = new ArrayList<>(); strings.add(ChatColor.RED + "尝试进行内存测试..."); if (this.cpu < 0) { strings.add(ChatColor.RED + "请等待CPU测试完毕"); } else if (this.memory > 0) { strings.add(ChatColor.RED + "已经进行过内存测试"); } else if (this.memory < 0) { strings.add(ChatColor.RED + "正在进行内存测试中"); } else { this.memory = -1; this.pool.execute(new TestMemoryTask()); strings.add(ChatColor.RED + "内存测试在后台运行"); strings.add(ChatColor.RED + "请稍后尝试查看结果"); } return strings.toArray(new String[] {}); } private class TestMemoryTask implements Runnable { @Override public void run() { int count = 0; for (long time = System.currentTimeMillis() + 16000; System.currentTimeMillis() < time; count++) { act(); } setMemory(count / 8); } private void act() { Arrays.fill(new byte[SIZE_MB_INT], BYTE_ZERO); } } private String[] testProcessors() { List<String> strings = new ArrayList<>(); strings.add(ChatColor.RED + "尝试进行CPU测试..."); if (this.memory < 0) { strings.add(ChatColor.RED + "请等待内存测试完毕"); } else if (this.cpu > 0) { strings.add(ChatColor.RED + "已经进行过CPU测试"); return strings.toArray(new String[] {}); } else if (this.cpu < 0) { strings.add(ChatColor.RED + "正在进行CPU测试中"); return strings.toArray(new String[] {}); } else { this.cpu = -1; this.pool.execute(new TestProcessorTask()); this.pool.execute(new TestProcessorTask()); strings.add(ChatColor.RED + "CPU测试在后台运行"); strings.add(ChatColor.RED + "请稍后尝试查看结果"); } return strings.toArray(new String[] {}); } private class TestProcessorTask implements Runnable { @Override public void run() { int count = 0; for (long time = System.currentTimeMillis() + 16000; System.currentTimeMillis() < time; count++) { pi(); } setProcessor(count); } private void pi() { for (double i = 1, pi = 0; i <= 16384; i = i + 1) { pi = pi + Math.pow(-1, (i + 1)) * 4 / (2 * i - 1); } } } private String[] getSystemInfo() { Runtime runtime = Runtime.getRuntime(); List<String> strings = new ArrayList<>(); long free = runtime.freeMemory(); long used = runtime.totalMemory() - free; strings.add(ChatColor.GOLD + "===== 内存信息 ====="); strings.add(ChatColor.GOLD + "已用内存: " + used / SIZE_MB_INT + "MB"); strings.add(ChatColor.GOLD + "最大内存: " + runtime.maxMemory() / SIZE_MB_INT + "MB"); if (this.memory > 0) { strings.add(ChatColor.GOLD + "内存跑分: " + this.memory); } else if (this.memory < 0) { strings.add(ChatColor.GOLD + "内存跑分: 测试中"); } else { strings.add(ChatColor.GOLD + "内存跑分: 未测试"); } strings.add(ChatColor.GOLD + "===== CPU信息 ====="); strings.add(ChatColor.GOLD + "TPS: " + getRecentTickPS()); if (this.cpu > 0) { strings.add(ChatColor.GOLD + "CPU跑分: " + this.cpu); } else if (this.cpu < 0) { strings.add(ChatColor.GOLD + "CPU跑分: 测试中"); } else { strings.add(ChatColor.GOLD + "CPU跑分: 未测试"); } File file = new File("."); strings.add(ChatColor.GOLD + "===== 硬盘信息 ====="); strings.add(ChatColor.GOLD + "空闲空间: " + file.getFreeSpace() / SIZE_MB_INT + "MB"); strings.add(ChatColor.GOLD + "硬盘跑分: 待更新"); return strings.toArray(new String[] {}); } private String getRecentTickPS() { StringBuilder builder = new StringBuilder(); List<Double> recent = TickManager.getManager().getTps(); for (int i = 0; i < recent.size(); i++) { if (i > 0) { builder.append(ChatColor.WHITE); builder.append(","); } double last = recent.get(i); if (last > 15) builder.append(ChatColor.GREEN); else if (last > 10) builder.append(ChatColor.YELLOW); else builder.append(ChatColor.RED); builder.append(last); } return builder.toString(); } private String[] getBannedInfo() { return SegmentManager.getManager().getMessage(); } private String unban(String string) { boolean result = SegmentManager.getManager().remove(string); if (result) { SegmentManager.getManager().saveLines(); return ChatColor.GOLD + "解除封禁成功"; } return ChatColor.RED + "解除封禁失败"; } private String ban(String name, int rate, int time) { long until = System.currentTimeMillis() + time * TimeUtils.TIME_DAY; String addr = PlayerRecordManager.getManager().getAddress(name); SegmentManager.getManager().createRecord(addr, rate, until); SegmentManager.getManager().saveLines(); filterOnline(); return ChatColor.GOLD + "封禁IP段" + time + "天成功"; } private void filterOnline() { for (Player player : Bukkit.getOnlinePlayers()) { filterPlayer(player); } } private void filterPlayer(Player player) { if (SegmentManager.getManager().contains(player.getAddress().getAddress())) { player.kickPlayer("你的IP段已被服务器临时封禁"); } } private String[] getChunkInfo() { List<String> messages = new ArrayList<>(); int total = 0; for (World world : Bukkit.getWorlds()) { int size = world.getLoadedChunks().length; total = total + size; messages.add(ChatColor.GOLD + world.getName() + ": " + size); } messages.add(ChatColor.GOLD + "Total: " + total); int size = messages.size(); return messages.toArray(new String[size]); } private String unloadChunk() { int i = 0; int j = 0; for (World world : Bukkit.getWorlds()) { i = i + world.getLoadedChunks().length; for (Chunk chunk : world.getLoadedChunks()) { chunk.unload(true, true); } j = j + world.getLoadedChunks().length; } i = i - j; return new String(ChatColor.GOLD + "Purge chunk number: " + i); } private synchronized void setProcessor(long cpu) { this.cpu += cpu; } private void setMemory(long memory) { this.memory = memory; } }