forked from xjboss/KCauldronX
Added /kc dump command for some debug reports
This commit is contained in:
parent
e64531cffa
commit
a5b10b36ab
17
CONTRIBUTING.md
Normal file
17
CONTRIBUTING.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
Contribution Guide
|
||||||
|
==================
|
||||||
|
You can make and publish your changes, and even suggest to merge your changes with main codebase of the server.
|
||||||
|
|
||||||
|
Installing Dev Environment
|
||||||
|
--------------------------
|
||||||
|
* First of all you need to clone main server code and some other parts, like Forge and Bukkit
|
||||||
|
`git clone --recursive https://gitlab.prok.pw/Prototik/KCauldron.git`
|
||||||
|
* Move to `KCauldron` directory
|
||||||
|
`cd KCauldron`
|
||||||
|
* Prepare some stuff
|
||||||
|
`./gradlew setupCauldron`
|
||||||
|
* For now you need to open project in Eclipse IDE
|
||||||
|
* If you haven't Eclipse on your computer - [download and install it](https://www.eclipse.org/downloads/)
|
||||||
|
* In Eclipse choose File - Import... - General - Existing Projects into Workspace, specify KCauldron/eclipse folder
|
||||||
|
* Unmark `Copy projects into workspace` button!
|
||||||
|
* Click Finish and start your contributing!
|
@ -193,7 +193,7 @@
|
|||||||
+ // Spigot start
|
+ // Spigot start
|
||||||
+
|
+
|
||||||
+ /** Positions to update */
|
+ /** Positions to update */
|
||||||
+ protected final gnu.trove.map.hash.TLongShortHashMap activeChunkSet_CB;
|
+ public final gnu.trove.map.hash.TLongShortHashMap activeChunkSet_CB;
|
||||||
+ public float growthOdds = 100;
|
+ public float growthOdds = 100;
|
||||||
+ protected float modifiedOdds = 100;
|
+ protected float modifiedOdds = 100;
|
||||||
+
|
+
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
package kcauldron;
|
package kcauldron;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@ -10,112 +17,164 @@ import org.bukkit.craftbukkit.entity.CraftPlayer;
|
|||||||
import kcauldron.updater.CommandSenderUpdateCallback;
|
import kcauldron.updater.CommandSenderUpdateCallback;
|
||||||
import kcauldron.updater.KCauldronUpdater;
|
import kcauldron.updater.KCauldronUpdater;
|
||||||
import kcauldron.updater.KVersionRetriever;
|
import kcauldron.updater.KVersionRetriever;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.world.NextTickListEntry;
|
||||||
import net.minecraft.world.WorldServer;
|
import net.minecraft.world.WorldServer;
|
||||||
import net.minecraftforge.server.command.ForgeCommand;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraftforge.common.DimensionManager;
|
||||||
|
|
||||||
public class KCauldronCommand extends Command {
|
public class KCauldronCommand extends Command {
|
||||||
public static final String NAME = "kc";
|
public static final String NAME = "kc";
|
||||||
public static final String CHECK = NAME + ".check";
|
public static final String CHECK = NAME + ".check";
|
||||||
public static final String UPDATE = NAME + ".update";
|
public static final String UPDATE = NAME + ".update";
|
||||||
public static final String TPS = NAME + ".tps";
|
public static final String TPS = NAME + ".tps";
|
||||||
public static final String RESTART = NAME + ".restart";
|
public static final String RESTART = NAME + ".restart";
|
||||||
|
public static final String DUMP = NAME + ".dump";
|
||||||
|
|
||||||
public KCauldronCommand() {
|
public KCauldronCommand() {
|
||||||
super(NAME);
|
super(NAME);
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append(String.format("/%s check - Check to update\n", NAME));
|
builder.append(String.format("/%s check - Check to update\n", NAME));
|
||||||
builder.append(String.format("/%s update [version] - Update to specified or latest version\n", NAME));
|
builder.append(String.format("/%s update [version] - Update to specified or latest version\n", NAME));
|
||||||
builder.append(String.format("/%s tps - Show tps statistics\n", NAME));
|
builder.append(String.format("/%s tps - Show tps statistics\n", NAME));
|
||||||
builder.append(String.format("/%s restart - Restart server\n", NAME));
|
builder.append(String.format("/%s restart - Restart server\n", NAME));
|
||||||
setUsage(builder.toString());
|
builder.append(String.format("/%s dump - Dump statistics into kcauldron.dump file\n", NAME));
|
||||||
|
setUsage(builder.toString());
|
||||||
|
|
||||||
setPermission("kcauldron");
|
setPermission("kc");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean testPermission(CommandSender target, String permission) {
|
public boolean testPermission(CommandSender target, String permission) {
|
||||||
if (testPermissionSilent(target, permission)) {
|
if (testPermissionSilent(target, permission)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
target.sendMessage(ChatColor.RED
|
target.sendMessage(ChatColor.RED
|
||||||
+ "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.");
|
+ "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean testPermissionSilent(CommandSender target, String permission) {
|
public boolean testPermissionSilent(CommandSender target, String permission) {
|
||||||
if (!super.testPermissionSilent(target)) {
|
if (!super.testPermissionSilent(target)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (String p : permission.split(";"))
|
for (String p : permission.split(";"))
|
||||||
if (target.hasPermission(p))
|
if (target.hasPermission(p))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
||||||
if (!testPermission(sender))
|
if (!testPermission(sender))
|
||||||
return true;
|
return true;
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
sender.sendMessage(ChatColor.YELLOW + "Please specify action");
|
sender.sendMessage(ChatColor.YELLOW + "Please specify action");
|
||||||
sender.sendMessage(ChatColor.AQUA + usageMessage);
|
sender.sendMessage(ChatColor.AQUA + usageMessage);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
String action = args[0];
|
String action = args[0];
|
||||||
if ("check".equals(action)) {
|
if ("check".equals(action)) {
|
||||||
if (!testPermission(sender, CHECK))
|
if (!testPermission(sender, CHECK))
|
||||||
return true;
|
return true;
|
||||||
sender.sendMessage(ChatColor.GREEN + "Initiated version check...");
|
sender.sendMessage(ChatColor.GREEN + "Initiated version check...");
|
||||||
KVersionRetriever.startServer(new CommandSenderUpdateCallback(sender), false);
|
KVersionRetriever.startServer(new CommandSenderUpdateCallback(sender), false);
|
||||||
} else if ("update".equals(action)) {
|
} else if ("update".equals(action)) {
|
||||||
KCauldronUpdater.initUpdate(sender, args.length > 1 ? args[1] : null);
|
KCauldronUpdater.initUpdate(sender, args.length > 1 ? args[1] : null);
|
||||||
} else if ("tps".equals(action)) {
|
} else if ("tps".equals(action)) {
|
||||||
if (!testPermission(sender, TPS))
|
if (!testPermission(sender, TPS))
|
||||||
return true;
|
return true;
|
||||||
World currentWorld = null;
|
World currentWorld = null;
|
||||||
if (sender instanceof CraftPlayer) {
|
if (sender instanceof CraftPlayer) {
|
||||||
currentWorld = ((CraftPlayer) sender).getWorld();
|
currentWorld = ((CraftPlayer) sender).getWorld();
|
||||||
}
|
}
|
||||||
sender.sendMessage(ChatColor.DARK_BLUE + "---------------------------------------");
|
sender.sendMessage(ChatColor.DARK_BLUE + "---------------------------------------");
|
||||||
final MinecraftServer server = MinecraftServer.getServer();
|
final MinecraftServer server = MinecraftServer.getServer();
|
||||||
for (World world : server.server.getWorlds()) {
|
for (World world : server.server.getWorlds()) {
|
||||||
if (world instanceof CraftWorld) {
|
if (world instanceof CraftWorld) {
|
||||||
boolean current = currentWorld != null && currentWorld == world;
|
boolean current = currentWorld != null && currentWorld == world;
|
||||||
net.minecraft.world.World mcWorld = ((CraftWorld) world).getHandle();
|
net.minecraft.world.World mcWorld = ((CraftWorld) world).getHandle();
|
||||||
String bukkitName = world.getName();
|
String bukkitName = world.getName();
|
||||||
int dimensionId = mcWorld.provider.dimensionId;
|
int dimensionId = mcWorld.provider.dimensionId;
|
||||||
String name = mcWorld.provider.getDimensionName();
|
String name = mcWorld.provider.getDimensionName();
|
||||||
String displayName = name.equals(bukkitName) ? name : String.format("%s | %s", name, bukkitName);
|
String displayName = name.equals(bukkitName) ? name : String.format("%s | %s", name, bukkitName);
|
||||||
|
|
||||||
double worldTickTime = mean(server.worldTickTimes.get(dimensionId)) * 1.0E-6D;
|
double worldTickTime = mean(server.worldTickTimes.get(dimensionId)) * 1.0E-6D;
|
||||||
double worldTPS = Math.min(1000.0 / worldTickTime, 20);
|
double worldTPS = Math.min(1000.0 / worldTickTime, 20);
|
||||||
|
|
||||||
sender.sendMessage(String.format("%s[%d] %s%s %s- %s%.2fms / %.2ftps", ChatColor.GOLD, dimensionId,
|
sender.sendMessage(String.format("%s[%d] %s%s %s- %s%.2fms / %.2ftps", ChatColor.GOLD, dimensionId,
|
||||||
current ? ChatColor.GREEN : ChatColor.YELLOW, displayName, ChatColor.RESET, ChatColor.DARK_RED, worldTickTime,
|
current ? ChatColor.GREEN : ChatColor.YELLOW, displayName, ChatColor.RESET,
|
||||||
worldTPS));
|
ChatColor.DARK_RED, worldTickTime, worldTPS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
double meanTickTime = mean(server.tickTimeArray) * 1.0E-6D;
|
double meanTickTime = mean(server.tickTimeArray) * 1.0E-6D;
|
||||||
double meanTPS = Math.min(1000.0 / meanTickTime, 20);
|
double meanTPS = Math.min(1000.0 / meanTickTime, 20);
|
||||||
sender.sendMessage(String.format("%sOverall - %s%s%.2fms / %.2ftps", ChatColor.BLUE, ChatColor.RESET,
|
sender.sendMessage(String.format("%sOverall - %s%s%.2fms / %.2ftps", ChatColor.BLUE, ChatColor.RESET,
|
||||||
ChatColor.DARK_RED, meanTickTime, meanTPS));
|
ChatColor.DARK_RED, meanTickTime, meanTPS));
|
||||||
} else if ("restart".equals(action)) {
|
} else if ("restart".equals(action)) {
|
||||||
if (!testPermission(sender, RESTART))
|
if (!testPermission(sender, RESTART))
|
||||||
return true;
|
return true;
|
||||||
KCauldron.restart();
|
KCauldron.restart();
|
||||||
} else {
|
} else if ("dump".equals(action)) {
|
||||||
sender.sendMessage(ChatColor.RED + "Unknown action");
|
if (!testPermission(sender, DUMP))
|
||||||
}
|
return true;
|
||||||
return true;
|
try {
|
||||||
}
|
File outputFile = new File("kcauldron.dump");
|
||||||
|
OutputStream os = new FileOutputStream(outputFile);
|
||||||
|
Writer writer = new OutputStreamWriter(os);
|
||||||
|
for (WorldServer world : DimensionManager.getWorlds()) {
|
||||||
|
writer.write(String.format("Stats for %s [%s] with id %d\n", world,
|
||||||
|
world.provider.getDimensionName(), world.dimension));
|
||||||
|
writer.write("Current tick: " + world.worldInfo.getWorldTotalTime() + "\n");
|
||||||
|
writer.write("\nEntities: ");
|
||||||
|
writer.write("count - " + world.loadedEntityList_KC.size() + "\n");
|
||||||
|
for (Entity entity : world.loadedEntityList_KC) {
|
||||||
|
writer.write(String.format(" %s at (%.4f;%.4f;%.4f)\n", entity.getClass().getName(),
|
||||||
|
entity.posX, entity.posY, entity.posZ));
|
||||||
|
}
|
||||||
|
writer.write("\nTileEntities: ");
|
||||||
|
writer.write("count - " + world.loadedTileEntityList_KC.size() + "\n");
|
||||||
|
for (TileEntity entity : world.loadedTileEntityList_KC) {
|
||||||
|
writer.write(String.format(" %s at (%d;%d;%d)\n", entity.getClass().getName(), entity.xCoord,
|
||||||
|
entity.yCoord, entity.zCoord));
|
||||||
|
}
|
||||||
|
writer.write("\nLoaded chunks: ");
|
||||||
|
writer.write("count - " + world.activeChunkSet_CB.size() + "\n");
|
||||||
|
for (long chunkKey : world.activeChunkSet_CB.keys()) {
|
||||||
|
final int x = WorldServer.keyToX(chunkKey);
|
||||||
|
final int z = WorldServer.keyToZ(chunkKey);
|
||||||
|
Chunk chunk = world.chunkProvider.provideChunk(x, z);
|
||||||
|
if (chunk == null)
|
||||||
|
continue;
|
||||||
|
writer.write(String.format("Chunk at (%d;%d)\n", x, z));
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<NextTickListEntry> updates = world.getPendingBlockUpdates(chunk, false);
|
||||||
|
writer.write("Pending block updates [" + updates.size() + "]:\n");
|
||||||
|
for (NextTickListEntry entry : updates) {
|
||||||
|
writer.write(String.format("(%d;%d;%d) at %d with priority %d\n", entry.xCoord,
|
||||||
|
entry.yCoord, entry.zCoord, entry.scheduledTime, entry.priority));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.write("-------------------------\n");
|
||||||
|
}
|
||||||
|
writer.close();
|
||||||
|
sender.sendMessage(ChatColor.RED + "Dump saved!");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Unknown action");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static final long mean(long[] array) {
|
private static final long mean(long[] array) {
|
||||||
long r = 0;
|
long r = 0;
|
||||||
for (long i : array)
|
for (long i : array)
|
||||||
r += i;
|
r += i;
|
||||||
return r / array.length;
|
return r / array.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user