/*
* CommandBook
* Copyright (C) 2011 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.commandbook;
import com.sk89q.minecraft.util.commands.*;
import com.zachsthings.libcomponents.ComponentInformation;
import com.zachsthings.libcomponents.bukkit.BukkitComponent;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
@ComponentInformation(friendlyName = "Debug", desc = "Provides useful debugging information for server owners.")
public class DebugComponent extends BukkitComponent {
@Override
public void enable() {
registerCommands(Commands.class);
}
public class Commands {
@Command(aliases = {"debug"}, desc = "Debugging commands")
@NestedCommand({DebugCommands.class})
public void debug(CommandContext args, CommandSender sender) throws CommandException {
}
}
public class DebugCommands {
@Command(aliases = {"clock"}, usage = "", desc = "Tests the clock rate of your server",
flags = "", min = 0, max = 1)
@CommandPermissions({"commandbook.debug.clock"})
public void testClock(CommandContext args, final CommandSender sender) throws CommandException {
int expected = 5;
if (args.argsLength() == 1) {
expected = Math.min(30, Math.max(1, args.getInteger(0)));
}
sender.sendMessage(ChatColor.DARK_RED
+ "Timing clock test for " + expected + " IN-GAME seconds...");
sender.sendMessage(ChatColor.DARK_RED
+ "DO NOT CHANGE A WORLD'S TIME OR PERFORM A HEAVY OPERATION.");
final World world = CommandBook.server().getWorlds().get(0);
final double expectedTime = expected * 1000;
final double expectedSecs = expected;
final int expectedTicks = 20 * (int)expectedSecs;
final long start = System.currentTimeMillis();
final long startTicks = world.getFullTime();
Runnable task = new Runnable() {
public void run() {
long now = System.currentTimeMillis();
long nowTicks = world.getFullTime();
long elapsedTime = now - start;
double elapsedSecs = elapsedTime / 1000.0;
int elapsedTicks = (int) (nowTicks - startTicks);
double error = (expectedTime - elapsedTime) / elapsedTime * 100;
double clockRate = elapsedTicks / elapsedSecs;
if (expectedTicks != elapsedTicks) {
sender.sendMessage(ChatColor.DARK_RED
+ "Warning: Bukkit scheduler inaccurate; expected "
+ expectedTicks + ", got " + elapsedTicks);
}
if (Math.round(clockRate) == 20) {
sender.sendMessage(ChatColor.YELLOW + "Clock test result: "
+ ChatColor.GREEN + "EXCELLENT");
} else {
if (elapsedSecs > expectedSecs) {
if (clockRate < 19) {
sender.sendMessage(ChatColor.YELLOW + "Clock test result: "
+ ChatColor.DARK_RED + "CLOCK BEHIND");
sender.sendMessage(ChatColor.DARK_RED
+ "WARNING: You have potential block respawn issues.");
} else {
sender.sendMessage(ChatColor.YELLOW + "Clock test result: "
+ ChatColor.DARK_RED + "CLOCK BEHIND");
}
} else {
sender.sendMessage(ChatColor.YELLOW + "Clock test result: "
+ ChatColor.DARK_RED + "CLOCK AHEAD");
}
}
sender.sendMessage(ChatColor.GRAY + "Expected time elapsed: " + expectedTime + "ms");
sender.sendMessage(ChatColor.GRAY + "Time elapsed: " + elapsedTime + "ms");
sender.sendMessage(ChatColor.GRAY + "Error: " + error + "%");
sender.sendMessage(ChatColor.GRAY + "Actual clock rate: " + clockRate + " ticks/sec");
sender.sendMessage(ChatColor.GRAY + "Expected clock rate: 20 ticks/sec");
}
};
CommandBook.server().getScheduler().scheduleSyncDelayedTask(CommandBook.inst(), task, expectedTicks);
}
@Command(aliases = {"info"}, usage = "", desc = "Get server information",
flags = "", min = 0, max = 0)
@CommandPermissions({"commandbook.debug.info"})
public void serverInfo(CommandContext args, CommandSender sender) throws CommandException {
Runtime rt = Runtime.getRuntime();
sender.sendMessage(ChatColor.YELLOW
+ String.format("System: %s %s (%s)",
System.getProperty("os.name"),
System.getProperty("os.version"),
System.getProperty("os.arch")));
sender.sendMessage(ChatColor.YELLOW
+ String.format("Java: %s %s (%s)",
System.getProperty("java.vendor"),
System.getProperty("java.version"),
System.getProperty("java.vendor.url")));
sender.sendMessage(ChatColor.YELLOW
+ String.format("JVM: %s %s %s",
System.getProperty("java.vm.vendor"),
System.getProperty("java.vm.name"),
System.getProperty("java.vm.version")));
sender.sendMessage(ChatColor.YELLOW + "Available processors: "
+ rt.availableProcessors());
sender.sendMessage(ChatColor.YELLOW + "Available total memory: "
+ Math.floor(rt.maxMemory() / 1024.0 / 1024.0) + " MB");
sender.sendMessage(ChatColor.YELLOW + "JVM allocated memory: "
+ Math.floor(rt.totalMemory() / 1024.0 / 1024.0) + " MB");
sender.sendMessage(ChatColor.YELLOW + "Free allocated memory: "
+ Math.floor(rt.freeMemory() / 1024.0 / 1024.0) + " MB");
}
}
}