Add some starting work for a forge tps command. Also update coremod for new FML behaviour

This commit is contained in:
Christian 2013-08-27 23:03:33 -04:00
parent 0c06d3b47a
commit dddb9b3189
6 changed files with 299 additions and 0 deletions

View file

@ -0,0 +1,5 @@
commands.forge.usage=Use /forge <subcommand>. Subcommands are tps, track
commands.forge.usage.tracking=Use /forge track <type> <duration>. Valid types are te (Tile Entities). Duration is < 60.
commands.forge.tps.summary=%s : Mean tick time: %d ms. Mean TPS: %d
commands.forge.tracking.te.enabled=Tile Entity tracking enabled for %d seconds.

View file

@ -1,5 +1,6 @@
package net.minecraftforge.classloading;
import java.io.File;
import java.util.Map;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
@ -7,6 +8,7 @@ import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
public class FMLForgePlugin implements IFMLLoadingPlugin
{
public static boolean RUNTIME_DEOBF = false;
public static File forgeLocation;
@Override
public String[] getLibraryRequestClass()
@ -39,5 +41,6 @@ public class FMLForgePlugin implements IFMLLoadingPlugin
public void injectData(Map<String, Object> data)
{
RUNTIME_DEOBF = (Boolean)data.get("runtimeDeobfuscationEnabled");
forgeLocation = (File)data.get("coremodLocation");
}
}

View file

@ -22,8 +22,10 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.LinkedHashMultimap;
@ -34,6 +36,7 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Multiset;
import com.google.common.collect.Multisets;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.collect.TreeMultiset;

View file

@ -10,14 +10,18 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.management.PlayerInstance;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.classloading.FMLForgePlugin;
import net.minecraftforge.common.network.ForgeConnectionHandler;
import net.minecraftforge.common.network.ForgeNetworkHandler;
import net.minecraftforge.common.network.ForgePacketHandler;
import net.minecraftforge.common.network.ForgeTinyPacketHandler;
import net.minecraftforge.server.command.ForgeCommand;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.client.FMLFileResourcePack;
import cpw.mods.fml.client.FMLFolderResourcePack;
import cpw.mods.fml.common.DummyModContainer;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.LoadController;
@ -27,6 +31,7 @@ import cpw.mods.fml.common.WorldAccessContainer;
import cpw.mods.fml.common.event.FMLConstructionEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.network.FMLNetworkHandler;
import cpw.mods.fml.common.network.NetworkMod;
@ -174,6 +179,11 @@ public class ForgeDummyContainer extends DummyModContainer implements WorldAcces
ForgeChunkManager.loadConfiguration();
}
@Subscribe
public void serverStarting(FMLServerStartingEvent evt)
{
evt.registerServerCommand(new ForgeCommand(evt.getServer()));
}
@Override
public NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info)
{
@ -191,4 +201,22 @@ public class ForgeDummyContainer extends DummyModContainer implements WorldAcces
DimensionManager.loadDimensionDataMap(tag.hasKey("DimensionData") ? tag.getCompoundTag("DimensionData") : null);
}
}
@Override
public File getSource()
{
return FMLForgePlugin.forgeLocation;
}
@Override
public Class<?> getCustomResourcePackClass()
{
if (getSource().isDirectory())
{
return FMLFolderResourcePack.class;
}
else
{
return FMLFileResourcePack.class;
}
}
}

View file

@ -0,0 +1,113 @@
package net.minecraftforge.server;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.MapMaker;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
public class ForgeTimeTracker {
public static boolean tileEntityTracking;
public static int tileEntityTrackingDuration;
public static long tileEntityTrackingTime;
private Map<TileEntity,int[]> tileEntityTimings;
private Map<Entity,int[]> entityTimings;
private static final ForgeTimeTracker INSTANCE = new ForgeTimeTracker();
private WeakReference<TileEntity> tile;
private WeakReference<Entity> entity;
private long timing;
private ForgeTimeTracker()
{
MapMaker mm = new MapMaker();
mm.weakKeys();
tileEntityTimings = mm.makeMap();
entityTimings = mm.makeMap();
}
private void trackTileStart(TileEntity tileEntity, long nanoTime)
{
if (tileEntityTrackingTime == 0)
{
tileEntityTrackingTime = nanoTime;
}
else if (tileEntityTrackingTime + tileEntityTrackingDuration < nanoTime)
{
tileEntityTracking = false;
tileEntityTrackingTime = 0;
return;
}
tile = new WeakReference<TileEntity>(tileEntity);
timing = nanoTime;
}
private void trackTileEnd(TileEntity tileEntity, long nanoTime)
{
if (tile == null || tile.get() != tileEntity)
{
tile = null;
// race, exit
return;
}
int[] timings = tileEntityTimings.get(tileEntity);
if (timings == null)
{
timings = new int[101];
tileEntityTimings.put(tileEntity, timings);
}
int idx = timings[100] = (timings[100] + 1) % 100;
timings[idx] = (int) (nanoTime - timing);
}
public static ImmutableMap<TileEntity,int[]> getTileTimings()
{
return INSTANCE.buildImmutableTileEntityTimingMap();
}
private ImmutableMap<TileEntity, int[]> buildImmutableTileEntityTimingMap()
{
Builder<TileEntity, int[]> builder = ImmutableMap.<TileEntity,int[]>builder();
for (Entry<TileEntity, int[]> entry : tileEntityTimings.entrySet())
{
builder.put(entry.getKey(), Arrays.copyOfRange(entry.getValue(), 0, 100));
}
return builder.build();
}
public static void trackStart(TileEntity tileEntity)
{
if (!tileEntityTracking) return;
INSTANCE.trackTileStart(tileEntity, System.nanoTime());
}
public static void trackEnd(TileEntity tileEntity)
{
if (!tileEntityTracking) return;
INSTANCE.trackTileEnd(tileEntity, System.nanoTime());
}
public static void trackStart(Entity par1Entity)
{
}
public static void trackEnd(Entity par1Entity)
{
}
}

View file

@ -0,0 +1,147 @@
package net.minecraftforge.server.command;
import java.text.DecimalFormat;
import java.util.List;
import com.google.common.collect.Multiset;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.WrongUsageException;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ChatMessageComponent;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.server.ForgeTimeTracker;
public class ForgeCommand extends CommandBase {
private MinecraftServer server;
public ForgeCommand(MinecraftServer server)
{
this.server = server;
}
private static final DecimalFormat timeFormatter = new DecimalFormat("########0.000");
@Override
public String getCommandName()
{
return "forge";
}
@Override
public String getCommandUsage(ICommandSender icommandsender)
{
return "commands.forge.usage";
}
@Override
public int getRequiredPermissionLevel()
{
return 2;
}
@Override
public void processCommand(ICommandSender sender, String[] args)
{
if (args.length == 0)
{
throw new WrongUsageException("commands.forge.usage");
}
else if ("help".equals(args[0]))
{
throw new WrongUsageException("commands.forge.usage");
}
else if ("tps".equals(args[0]))
{
displayTPS(sender,args);
}
else if ("tpslog".equals(args[0]))
{
doTPSLog(sender,args);
}
else if ("track".equals(args[0]))
{
handleTracking(sender, args);
}
else
{
throw new WrongUsageException("commands.forge.usage");
}
}
private void handleTracking(ICommandSender sender, String[] args)
{
if (args.length != 3)
{
throw new WrongUsageException("commands.forge.usage.tracking");
}
String type = args[1];
int duration = parseIntBounded(sender, args[2], 1, 60);
if ("te".equals(type))
{
doTurnOnTileEntityTracking(sender, duration);
}
else
{
throw new WrongUsageException("commands.forge.usage.tracking");
}
}
private void doTurnOnTileEntityTracking(ICommandSender sender, int duration)
{
ForgeTimeTracker.tileEntityTrackingDuration = duration;
ForgeTimeTracker.tileEntityTracking = true;
sender.sendChatToPlayer(ChatMessageComponent.func_111082_b("commands.forge.tracking.te.enabled", duration));
}
private void doTPSLog(ICommandSender sender, String[] args)
{
}
private void displayTPS(ICommandSender sender, String[] args)
{
int dim = 0;
boolean summary = true;
if (args.length > 1)
{
dim = parseInt(sender, args[1]);
summary = false;
}
if (summary)
{
for (Integer dimId : DimensionManager.getIDs())
{
double worldTickTime = ForgeCommand.mean(this.server.worldTickTimes.get(dimId)) * 1.0E-6D;
double worldTPS = Math.min(1000.0/worldTickTime, 20);
sender.sendChatToPlayer(ChatMessageComponent.func_111082_b("commands.forge.tps.summary",String.format("Dim %d", dimId), timeFormatter.format(worldTickTime), timeFormatter.format(worldTPS)));
}
double meanTickTime = ForgeCommand.mean(this.server.tickTimeArray) * 1.0E-6D;
double meanTPS = Math.min(1000.0/meanTickTime, 20);
sender.sendChatToPlayer(ChatMessageComponent.func_111082_b("commands.forge.tps.summary","Overall", timeFormatter.format(meanTickTime), timeFormatter.format(meanTPS)));
}
else
{
double worldTickTime = ForgeCommand.mean(this.server.worldTickTimes.get(dim)) * 1.0E-6D;
double worldTPS = Math.min(1000.0/worldTickTime, 20);
sender.sendChatToPlayer(ChatMessageComponent.func_111082_b("commands.forge.tps.summary",String.format("Dim %d", dim), timeFormatter.format(worldTickTime), timeFormatter.format(worldTPS)));
}
}
private static long mean(long[] values)
{
long sum = 0l;
for (long v : values)
{
sum+=v;
}
return sum / values.length;
}
}