From 490db4f5d6480ace45d424b376c4248053475e91 Mon Sep 17 00:00:00 2001 From: G4me4u Date: Thu, 2 Jan 2020 21:47:28 +0100 Subject: [PATCH 1/2] Added a way to ensure tickrate compatibility with other mods --- src/main/java/carpet/helpers/TickSpeed.java | 85 +++++++++++++++---- .../MinecraftServer_tickspeedMixin.java | 29 +++++-- 2 files changed, 91 insertions(+), 23 deletions(-) diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 8cf8982d..40b7c68c 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -1,18 +1,22 @@ package carpet.helpers; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + import carpet.CarpetServer; import carpet.utils.Messenger; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.BaseText; public class TickSpeed { public static final int PLAYER_GRACE = 2; public static float tickrate = 20.0f; - public static long mspt = 50l; + public static float mspt = 50.0f; public static long time_bias = 0; public static long time_warp_start_time = 0; public static long time_warp_scheduled_ticks = 0; @@ -24,6 +28,13 @@ public class TickSpeed public static boolean is_paused = false; public static boolean is_superHot = false; + /** + * Functional interface that listens for tickrate changes. This is + * implemented to allow tickrate compatibility with other mods etc. + */ + private static final Map> tickrateListeners = new HashMap<>(); + private static final float MIN_TICKRATE = 0.01f; + public static void reset_player_active_timeout() { if (player_active_timeout < PLAYER_GRACE) @@ -37,17 +48,6 @@ public class TickSpeed player_active_timeout = PLAYER_GRACE+ticks; } - public static void tickrate(float rate) - { - tickrate = rate; - mspt = (long)(1000.0/tickrate); - if (mspt <=0) - { - mspt = 1l; - tickrate = 1000.0f; - } - } - public static BaseText tickrate_advance(PlayerEntity player, int advance, String callback, ServerCommandSource source) { if (0 == advance) @@ -156,8 +156,61 @@ public class TickSpeed } } - - + } + + public static void tickrate(float rate) + { + tickrate = rate; + long mspt = (long)(1000.0 / tickrate); + if (mspt <= 0L) + { + mspt = 1L; + tickrate = 1000.0f; + } + + TickSpeed.mspt = (float)mspt; + + notifyTickrateListeners("carpet"); + } + + private static void tickrateChanged(String modId, float rate) + { + // Other mods might change the tickrate in a slightly + // different way. Also allow for tickrates that don't + // divide into 1000 here. + + if (rate < MIN_TICKRATE) + { + rate = MIN_TICKRATE; + } + + tickrate = rate; + mspt = 1000.0f / tickrate; + + notifyTickrateListeners(modId); + } + + private static void notifyTickrateListeners(String originModId) + { + synchronized (tickrateListeners) + { + for (Map.Entry> listenerEntry : tickrateListeners.entrySet()) + { + if (originModId == null || !originModId.equals(listenerEntry.getKey())) + { + listenerEntry.getValue().accept(originModId, Float.valueOf(tickrate)); + } + } + } + } + + public static BiConsumer establishTickrateLink(String modId, BiConsumer tickrateListener) + { + synchronized (tickrateListeners) + { + tickrateListeners.put(modId, tickrateListener); + } + return TickSpeed::tickrateChanged; } } diff --git a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java index a9d86dd0..8d120405 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java @@ -44,6 +44,12 @@ public abstract class MinecraftServer_tickspeedMixin @Shadow private volatile boolean loading; CarpetProfiler.ProfilerToken currentSection; + + private float carpetMsptAccum = 0.0f; + + /** + * To ensure compatibility with other mods we should allow milliseconds + */ // Cancel a while statement @Redirect(method = "run", at = @At(value = "FIELD", target = "Lnet/minecraft/server/MinecraftServer;running:Z")) @@ -67,29 +73,38 @@ public abstract class MinecraftServer_tickspeedMixin { CarpetProfiler.start_tick_profiling(); } - long mspt = 0L; + long msThisTick = 0L; long long_1 = 0L; if (TickSpeed.time_warp_start_time != 0 && TickSpeed.continueWarp()) { //making sure server won't flop after the warp or if the warp is interrupted this.timeReference = this.field_4557 = SystemUtil.getMeasuringTimeMs(); + carpetMsptAccum = TickSpeed.mspt; } else { - mspt = TickSpeed.mspt; // regular tick + if (Math.abs(carpetMsptAccum - TickSpeed.mspt) > 1.0f) + { + // Tickrate changed. Ensure that we use the correct value. + carpetMsptAccum = TickSpeed.mspt; + } + + msThisTick = (long)carpetMsptAccum; // regular tick + carpetMsptAccum += TickSpeed.mspt - msThisTick; + long_1 = SystemUtil.getMeasuringTimeMs() - this.timeReference; } //end tick deciding //smoothed out delay to include mcpt component. With 50L gives defaults. - if (long_1 > /*2000L*/1000L+20*mspt && this.timeReference - this.field_4557 >= /*15000L*/10000L+100*mspt) + if (long_1 > /*2000L*/1000L+20*TickSpeed.mspt && this.timeReference - this.field_4557 >= /*15000L*/10000L+100*TickSpeed.mspt) { - long long_2 = long_1 / mspt;//50L; + long long_2 = (long)(long_1 / TickSpeed.mspt);//50L; LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", long_1, long_2); - this.timeReference += long_2 * mspt;//50L; + this.timeReference += (long)(long_2 * TickSpeed.mspt);//50L; this.field_4557 = this.timeReference; } - this.timeReference += mspt;//50L; + this.timeReference += msThisTick;//50L; if (this.profilerStartQueued) { this.profilerStartQueued = false; @@ -101,7 +116,7 @@ public abstract class MinecraftServer_tickspeedMixin this.tick(TickSpeed.time_warp_start_time != 0 ? ()->true : this::shouldKeepTicking); this.profiler.swap("nextTickWait"); this.field_19249 = true; - this.field_19248 = Math.max(SystemUtil.getMeasuringTimeMs() + /*50L*/ mspt, this.timeReference); + this.field_19248 = Math.max(SystemUtil.getMeasuringTimeMs() + /*50L*/ msThisTick, this.timeReference); this.method_16208(); this.profiler.pop(); this.profiler.endTick(); From 08539da5cc70e2baa9e59ed2f84e56e7fe6fa60c Mon Sep 17 00:00:00 2001 From: G4me4u Date: Thu, 2 Jan 2020 22:23:54 +0100 Subject: [PATCH 2/2] Renamed establishTickrateLink to addTickrateListener --- src/main/java/carpet/helpers/TickSpeed.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 40b7c68c..79d05576 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -204,7 +204,7 @@ public class TickSpeed } } - public static BiConsumer establishTickrateLink(String modId, BiConsumer tickrateListener) + public static BiConsumer addTickrateListener(String modId, BiConsumer tickrateListener) { synchronized (tickrateListeners) {