aboutsummaryrefslogtreecommitdiff
path: root/spark-bukkit
diff options
context:
space:
mode:
authorLuck <git@lucko.me>2019-04-17 00:58:28 +0100
committerLuck <git@lucko.me>2019-04-17 00:58:28 +0100
commit394c59d375811e4b1e0f23a528ef85d8c4d0e5a0 (patch)
tree2e9486f564a2a518fc938dfc0d5b58ae067789f1 /spark-bukkit
parentecd4cec8545460a4fc4ca65b911c2503a00cd8e7 (diff)
downloadspark-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.java165
-rw-r--r--spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java18
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