package net.minecraft.src;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiIngame;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.profiler.Profiler;
import org.lwjgl.opengl.GL11;
public class Lagometer
{
private static Minecraft mc;
private static GameSettings gameSettings;
private static Profiler profiler;
public static boolean active = false;
public static Lagometer.TimerNano timerTick = new Lagometer.TimerNano();
public static Lagometer.TimerNano timerScheduledExecutables = new Lagometer.TimerNano();
public static Lagometer.TimerNano timerChunkUpload = new Lagometer.TimerNano();
public static Lagometer.TimerNano timerChunkUpdate = new Lagometer.TimerNano();
public static Lagometer.TimerNano timerVisibility = new Lagometer.TimerNano();
public static Lagometer.TimerNano timerTerrain = new Lagometer.TimerNano();
public static Lagometer.TimerNano timerServer = new Lagometer.TimerNano();
private static long[] timesFrame = new long[512];
private static long[] timesTick = new long[512];
private static long[] timesScheduledExecutables = new long[512];
private static long[] timesChunkUpload = new long[512];
private static long[] timesChunkUpdate = new long[512];
private static long[] timesVisibility = new long[512];
private static long[] timesTerrain = new long[512];
private static long[] timesServer = new long[512];
private static boolean[] gcs = new boolean[512];
private static int numRecordedFrameTimes = 0;
private static long prevFrameTimeNano = -1L;
private static long renderTimeNano = 0L;
private static long memTimeStartMs = System.currentTimeMillis();
private static long memStart = getMemoryUsed();
private static long memTimeLast = memTimeStartMs;
private static long memLast = memStart;
private static long memTimeDiffMs = 1L;
private static long memDiff = 0L;
private static int memMbSec = 0;
public static boolean updateMemoryAllocation()
{
long timeNowMs = System.currentTimeMillis();
long memNow = getMemoryUsed();
boolean gc = false;
if (memNow < memLast)
{
double memDiffMb = (double)memDiff / 1000000.0D;
double timeDiffSec = (double)memTimeDiffMs / 1000.0D;
int mbSec = (int)(memDiffMb / timeDiffSec);
if (mbSec > 0)
{
memMbSec = mbSec;
}
memTimeStartMs = timeNowMs;
memStart = memNow;
memTimeDiffMs = 0L;
memDiff = 0L;
gc = true;
}
else
{
memTimeDiffMs = timeNowMs - memTimeStartMs;
memDiff = memNow - memStart;
}
memTimeLast = timeNowMs;
memLast = memNow;
return gc;
}
private static long getMemoryUsed()
{
Runtime r = Runtime.getRuntime();
return r.totalMemory() - r.freeMemory();
}
public static void updateLagometer()
{
if (mc == null)
{
mc = Minecraft.getMinecraft();
gameSettings = mc.gameSettings;
profiler = mc.mcProfiler;
}
if (gameSettings.showDebugInfo && gameSettings.ofLagometer)
{
active = true;
long timeNowNano = System.nanoTime();
if (prevFrameTimeNano == -1L)
{
prevFrameTimeNano = timeNowNano;
}
else
{
int frameIndex = numRecordedFrameTimes & timesFrame.length - 1;
++numRecordedFrameTimes;
boolean gc = updateMemoryAllocation();
timesFrame[frameIndex] = timeNowNano - prevFrameTimeNano - renderTimeNano;
timesTick[frameIndex] = timerTick.timeNano;
timesScheduledExecutables[frameIndex] = timerScheduledExecutables.timeNano;
timesChunkUpload[frameIndex] = timerChunkUpload.timeNano;
timesChunkUpdate[frameIndex] = timerChunkUpdate.timeNano;
timesVisibility[frameIndex] = timerVisibility.timeNano;
timesTerrain[frameIndex] = timerTerrain.timeNano;
timesServer[frameIndex] = timerServer.timeNano;
gcs[frameIndex] = gc;
timerTick.reset();
timerScheduledExecutables.reset();
timerVisibility.reset();
timerChunkUpdate.reset();
timerChunkUpload.reset();
timerTerrain.reset();
timerServer.reset();
prevFrameTimeNano = System.nanoTime();
}
}
else
{
active = false;
prevFrameTimeNano = -1L;
}
}
public static void showLagometer(ScaledResolution scaledResolution)
{
if (gameSettings != null && gameSettings.ofLagometer)
{
long timeRenderStartNano = System.nanoTime();
GlStateManager.clear(256);
GlStateManager.matrixMode(5889);
GlStateManager.pushMatrix();
GlStateManager.enableColorMaterial();
GlStateManager.loadIdentity();
GlStateManager.ortho(0.0D, (double)mc.displayWidth, (double)mc.displayHeight, 0.0D, 1000.0D, 3000.0D);
GlStateManager.matrixMode(5888);
GlStateManager.pushMatrix();
GlStateManager.loadIdentity();
GlStateManager.translate(0.0F, 0.0F, -2000.0F);
GL11.glLineWidth(1.0F);
GlStateManager.func_179090_x();
Tessellator tess = Tessellator.getInstance();
WorldRenderer tessellator = tess.getWorldRenderer();
tessellator.startDrawing(1);
int memColR;
for (int lumMem = 0; lumMem < timesFrame.length; ++lumMem)
{
memColR = (lumMem - numRecordedFrameTimes & timesFrame.length - 1) * 100 / timesFrame.length;
memColR += 155;
float memColG = (float)mc.displayHeight;
long memColB = 0L;
if (gcs[lumMem])
{
renderTime(lumMem, timesFrame[lumMem], memColR, memColR / 2, 0, memColG, tessellator);
}
else
{
renderTime(lumMem, timesFrame[lumMem], memColR, memColR, memColR, memColG, tessellator);
memColG -= (float)renderTime(lumMem, timesServer[lumMem], memColR / 2, memColR / 2, memColR / 2, memColG, tessellator);
memColG -= (float)renderTime(lumMem, timesTerrain[lumMem], 0, memColR, 0, memColG, tessellator);
memColG -= (float)renderTime(lumMem, timesVisibility[lumMem], memColR, memColR, 0, memColG, tessellator);
memColG -= (float)renderTime(lumMem, timesChunkUpdate[lumMem], memColR, 0, 0, memColG, tessellator);
memColG -= (float)renderTime(lumMem, timesChunkUpload[lumMem], memColR, 0, memColR, memColG, tessellator);
memColG -= (float)renderTime(lumMem, timesScheduledExecutables[lumMem], 0, 0, memColR, memColG, tessellator);
float var10000 = memColG - (float)renderTime(lumMem, timesTick[lumMem], 0, memColR, memColR, memColG, tessellator);
}
}
tess.draw();
GlStateManager.matrixMode(5889);
GlStateManager.popMatrix();
GlStateManager.matrixMode(5888);
GlStateManager.popMatrix();
GlStateManager.func_179098_w();
float var12 = 1.0F - (float)((double)(System.currentTimeMillis() - memTimeStartMs) / 1000.0D);
var12 = Config.limit(var12, 0.0F, 1.0F);
memColR = (int)(170.0F + var12 * 85.0F);
int var13 = (int)(100.0F + var12 * 55.0F);
int var14 = (int)(10.0F + var12 * 10.0F);
int colMem = memColR << 16 | var13 << 8 | var14;
int posX = 512 / scaledResolution.getScaleFactor() + 2;
int posY = mc.displayHeight / scaledResolution.getScaleFactor() - 8;
GuiIngame var15 = mc.ingameGUI;
GuiIngame.drawRect(posX - 1, posY - 1, posX + 50, posY + 10, -1605349296);
mc.fontRendererObj.drawString(" " + memMbSec + " MB/s", posX, posY, colMem);
renderTimeNano = System.nanoTime() - timeRenderStartNano;
}
}
private static long renderTime(int frameNum, long time, int r, int g, int b, float baseHeight, WorldRenderer tessellator)
{
long heightTime = time / 200000L;
if (heightTime < 3L)
{
return 0L;
}
else
{
tessellator.func_178961_b(r, g, b, 255);
tessellator.addVertex((double)((float)frameNum + 0.5F), (double)(baseHeight - (float)heightTime + 0.5F), 0.0D);
tessellator.addVertex((double)((float)frameNum + 0.5F), (double)(baseHeight + 0.5F), 0.0D);
return heightTime;
}
}
public static boolean isActive()
{
return active;
}
public static class TimerNano
{
public long timeStartNano = 0L;
public long timeNano = 0L;
public void start()
{
if (Lagometer.active)
{
if (this.timeStartNano == 0L)
{
this.timeStartNano = System.nanoTime();
}
}
}
public void end()
{
if (Lagometer.active)
{
if (this.timeStartNano != 0L)
{
this.timeNano += System.nanoTime() - this.timeStartNano;
this.timeStartNano = 0L;
}
}
}
private void reset()
{
this.timeNano = 0L;
this.timeStartNano = 0L;
}
}
}