diff --git a/src/main/java/de/shiewk/widgets/WidgetUtils.java b/src/main/java/de/shiewk/widgets/WidgetUtils.java index 34c45e7..6da10eb 100644 --- a/src/main/java/de/shiewk/widgets/WidgetUtils.java +++ b/src/main/java/de/shiewk/widgets/WidgetUtils.java @@ -1,6 +1,7 @@ package de.shiewk.widgets; import net.minecraft.client.MinecraftClient; +import net.minecraft.world.tick.TickManager; import java.util.function.BooleanSupplier; @@ -24,4 +25,16 @@ public class WidgetUtils { return MinecraftClient.getInstance().isInSingleplayer(); } + public static float getClientTickRate(){ + float tickRate = 20f; + MinecraftClient client = MinecraftClient.getInstance(); + if (client.world != null) { + TickManager tickManager = client.world.getTickManager(); + if (!tickManager.isFrozen()){ + tickRate = Math.min(tickManager.getTickRate(), 20); + } + } + return tickRate; + } + } diff --git a/src/main/java/de/shiewk/widgets/client/WidgetsModClient.java b/src/main/java/de/shiewk/widgets/client/WidgetsModClient.java index 289caf3..b58cf6f 100644 --- a/src/main/java/de/shiewk/widgets/client/WidgetsModClient.java +++ b/src/main/java/de/shiewk/widgets/client/WidgetsModClient.java @@ -68,5 +68,6 @@ public class WidgetsModClient implements ClientModInitializer { WidgetManager.register(new PlainTextWidget(Identifier.of(WidgetsMod.MOD_ID, "plaintext"))); WidgetManager.register(new TPSWidget(Identifier.of(WidgetsMod.MOD_ID, "tps"))); WidgetManager.register(new BiomeWidget(Identifier.of(WidgetsMod.MOD_ID, "biome"))); + WidgetManager.register(new SpeedWidget(Identifier.of(WidgetsMod.MOD_ID, "speed"))); } } diff --git a/src/main/java/de/shiewk/widgets/widgets/BandwidthWidget.java b/src/main/java/de/shiewk/widgets/widgets/BandwidthWidget.java index 1df03cf..92c84d2 100644 --- a/src/main/java/de/shiewk/widgets/widgets/BandwidthWidget.java +++ b/src/main/java/de/shiewk/widgets/widgets/BandwidthWidget.java @@ -8,7 +8,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.profiler.MultiValueDebugSampleLogImpl; -import net.minecraft.world.tick.TickManager; import java.util.List; import java.util.function.LongFunction; @@ -60,18 +59,11 @@ public class BandwidthWidget extends BasicTextWidget { public void tickWidget() { shouldRender = !(hideInSingleplayer && WidgetUtils.isInSingleplayer()); if (!shouldRender) return; - float tickRate = 20f; - MinecraftClient client = MinecraftClient.getInstance(); - if (client.world != null) { - TickManager tickManager = client.world.getTickManager(); - if (!tickManager.isFrozen()){ - tickRate = Math.min(tickManager.getTickRate(), 20); - } - } + float tickRate = WidgetUtils.getClientTickRate(); t++; if (t >= tickRate){ t = 0; - long avgBytesPerSecond = getAvgBytesPerSecond(client, tickRate); + long avgBytesPerSecond = getAvgBytesPerSecond(MinecraftClient.getInstance(), tickRate); this.renderText = Text.of(unit.sizeFormatter.apply(avgBytesPerSecond)); if (this.dynamicColor){ if (avgBytesPerSecond < 100000){ diff --git a/src/main/java/de/shiewk/widgets/widgets/SpeedWidget.java b/src/main/java/de/shiewk/widgets/widgets/SpeedWidget.java new file mode 100644 index 0000000..767dbeb --- /dev/null +++ b/src/main/java/de/shiewk/widgets/widgets/SpeedWidget.java @@ -0,0 +1,113 @@ +package de.shiewk.widgets.widgets; + +import de.shiewk.widgets.WidgetSettings; +import de.shiewk.widgets.WidgetUtils; +import de.shiewk.widgets.widgets.settings.EnumWidgetSetting; +import de.shiewk.widgets.widgets.settings.IntSliderWidgetSetting; +import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; + +import java.util.List; + +public class SpeedWidget extends BasicTextWidget { + + public enum Unit { + METERS_PER_SECOND("m/s"), + BLOCKS_PER_SECOND("b/s"), + CENTIMETERS_PER_TICK("cm/t"); + + public final String displayName; + + Unit(String displayName) { + this.displayName = displayName; + } + } + + public SpeedWidget(Identifier id) { + super(id, List.of( + new EnumWidgetSetting<>( + "unit", + Text.translatable("widgets.widgets.speed.unit"), + Unit.class, + Unit.METERS_PER_SECOND, + unit -> Text.of(unit.displayName) + ), + new ToggleWidgetSetting("with_x", Text.translatable("widgets.widgets.speed.withX"), true), + new ToggleWidgetSetting("with_y", Text.translatable("widgets.widgets.speed.withY"), false), + new ToggleWidgetSetting("with_z", Text.translatable("widgets.widgets.speed.withZ"), true), + new IntSliderWidgetSetting("digits", Text.translatable("widgets.widgets.speed.digits"), 0, 1, 3), + new IntSliderWidgetSetting("window_size", Text.translatable("widgets.widgets.speed.windowSize"), 3, 10, 60) + )); + } + + private Unit unit = Unit.METERS_PER_SECOND; + private boolean withXVelocity = true; + private boolean withYVelocity = false; + private boolean withZVelocity = true; + private int digitsAfterComma = 1; + private double[] averagingWindow = new double[10]; + private int windowPointer = 0; + + private Vec3d lastPos = new Vec3d(0, 0, 0); + + @Override + public void tickWidget() { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player != null) { + Vec3d lastPos = this.lastPos; + Vec3d newPos = this.lastPos = player.getPos(); + Vec3d velocity = lastPos.subtract(newPos); + double rt = 0; + if (withXVelocity) rt += velocity.getX() * velocity.getX(); + if (withYVelocity) rt += velocity.getY() * velocity.getY(); + if (withZVelocity) rt += velocity.getZ() * velocity.getZ(); + averagingWindow[windowPointer++] = switch (unit){ + case METERS_PER_SECOND, BLOCKS_PER_SECOND -> Math.sqrt(rt) * WidgetUtils.getClientTickRate(); + case CENTIMETERS_PER_TICK -> Math.sqrt(rt) * 100; + }; + } else { + averagingWindow[windowPointer++] = 0d; + } + if (windowPointer >= averagingWindow.length) { + windowPointer = 0; + } + double avg = 0; + for (double v : averagingWindow) { + avg += v; + } + avg /= averagingWindow.length; + renderText = Text.of(reduceDigits(avg) + unit.displayName); + } + + private String reduceDigits(double v) { + if (digitsAfterComma == 0) return String.valueOf((int) Math.floor(v)); + double f = Math.pow(10, digitsAfterComma); + return String.valueOf(Math.floor(v * f) / f); + } + + @Override + public Text getName() { + return Text.translatable("widgets.widgets.speed"); + } + + @Override + public Text getDescription() { + return Text.translatable("widgets.widgets.speed.description"); + } + + @Override + public void onSettingsChanged(WidgetSettings settings) { + super.onSettingsChanged(settings); + this.unit = ((Unit) ((EnumWidgetSetting) settings.optionById("unit")).getValue()); + this.withXVelocity = ((ToggleWidgetSetting) settings.optionById("with_x")).getValue(); + this.withYVelocity = ((ToggleWidgetSetting) settings.optionById("with_y")).getValue(); + this.withZVelocity = ((ToggleWidgetSetting) settings.optionById("with_z")).getValue(); + this.digitsAfterComma = ((IntSliderWidgetSetting) settings.optionById("digits")).getValue(); + this.windowPointer = 0; + this.averagingWindow = new double[((IntSliderWidgetSetting) settings.optionById("window_size")).getValue()]; + } +} diff --git a/src/main/resources/assets/widgets/lang/de_de.json b/src/main/resources/assets/widgets/lang/de_de.json index 2e7cb75..37b96f7 100644 --- a/src/main/resources/assets/widgets/lang/de_de.json +++ b/src/main/resources/assets/widgets/lang/de_de.json @@ -95,5 +95,13 @@ "widgets.widgets.tps": "TPS", "widgets.widgets.tps.description": "Zeigt die TPS im Einzelspielermodus an oder schätzt die TPS im Mehrspielermodus", "widgets.widgets.tps.dynamicColor": "Farbe dynamisch anzeigen", - "widgets.widgets.tps.tps": "%s TPS" + "widgets.widgets.tps.tps": "%s TPS", + "widgets.widgets.speed": "Geschwindigkeit", + "widgets.widgets.speed.description": "Zeigt, wie schnell du dich bewegst.", + "widgets.widgets.speed.digits": "Nachkommastellen", + "widgets.widgets.speed.unit": "Einheit", + "widgets.widgets.speed.windowSize": "Durchschnittsfenstergröße", + "widgets.widgets.speed.withX": "Mit Geschwindigkeit auf der X-Achse", + "widgets.widgets.speed.withY": "Mit Geschwindigkeit auf der Y-Achse", + "widgets.widgets.speed.withZ": "Mit Geschwindigkeit auf der Z-Achse" } \ No newline at end of file diff --git a/src/main/resources/assets/widgets/lang/en_us.json b/src/main/resources/assets/widgets/lang/en_us.json index ec08e77..aa1b278 100644 --- a/src/main/resources/assets/widgets/lang/en_us.json +++ b/src/main/resources/assets/widgets/lang/en_us.json @@ -92,6 +92,14 @@ "widgets.widgets.serverIP": "Server IP", "widgets.widgets.serverIP.description": "Shows the server address", "widgets.widgets.serverIP.dynamicWidth": "Dynamically set widget width", + "widgets.widgets.speed": "Speed", + "widgets.widgets.speed.description": "Shows the speed you are moving at.", + "widgets.widgets.speed.digits": "Digits after comma", + "widgets.widgets.speed.unit": "Unit", + "widgets.widgets.speed.windowSize": "Averaging window size", + "widgets.widgets.speed.withX": "With X-axis velocity", + "widgets.widgets.speed.withY": "With Y-axis velocity", + "widgets.widgets.speed.withZ": "With Z-axis velocity", "widgets.widgets.tps": "TPS", "widgets.widgets.tps.description": "Shows the current TPS when in singleplayer or estimates server TPS when in multiplayer", "widgets.widgets.tps.dynamicColor": "Dynamic Color",