From d3766dccd810c6c0d4a732e2338f0c389ec55088 Mon Sep 17 00:00:00 2001 From: thefrostypixel Date: Thu, 24 Jul 2025 15:11:24 +0200 Subject: [PATCH] Add line for TPS to FPS module --- .../betterf3/mixin/time/TimeUpdateMixin.java | 47 +++++++++++++++++++ .../betterf3/mixin/time/package-info.java | 4 ++ .../cominixo/betterf3/modules/FpsModule.java | 37 ++++++++++++++- .../me/cominixo/betterf3/utils/Utils.java | 16 +++++++ .../resources/assets/betterf3/lang/en_us.json | 2 + .../src/main/resources/betterf3.mixins.json | 3 +- 6 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 common/src/main/java/me/cominixo/betterf3/mixin/time/TimeUpdateMixin.java create mode 100644 common/src/main/java/me/cominixo/betterf3/mixin/time/package-info.java diff --git a/common/src/main/java/me/cominixo/betterf3/mixin/time/TimeUpdateMixin.java b/common/src/main/java/me/cominixo/betterf3/mixin/time/TimeUpdateMixin.java new file mode 100644 index 00000000..832a9d6b --- /dev/null +++ b/common/src/main/java/me/cominixo/betterf3/mixin/time/TimeUpdateMixin.java @@ -0,0 +1,47 @@ +package me.cominixo.betterf3.mixin.time; + +import io.netty.channel.ChannelHandlerContext; +import me.cominixo.betterf3.modules.FpsModule; +import net.minecraft.network.Connection; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundLoginPacket; +import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * Mixin to count time updates sent by the server. + */ +@Mixin(Connection.class) +public class TimeUpdateMixin { + + /** + * Used to catch the first two time updates received after joining the server as they're usually out of sync with the others. + */ + private int skipTimeUpdates = 2; + + /** + * Counts time updates sent by the server. + * + * @param context Channel Handler Context + * @param packet Time Update Packet + * @param info Callback info + */ + @Inject(at = @At("HEAD"), method = "channelRead0") + private void onPacket(final ChannelHandlerContext context, final Packet packet, final CallbackInfo info) { + if (packet instanceof ClientboundLoginPacket) { + this.skipTimeUpdates = 2; + FpsModule.firstTimeUpdate = Long.MAX_VALUE; + FpsModule.lastTimeUpdates.clear(); + } else if (packet instanceof ClientboundSetTimePacket) { + if (this.skipTimeUpdates > 0) { + this.skipTimeUpdates--; + } else { + FpsModule.firstTimeUpdate = Math.min(FpsModule.firstTimeUpdate, System.currentTimeMillis()); + FpsModule.lastTimeUpdates.add(System.currentTimeMillis()); + } + } + } +} diff --git a/common/src/main/java/me/cominixo/betterf3/mixin/time/package-info.java b/common/src/main/java/me/cominixo/betterf3/mixin/time/package-info.java new file mode 100644 index 00000000..fdc74364 --- /dev/null +++ b/common/src/main/java/me/cominixo/betterf3/mixin/time/package-info.java @@ -0,0 +1,4 @@ +/** + * Time related mixins. + */ +package me.cominixo.betterf3.mixin.time; diff --git a/common/src/main/java/me/cominixo/betterf3/modules/FpsModule.java b/common/src/main/java/me/cominixo/betterf3/modules/FpsModule.java index 742d8d3e..f32c0196 100644 --- a/common/src/main/java/me/cominixo/betterf3/modules/FpsModule.java +++ b/common/src/main/java/me/cominixo/betterf3/modules/FpsModule.java @@ -1,6 +1,8 @@ package me.cominixo.betterf3.modules; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import me.cominixo.betterf3.utils.DebugLine; import me.cominixo.betterf3.utils.Utils; import net.minecraft.ChatFormatting; @@ -44,11 +46,22 @@ public class FpsModule extends BaseModule { */ public final TextColor defaultColorLow = TextColor.fromLegacyFormat(ChatFormatting.RED); + /** + * The millisecond times of the first time update sent by the server. + */ + public static long firstTimeUpdate = Long.MAX_VALUE; + + /** + * The millisecond times of all time updates sent by the server during the last 30 seconds. + */ + public static final List lastTimeUpdates = new ArrayList<>(); + /** * Instantiates a new FPS module. */ public FpsModule() { lines.add(new DebugLine("fps", "format.betterf3.no_format", true)); + lines.add(new DebugLine("tps", "format.betterf3.no_format", true)); lines.get(0).inReducedDebug = true; this.colorHigh = this.defaultColorHigh; @@ -73,12 +86,32 @@ public void update(final Minecraft client) { I18n.get("text.betterf3.line.fps.vsync") : "") .trim(); - final TextColor color = switch (Utils.fpsColor(currentFps)) { + final TextColor fpsColor = switch (Utils.fpsColor(currentFps)) { + case HIGH -> this.colorHigh; + case MEDIUM -> this.colorMed; + case LOW -> this.colorLow; + }; + + lines.get(0).value(Collections.singletonList(Utils.styledText(fpsString, fpsColor))); + + while (lastTimeUpdates.size() > 2 && System.currentTimeMillis() - lastTimeUpdates.getFirst() > 30000) { + lastTimeUpdates.removeFirst(); + } + final int secondsMeasured = (int) Math.max(Math.min(Math.ceil((System.currentTimeMillis() - firstTimeUpdate) / 1000F), 30), 0); + final int currentTps = lastTimeUpdates.size() < 2 ? 0 : Math.round(20000F / Math.max( + System.currentTimeMillis() - lastTimeUpdates.getLast(), + lastTimeUpdates.getLast() - lastTimeUpdates.get(lastTimeUpdates.size() - 2) + )); + final int recentTps = secondsMeasured == 0 ? 0 : Math.round(20F * lastTimeUpdates.size() / secondsMeasured); + + final String tpsString = I18n.get("format.betterf3.tps", currentTps, recentTps, secondsMeasured).trim(); + + final TextColor tpsColor = switch (Utils.tpsColor(currentTps)) { case HIGH -> this.colorHigh; case MEDIUM -> this.colorMed; case LOW -> this.colorLow; }; - lines.get(0).value(Collections.singletonList(Utils.styledText(fpsString, color))); + lines.get(1).value(Collections.singletonList(Utils.styledText(tpsString, tpsColor))); } } diff --git a/common/src/main/java/me/cominixo/betterf3/utils/Utils.java b/common/src/main/java/me/cominixo/betterf3/utils/Utils.java index 17283f32..63095c77 100644 --- a/common/src/main/java/me/cominixo/betterf3/utils/Utils.java +++ b/common/src/main/java/me/cominixo/betterf3/utils/Utils.java @@ -58,6 +58,22 @@ public static FpsEnum fpsColor(final int currentFps) { } } + /** + * Gets tps color. + * + * @param currentTps the current tps + * @return the tps color + */ + public static FpsEnum tpsColor(final int currentTps) { + if (currentTps >= 19) { + return FpsEnum.HIGH; + } else if (currentTps >= 10) { + return FpsEnum.MEDIUM; + } else { + return FpsEnum.LOW; + } + } + /** * Gets percent color. * diff --git a/common/src/main/resources/assets/betterf3/lang/en_us.json b/common/src/main/resources/assets/betterf3/lang/en_us.json index 78779e41..5f3af63b 100644 --- a/common/src/main/resources/assets/betterf3/lang/en_us.json +++ b/common/src/main/resources/assets/betterf3/lang/en_us.json @@ -6,6 +6,7 @@ "format.betterf3.server_tick": "%s at %.0f ms ticks", "format.betterf3.no_format": "%s", "format.betterf3.fps": "%s fps / %s fps %s", + "format.betterf3.tps": "%s tps (%s avg during last %s s)", "format.betterf3.chunklight": "Total: %s Sky: %s Block: %s", "format.betterf3.chunklight_server": "Sky: %s Block: %s", "format.betterf3.rotation": "Yaw: %s Pitch: %s", @@ -149,6 +150,7 @@ "text.betterf3.line.fps": "", "text.betterf3.line.fps.unlimited": "Unlimited", "text.betterf3.line.fps.vsync": "with V-Sync", + "text.betterf3.line.tps": "", "text.betterf3.line.render_distance": "Render Distance", "text.betterf3.line.graphics": "Graphics", "text.betterf3.line.clouds": "Clouds", diff --git a/common/src/main/resources/betterf3.mixins.json b/common/src/main/resources/betterf3.mixins.json index e66c8bfc..8299e22c 100644 --- a/common/src/main/resources/betterf3.mixins.json +++ b/common/src/main/resources/betterf3.mixins.json @@ -12,6 +12,7 @@ "chunk.ClientChunkManagerMixin", "chunk.ClientChunkMapMixin", "debugcrosshair.DebugCrosshairMixin", - "scoreboard.ScoreboardMixin" + "scoreboard.ScoreboardMixin", + "time.TimeUpdateMixin" ] }