diff options
author | Luck <git@lucko.me> | 2019-04-17 00:58:28 +0100 |
---|---|---|
committer | Luck <git@lucko.me> | 2019-04-17 00:58:28 +0100 |
commit | 394c59d375811e4b1e0f23a528ef85d8c4d0e5a0 (patch) | |
tree | 2e9486f564a2a518fc938dfc0d5b58ae067789f1 /spark-bukkit | |
parent | ecd4cec8545460a4fc4ca65b911c2503a00cd8e7 (diff) | |
download | spark-394c59d375811e4b1e0f23a528ef85d8c4d0e5a0.tar.gz spark-394c59d375811e4b1e0f23a528ef85d8c4d0e5a0.tar.bz2 spark-394c59d375811e4b1e0f23a528ef85d8c4d0e5a0.zip |
Add /spark health command to report tps / memory usage stats
Diffstat (limited to 'spark-bukkit')
-rw-r--r-- | spark-bukkit/src/main/java/me/lucko/spark/bukkit/CommandMapUtil.java | 165 | ||||
-rw-r--r-- | spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java | 18 |
2 files changed, 183 insertions, 0 deletions
diff --git a/spark-bukkit/src/main/java/me/lucko/spark/bukkit/CommandMapUtil.java b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/CommandMapUtil.java new file mode 100644 index 0000000..08d65df --- /dev/null +++ b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/CommandMapUtil.java @@ -0,0 +1,165 @@ +/* + * This file is part of helper, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) <luck@lucko.me> + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.spark.bukkit; + +import com.google.common.base.Preconditions; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandMap; +import org.bukkit.command.PluginCommand; +import org.bukkit.command.SimpleCommandMap; +import org.bukkit.command.TabCompleter; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.SimplePluginManager; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.Iterator; +import java.util.Map; + +/** + * Utility for interacting with the server's {@link CommandMap} instance. + */ +public final class CommandMapUtil { + + private static final Constructor<PluginCommand> COMMAND_CONSTRUCTOR; + private static final Field COMMAND_MAP_FIELD; + private static final Field KNOWN_COMMANDS_FIELD; + + static { + Constructor<PluginCommand> commandConstructor; + try { + commandConstructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); + commandConstructor.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + COMMAND_CONSTRUCTOR = commandConstructor; + + Field commandMapField; + try { + commandMapField = SimplePluginManager.class.getDeclaredField("commandMap"); + commandMapField.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + COMMAND_MAP_FIELD = commandMapField; + + Field knownCommandsField; + try { + knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands"); + knownCommandsField.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + KNOWN_COMMANDS_FIELD = knownCommandsField; + } + + private static CommandMap getCommandMap() { + try { + return (CommandMap) COMMAND_MAP_FIELD.get(Bukkit.getServer().getPluginManager()); + } catch (Exception e) { + throw new RuntimeException("Could not get CommandMap", e); + } + } + + private static Map<String, Command> getKnownCommandMap() { + try { + //noinspection unchecked + return (Map<String, Command>) KNOWN_COMMANDS_FIELD.get(getCommandMap()); + } catch (Exception e) { + throw new RuntimeException("Could not get known commands map", e); + } + } + + /** + * Registers a CommandExecutor with the server + * + * @param plugin the plugin instance + * @param command the command instance + * @param aliases the command aliases + * @param <T> the command executor class type + * @return the command executor + */ + public static <T extends CommandExecutor> T registerCommand(Plugin plugin, T command, String... aliases) { + Preconditions.checkArgument(aliases.length != 0, "No aliases"); + for (String alias : aliases) { + try { + PluginCommand cmd = COMMAND_CONSTRUCTOR.newInstance(alias, plugin); + + getCommandMap().register(plugin.getDescription().getName(), cmd); + getKnownCommandMap().put(plugin.getDescription().getName().toLowerCase() + ":" + alias.toLowerCase(), cmd); + getKnownCommandMap().put(alias.toLowerCase(), cmd); + cmd.setLabel(alias.toLowerCase()); + + cmd.setExecutor(command); + if (command instanceof TabCompleter) { + cmd.setTabCompleter((TabCompleter) command); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + return command; + } + + /** + * Unregisters a CommandExecutor with the server + * + * @param command the command instance + * @param <T> the command executor class type + * @return the command executor + */ + public static <T extends CommandExecutor> T unregisterCommand(T command) { + CommandMap map = getCommandMap(); + try { + //noinspection unchecked + Map<String, Command> knownCommands = (Map<String, Command>) KNOWN_COMMANDS_FIELD.get(map); + + Iterator<Command> iterator = knownCommands.values().iterator(); + while (iterator.hasNext()) { + Command cmd = iterator.next(); + if (cmd instanceof PluginCommand) { + CommandExecutor executor = ((PluginCommand) cmd).getExecutor(); + if (command == executor) { + cmd.unregister(map); + iterator.remove(); + } + } + } + } catch (Exception e) { + throw new RuntimeException("Could not unregister command", e); + } + + return command; + } + + private CommandMapUtil() { + throw new UnsupportedOperationException("This class cannot be instantiated"); + } + +}
\ No newline at end of file diff --git a/spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java index 1d6160a..1fcb571 100644 --- a/spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java +++ b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java @@ -22,6 +22,8 @@ package me.lucko.spark.bukkit; import me.lucko.spark.common.SparkPlatform; import me.lucko.spark.common.SparkPlugin; +import me.lucko.spark.common.command.CommandResponseHandler; +import me.lucko.spark.common.monitor.tick.TpsCalculator; import me.lucko.spark.common.sampler.ThreadDumper; import me.lucko.spark.common.sampler.TickCounter; import org.bukkit.ChatColor; @@ -42,6 +44,22 @@ public class SparkBukkitPlugin extends JavaPlugin implements SparkPlugin<Command @Override public void onEnable() { this.platform.enable(); + + // override Spigot's TPS command with our own. + if (getConfig().getBoolean("override-tps-command", true)) { + CommandMapUtil.registerCommand(this, (sender, command, label, args) -> { + if (!sender.hasPermission("spark") && !sender.hasPermission("spark.tps") && !sender.hasPermission("bukkit.command.tps")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + CommandResponseHandler<CommandSender> resp = new CommandResponseHandler<>(this.platform, sender); + TpsCalculator tpsCalculator = this.platform.getTpsCalculator(); + resp.replyPrefixed("TPS from last 5s, 10s, 1m, 5m, 15m:"); + resp.replyPrefixed(" " + tpsCalculator.toFormattedString()); + return true; + }, "tps"); + } } @Override |