diff --git a/common/src/main/java/xyz/jpenilla/tabtps/common/command/commands/TickInfoCommand.java b/common/src/main/java/xyz/jpenilla/tabtps/common/command/commands/TickInfoCommand.java index 46c4166c..687091a3 100644 --- a/common/src/main/java/xyz/jpenilla/tabtps/common/command/commands/TickInfoCommand.java +++ b/common/src/main/java/xyz/jpenilla/tabtps/common/command/commands/TickInfoCommand.java @@ -135,7 +135,7 @@ private void executeTickInfo(final @NonNull CommandContext ctx) { ? new ArrayDeque<>(Arrays.asList("5s", "1m", "5m", "15m")) : new ArrayDeque<>(Arrays.asList("1m", "5m", "15m")); while (tpsIterator.hasNext()) { - builder.append(TPSUtil.coloredTps(tpsIterator.next(), Theme.DEFAULT.colorScheme())) + builder.append(TPSUtil.coloredTps(tpsIterator.next(), this.tabTPS.platform().tickTimeService().targetTickRate(), Theme.DEFAULT.colorScheme())) .append(space()) .append(text("(", GRAY, ITALIC)) .append(text(tpsDurations.removeFirst(), GRAY, ITALIC)) diff --git a/common/src/main/java/xyz/jpenilla/tabtps/common/display/task/BossBarDisplayTask.java b/common/src/main/java/xyz/jpenilla/tabtps/common/display/task/BossBarDisplayTask.java index ede732ba..e11d197e 100644 --- a/common/src/main/java/xyz/jpenilla/tabtps/common/display/task/BossBarDisplayTask.java +++ b/common/src/main/java/xyz/jpenilla/tabtps/common/display/task/BossBarDisplayTask.java @@ -31,6 +31,7 @@ import xyz.jpenilla.tabtps.common.config.Theme; import xyz.jpenilla.tabtps.common.display.Display; import xyz.jpenilla.tabtps.common.module.ModuleRenderer; +import xyz.jpenilla.tabtps.common.util.TPSUtil; public final class BossBarDisplayTask implements Display { private final TabTPS tabTPS; @@ -78,11 +79,11 @@ private float progress() { } private float msptProgress() { - return ensureInRange(this.tabTPS.platform().tickTimeService().averageMspt() / 50.0f); + return ensureInRange(this.tabTPS.platform().tickTimeService().averageMspt() / this.tabTPS.platform().tickTimeService().targetMspt()); } private float tpsProgress() { - return ensureInRange(this.tabTPS.platform().tickTimeService().recentTps()[0] / 20.0f); + return ensureInRange(this.tabTPS.platform().tickTimeService().recentTps()[0] / this.tabTPS.platform().tickTimeService().targetTickRate()); } private static float ensureInRange(final double value) { @@ -94,9 +95,10 @@ private static float ensureInRange(final double value) { case MSPT: case REVERSE_MSPT: final double mspt = this.tabTPS.platform().tickTimeService().averageMspt(); - if (mspt < 25) { + final float targetMspt = this.tabTPS.platform().tickTimeService().targetMspt(); + if (mspt < TPSUtil.scaleMspt(25, targetMspt)) { return this.settings.colors().goodPerformance(); - } else if (mspt < 40) { + } else if (mspt < TPSUtil.scaleMspt(40, targetMspt)) { return this.settings.colors().mediumPerformance(); } else { return this.settings.colors().lowPerformance(); @@ -104,9 +106,10 @@ private static float ensureInRange(final double value) { case REVERSE_TPS: case TPS: final double tps = this.tabTPS.platform().tickTimeService().recentTps()[0]; - if (tps > 18.50D) { + final float targetTps = this.tabTPS.platform().tickTimeService().targetTickRate(); + if (tps > TPSUtil.scaleTps(18.50f, targetTps)) { return this.settings.colors().goodPerformance(); - } else if (tps > 15.00D) { + } else if (tps > TPSUtil.scaleTps(15.00f, targetTps)) { return this.settings.colors().mediumPerformance(); } else { return this.settings.colors().lowPerformance(); diff --git a/common/src/main/java/xyz/jpenilla/tabtps/common/module/MSPTModule.java b/common/src/main/java/xyz/jpenilla/tabtps/common/module/MSPTModule.java index c26f019f..d45db0f9 100644 --- a/common/src/main/java/xyz/jpenilla/tabtps/common/module/MSPTModule.java +++ b/common/src/main/java/xyz/jpenilla/tabtps/common/module/MSPTModule.java @@ -45,6 +45,6 @@ public MSPTModule( @Override public @NonNull Component display() { - return TPSUtil.coloredMspt(this.tabTPS.platform().tickTimeService().averageMspt(), this.theme.colorScheme()); + return TPSUtil.coloredMspt(this.tabTPS.platform().tickTimeService().averageMspt(), this.tabTPS.platform().tickTimeService().targetMspt(), this.theme.colorScheme()); } } diff --git a/common/src/main/java/xyz/jpenilla/tabtps/common/module/TPSModule.java b/common/src/main/java/xyz/jpenilla/tabtps/common/module/TPSModule.java index 77e17017..0274c9b4 100644 --- a/common/src/main/java/xyz/jpenilla/tabtps/common/module/TPSModule.java +++ b/common/src/main/java/xyz/jpenilla/tabtps/common/module/TPSModule.java @@ -45,6 +45,6 @@ public TPSModule( @Override public @NonNull Component display() { - return TPSUtil.coloredTps(this.tabTPS.platform().tickTimeService().recentTps()[0], this.theme.colorScheme()); + return TPSUtil.coloredTps(this.tabTPS.platform().tickTimeService().recentTps()[0], this.tabTPS.platform().tickTimeService().targetTickRate(), this.theme.colorScheme()); } } diff --git a/common/src/main/java/xyz/jpenilla/tabtps/common/service/TickTimeService.java b/common/src/main/java/xyz/jpenilla/tabtps/common/service/TickTimeService.java index c3d637cb..d1083819 100644 --- a/common/src/main/java/xyz/jpenilla/tabtps/common/service/TickTimeService.java +++ b/common/src/main/java/xyz/jpenilla/tabtps/common/service/TickTimeService.java @@ -29,4 +29,10 @@ public interface TickTimeService { double averageMspt(); double @NonNull [] recentTps(); + + float targetTickRate(); + + default float targetMspt() { + return 1000.0f / this.targetTickRate(); + } } diff --git a/common/src/main/java/xyz/jpenilla/tabtps/common/util/FloatSupplier.java b/common/src/main/java/xyz/jpenilla/tabtps/common/util/FloatSupplier.java new file mode 100644 index 00000000..b8b025d2 --- /dev/null +++ b/common/src/main/java/xyz/jpenilla/tabtps/common/util/FloatSupplier.java @@ -0,0 +1,29 @@ +/* + * This file is part of TabTPS, licensed under the MIT License. + * + * Copyright (c) 2020-2024 Jason Penilla + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package xyz.jpenilla.tabtps.common.util; + +@FunctionalInterface +public interface FloatSupplier { + float get(); +} diff --git a/common/src/main/java/xyz/jpenilla/tabtps/common/util/TPSUtil.java b/common/src/main/java/xyz/jpenilla/tabtps/common/util/TPSUtil.java index 8998bf7c..e70b6419 100644 --- a/common/src/main/java/xyz/jpenilla/tabtps/common/util/TPSUtil.java +++ b/common/src/main/java/xyz/jpenilla/tabtps/common/util/TPSUtil.java @@ -54,13 +54,27 @@ private TPSUtil() { return FORMAT.format(value); } - public static @NonNull Component coloredTps(final double tps, final Theme.@NonNull Colors colors) { + public static float scaleTps(final float tps, final float targetTickRate) { + if (Float.compare(20, targetTickRate) == 0) { + return tps; + } + return tps / 20 * targetTickRate; + } + + public static double scaleMspt(final float ms, final float targetMspt) { + if (Float.compare(50, targetMspt) == 0) { + return ms; + } + return ms / 50 * targetMspt; + } + + public static @NonNull Component coloredTps(final double tps, final float targetTps, final Theme.@NonNull Colors colors) { final TextColor color1; final TextColor color2; - if (tps >= 18.5) { + if (tps >= scaleTps(18.5f, targetTps)) { color1 = colors.goodPerformance(); color2 = colors.goodPerformanceSecondary(); - } else if (tps > 15.0) { + } else if (tps > scaleTps(15.0f, targetTps)) { color1 = colors.mediumPerformance(); color2 = colors.mediumPerformanceSecondary(); } else { @@ -78,13 +92,13 @@ public static double toMilliseconds(final double time) { return time * 1.0E-6D; } - public static @NonNull Component coloredMspt(final double mspt, final Theme.@NonNull Colors colors) { + public static @NonNull Component coloredMspt(final double mspt, final float targetMspt, final Theme.@NonNull Colors colors) { final TextColor color1; final TextColor color2; - if (mspt <= 25.0) { + if (mspt <= scaleMspt(25.0f, targetMspt)) { color1 = colors.goodPerformance(); color2 = colors.goodPerformanceSecondary(); - } else if (mspt <= 40) { + } else if (mspt <= scaleMspt(40.0f, targetMspt)) { color1 = colors.mediumPerformance(); color2 = colors.mediumPerformanceSecondary(); } else { @@ -94,7 +108,7 @@ public static double toMilliseconds(final double time) { return gradient(formatDouble(mspt), color1, color2); } - public static @NonNull List formatTickTimes(final @NonNull List> times) { + public static @NonNull List formatTickTimes(final @NonNull List> times, final float targetMspt) { final Component header = text() .color(GRAY) .append( @@ -119,13 +133,14 @@ public static double toMilliseconds(final double time) { output.add(formatStatistics( branch, text(pair.first()), - pair.second() + pair.second(), + targetMspt )); } return output; } - private static @NonNull Component formatStatistics(final @NonNull String branch, final @NonNull Component time, final long @NonNull [] times) { + private static @NonNull Component formatStatistics(final @NonNull String branch, final @NonNull Component time, final long @NonNull [] times, final float targetMspt) { final LongSummaryStatistics statistics = LongStream.of(times).filter(NOT_ZERO).summaryStatistics(); return Components.ofChildren( space(), @@ -133,11 +148,11 @@ public static double toMilliseconds(final double time) { space(), time.color(GRAY), text(" - ", WHITE), - TPSUtil.coloredMspt(TPSUtil.toMilliseconds(statistics.getAverage()), Theme.DEFAULT.colorScheme()), + TPSUtil.coloredMspt(TPSUtil.toMilliseconds(statistics.getAverage()), targetMspt, Theme.DEFAULT.colorScheme()), text(", ", WHITE), - TPSUtil.coloredMspt(TPSUtil.toMilliseconds(statistics.getMin()), Theme.DEFAULT.colorScheme()), + TPSUtil.coloredMspt(TPSUtil.toMilliseconds(statistics.getMin()), targetMspt, Theme.DEFAULT.colorScheme()), text(", ", WHITE), - TPSUtil.coloredMspt(TPSUtil.toMilliseconds(statistics.getMax()), Theme.DEFAULT.colorScheme()) + TPSUtil.coloredMspt(TPSUtil.toMilliseconds(statistics.getMax()), targetMspt, Theme.DEFAULT.colorScheme()) ); } diff --git a/fabric/src/main/java/xyz/jpenilla/tabtps/fabric/command/FabricTickInfoCommandFormatter.java b/fabric/src/main/java/xyz/jpenilla/tabtps/fabric/command/FabricTickInfoCommandFormatter.java index 3683570f..68e5f776 100644 --- a/fabric/src/main/java/xyz/jpenilla/tabtps/fabric/command/FabricTickInfoCommandFormatter.java +++ b/fabric/src/main/java/xyz/jpenilla/tabtps/fabric/command/FabricTickInfoCommandFormatter.java @@ -47,6 +47,6 @@ public FabricTickInfoCommandFormatter(final @NonNull TabTPSFabric tabTPSFabric) Pair.of("5s", server.tickTimes5s().times()), Pair.of("10s", server.tickTimes10s().times()), Pair.of("60s", server.tickTimes60s().times()) - )); + ), this.tabTPSFabric.tickTimeService().targetMspt()); } } diff --git a/fabric/src/main/java/xyz/jpenilla/tabtps/fabric/mixin/MinecraftServerMixin.java b/fabric/src/main/java/xyz/jpenilla/tabtps/fabric/mixin/MinecraftServerMixin.java index c6f20ae0..fd0b67d8 100644 --- a/fabric/src/main/java/xyz/jpenilla/tabtps/fabric/mixin/MinecraftServerMixin.java +++ b/fabric/src/main/java/xyz/jpenilla/tabtps/fabric/mixin/MinecraftServerMixin.java @@ -27,6 +27,7 @@ import java.math.RoundingMode; import java.util.function.BooleanSupplier; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.ServerTickRateManager; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; @@ -65,6 +66,8 @@ abstract class MinecraftServerMixin implements MinecraftServerAccess { @Shadow private int tickCount; @Shadow @Final private long[] tickTimesNanos; + @Shadow public abstract ServerTickRateManager tickRateManager(); + @Inject(method = "tickServer", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) public void injectTick(final BooleanSupplier var1, final CallbackInfo ci, final long tickStartTimeNanos, final long tickDurationNanos) { this.tickTimes5s.add(this.tickCount, tickDurationNanos); @@ -98,6 +101,14 @@ public void injectTick(final BooleanSupplier var1, final CallbackInfo ci, final return tps; } + public float tabtps$targetTickRate() { + return this.tickRateManager().tickrate(); + } + + public float tabtps$targetMspt() { + return this.tickRateManager().millisecondsPerTick(); + } + @Override public @NonNull TickTimes tickTimes5s() { return this.tickTimes5s; diff --git a/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/TabTPSPlugin.java b/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/TabTPSPlugin.java index f80e7234..6f37f3e1 100644 --- a/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/TabTPSPlugin.java +++ b/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/TabTPSPlugin.java @@ -138,7 +138,7 @@ private void setupCommandManager() { private void registerCommands() { if (PaperLib.getMinecraftVersion() >= 15 && PaperLib.isPaper()) { - TickInfoCommand.withFormatter(this.tabTPS, this.tabTPS.commands(), new PaperTickInfoCommandFormatter()).register(); + TickInfoCommand.withFormatter(this.tabTPS, this.tabTPS.commands(), new PaperTickInfoCommandFormatter(this)).register(); } else { TickInfoCommand.defaultFormatter(this.tabTPS, this.tabTPS.commands()).register(); } diff --git a/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/command/PaperTickInfoCommandFormatter.java b/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/command/PaperTickInfoCommandFormatter.java index 485aef70..7376d1d1 100644 --- a/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/command/PaperTickInfoCommandFormatter.java +++ b/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/command/PaperTickInfoCommandFormatter.java @@ -32,10 +32,13 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.incendo.cloud.type.tuple.Pair; import xyz.jpenilla.pluginbase.legacy.Crafty; +import xyz.jpenilla.tabtps.common.TabTPSPlatform; import xyz.jpenilla.tabtps.common.command.commands.TickInfoCommand; import xyz.jpenilla.tabtps.common.util.TPSUtil; public final class PaperTickInfoCommandFormatter implements TickInfoCommand.Formatter { + private final TabTPSPlatform platform; + private final Class _MinecraftServer = Crafty.needNMSClassOrElse( "MinecraftServer", "net.minecraft.server.MinecraftServer" @@ -52,7 +55,8 @@ public final class PaperTickInfoCommandFormatter implements TickInfoCommand.Form private final Field _tickTimes10s; private final Field _tickTimes60s; - public PaperTickInfoCommandFormatter() { + public PaperTickInfoCommandFormatter(final TabTPSPlatform platform) { + this.platform = platform; try { this._tickTimes5s = Crafty.needField(this._MinecraftServer, "tickTimes5s"); this._tickTimes10s = Crafty.needField(this._MinecraftServer, "tickTimes10s"); @@ -78,7 +82,7 @@ public PaperTickInfoCommandFormatter() { Pair.of("5s", times5s), Pair.of("10s", times10s), Pair.of("60s", times60s) - )); + ), this.platform.tickTimeService().targetMspt()); } catch (final Throwable throwable) { throw new IllegalStateException("Failed to retrieve tick time statistics", throwable); } diff --git a/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/service/PaperTickTimeService.java b/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/service/PaperTickTimeService.java index 2c9441b0..2631bcbc 100644 --- a/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/service/PaperTickTimeService.java +++ b/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/service/PaperTickTimeService.java @@ -23,11 +23,20 @@ */ package xyz.jpenilla.tabtps.spigot.service; +import java.lang.reflect.Method; import org.bukkit.Bukkit; import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.NotNull; import xyz.jpenilla.tabtps.common.service.TickTimeService; +import xyz.jpenilla.tabtps.common.util.FloatSupplier; public final class PaperTickTimeService implements TickTimeService { + private final FloatSupplier targetTickRateGetter; + + public PaperTickTimeService() { + this.targetTickRateGetter = makeTickRateGetter(); + } + @Override public double averageMspt() { return Bukkit.getAverageTickTime(); @@ -37,4 +46,27 @@ public double averageMspt() { public double @NonNull [] recentTps() { return Bukkit.getTPS(); } + + @Override + public float targetTickRate() { + return this.targetTickRateGetter.get(); + } + + private static @NotNull FloatSupplier makeTickRateGetter() { + try { + final Method getServerTickManager = Bukkit.class.getDeclaredMethod("getServerTickManager"); + final Object serverTickManager = getServerTickManager.invoke(null); + final Method getTickRate = serverTickManager.getClass().getMethod("getTickRate"); + getTickRate.setAccessible(true); + return () -> { + try { + return (float) getTickRate.invoke(serverTickManager); + } catch (final ReflectiveOperationException e) { + throw new RuntimeException(e); + } + }; + } catch (final ReflectiveOperationException e) { + return () -> 20; + } + } } diff --git a/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/service/SpigotTickTimeService.java b/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/service/SpigotTickTimeService.java index d480a68c..a91aa826 100644 --- a/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/service/SpigotTickTimeService.java +++ b/spigot/src/main/java/xyz/jpenilla/tabtps/spigot/service/SpigotTickTimeService.java @@ -38,4 +38,9 @@ public double averageMspt() { public double @NonNull [] recentTps() { return spigotReflection().recentTps(); } + + @Override + public float targetTickRate() { + return 20; + } } diff --git a/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/TabTPSPlugin.java b/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/TabTPSPlugin.java index 64382c44..b01acb86 100644 --- a/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/TabTPSPlugin.java +++ b/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/TabTPSPlugin.java @@ -102,7 +102,7 @@ public TabTPSPlugin( })); this.commandManager.parserMapper().cloudNumberSuggestions(true); this.tabTPS = new TabTPS(this); - TickInfoCommand.withFormatter(this.tabTPS(), this.tabTPS().commands(), new SpongeTickInfoCommandFormatter()).register(); + TickInfoCommand.withFormatter(this.tabTPS(), this.tabTPS().commands(), new SpongeTickInfoCommandFormatter(this)).register(); new SpongePingCommand(this, this.tabTPS.commands()).register(); game.eventManager().registerListeners(this.pluginContainer, new UserListener(this)); this.logger.info("Done initializing TabTPS."); diff --git a/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/command/SpongeTickInfoCommandFormatter.java b/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/command/SpongeTickInfoCommandFormatter.java index 9344d09d..31ed54e5 100644 --- a/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/command/SpongeTickInfoCommandFormatter.java +++ b/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/command/SpongeTickInfoCommandFormatter.java @@ -29,11 +29,18 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.incendo.cloud.type.tuple.Pair; import org.spongepowered.api.Sponge; +import xyz.jpenilla.tabtps.common.TabTPSPlatform; import xyz.jpenilla.tabtps.common.command.commands.TickInfoCommand; import xyz.jpenilla.tabtps.common.util.TPSUtil; import xyz.jpenilla.tabtps.sponge.access.MinecraftServerAccess; public final class SpongeTickInfoCommandFormatter implements TickInfoCommand.Formatter { + private final TabTPSPlatform platform; + + public SpongeTickInfoCommandFormatter(final TabTPSPlatform platform) { + this.platform = platform; + } + @Override public @NonNull List formatTickTimes() { final MinecraftServerAccess server = (MinecraftServerAccess) Sponge.server(); @@ -41,6 +48,6 @@ public final class SpongeTickInfoCommandFormatter implements TickInfoCommand.For Pair.of("5s", server.tickTimes5s().times()), Pair.of("10s", server.tickTimes10s().times()), Pair.of("60s", server.tickTimes60s().times()) - )); + ), this.platform.tickTimeService().targetMspt()); } } diff --git a/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/mixin/MinecraftServerMixin.java b/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/mixin/MinecraftServerMixin.java index d8d7bb32..81e3fa9a 100644 --- a/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/mixin/MinecraftServerMixin.java +++ b/sponge/src/main/java/xyz/jpenilla/tabtps/sponge/mixin/MinecraftServerMixin.java @@ -27,6 +27,7 @@ import java.math.RoundingMode; import java.util.function.BooleanSupplier; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.ServerTickRateManager; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; @@ -65,6 +66,8 @@ abstract class MinecraftServerMixin implements MinecraftServerAccess { @Shadow private int tickCount; @Shadow @Final private long[] tickTimesNanos; + @Shadow public abstract ServerTickRateManager tickRateManager(); + @Inject(method = "tickServer", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) public void injectTick(final BooleanSupplier var1, final CallbackInfo ci, final long tickStartTimeNanos, final long tickDurationNanos) { this.tickTimes5s.add(this.tickCount, tickDurationNanos); @@ -98,6 +101,14 @@ public void injectTick(final BooleanSupplier var1, final CallbackInfo ci, final return tps; } + public float tabtps$targetTickRate() { + return this.tickRateManager().tickrate(); + } + + public float tabtps$targetMspt() { + return this.tickRateManager().millisecondsPerTick(); + } + @Override public @NonNull TickTimes tickTimes5s() { return this.tickTimes5s;