Refactored Feature to Mod (renamed)
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
package org.saturnclient.mod.mods;
|
||||
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
import org.saturnclient.config.property.BoolProperty;
|
||||
import org.saturnclient.config.property.Property;
|
||||
import org.saturnclient.mod.HudMod;
|
||||
import org.saturnclient.mod.Mod;
|
||||
import org.saturnclient.mod.ModLayout;
|
||||
import org.saturnclient.mod.ModSpec;
|
||||
|
||||
/**
|
||||
* TpsMod estimates the server's ticks-per-second by measuring the
|
||||
* elapsed real time between consecutive world-time packets.
|
||||
*
|
||||
* TPS calculation is event-driven: the networking layer (or mixin)
|
||||
* calls {@link #onTimePacket(long)} whenever a time-update packet
|
||||
* arrives. No ModuleProvider is required because there is no
|
||||
* per-frame polling of the engine.
|
||||
*/
|
||||
public class TpsMod extends Mod implements HudMod {
|
||||
|
||||
private static final BoolProperty enabled = Property.bool(false);
|
||||
private static final ModLayout layout = new ModLayout(60, Fonts.getHeight());
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// TPS sampling state (static — shared across all instances)
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
private static final int SAMPLE_COUNT = 2;
|
||||
private static final double[] samples = new double[SAMPLE_COUNT];
|
||||
|
||||
static {
|
||||
java.util.Arrays.fill(samples, 20.0);
|
||||
}
|
||||
|
||||
private static long lastWorldAge = -1L;
|
||||
private static long lastRealTime = -1L;
|
||||
private static double currentTps = 20.0;
|
||||
private static int sampleIndex = 0;
|
||||
private static int samplesFilled = SAMPLE_COUNT;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
public TpsMod() {
|
||||
super(
|
||||
new ModSpec("TPS Display", "tps")
|
||||
.description("Displays the server's ticks per second")
|
||||
.version("v0.2.0")
|
||||
.tags("Utility"),
|
||||
enabled.named("Enabled"),
|
||||
layout.prop());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Packet hook (called by the networking mixin)
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Must be called every time the client receives a world-time packet
|
||||
* carrying the updated {@code worldAge} value.
|
||||
*/
|
||||
public static void onTimePacket(long worldAge) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (lastWorldAge != -1L && lastRealTime != -1L) {
|
||||
long tickDelta = worldAge - lastWorldAge;
|
||||
long timeDelta = now - lastRealTime;
|
||||
|
||||
if (timeDelta > 0 && tickDelta > 0) {
|
||||
double sample = Math.min((tickDelta / (double) timeDelta) * 1000.0, 20.0);
|
||||
|
||||
samples[sampleIndex % SAMPLE_COUNT] = sample;
|
||||
sampleIndex++;
|
||||
samplesFilled = Math.min(samplesFilled + 1, SAMPLE_COUNT);
|
||||
|
||||
double sum = 0;
|
||||
for (int i = 0; i < samplesFilled; i++)
|
||||
sum += samples[i];
|
||||
currentTps = sum / samplesFilled;
|
||||
}
|
||||
}
|
||||
|
||||
lastWorldAge = worldAge;
|
||||
lastRealTime = now;
|
||||
}
|
||||
|
||||
/** Resets TPS history (e.g. on server disconnect). */
|
||||
public static void reset() {
|
||||
lastWorldAge = -1L;
|
||||
lastRealTime = -1L;
|
||||
currentTps = 20.0;
|
||||
sampleIndex = 0;
|
||||
samplesFilled = SAMPLE_COUNT;
|
||||
java.util.Arrays.fill(samples, 20.0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// HudMod
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void renderHud(RenderScope scope) {
|
||||
renderTps(currentTps, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDummy(RenderScope scope) {
|
||||
renderTps(20.0, scope);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Rendering
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
private void renderTps(double tps, RenderScope scope) {
|
||||
String text = String.format("%.1f TPS", tps);
|
||||
scope.drawText(text, 0, 0, layout.font.value, layout.fgColor.value);
|
||||
layout.width = Fonts.getWidth(text, layout.font.value);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Mod contract
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public ModLayout getDimensions() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled(boolean e) {
|
||||
enabled.value = e;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user