diff --git a/src/main/java/carpet/commands/TickCommand.java b/src/main/java/carpet/commands/TickCommand.java index 19167216..491b6c6a 100644 --- a/src/main/java/carpet/commands/TickCommand.java +++ b/src/main/java/carpet/commands/TickCommand.java @@ -79,8 +79,8 @@ public class TickCommand private static int queryTps(CommandSourceStack source) { - Messenger.m(source, "w Current tps is: ",String.format("wb %.1f", TickSpeed.tickrate)); - return (int)TickSpeed.tickrate; + Messenger.m(source, "w Current tps is: ",String.format("wb %.1f", TickSpeed.gTRM().map(trm -> trm.tickrate).orElse(20.0f))); + return (int)(float)TickSpeed.gTRM().map(trm -> trm.tickrate).orElse(20.0f); } private static int setWarp(CommandSourceStack source, int advance, String tail_command) @@ -132,9 +132,9 @@ public class TickCommand private static int toggleSuperHot(CommandSourceStack source) { - TickSpeed.is_superHot = !TickSpeed.is_superHot; - ServerNetworkHandler.updateSuperHotStateToConnectedPlayers(); - if (TickSpeed.is_superHot) + TickSpeed.gTRM().ifPresent(trm -> trm.is_superHot = !trm.is_superHot); + ServerNetworkHandler.updateSuperHotStateToConnectedPlayers(source.getServer()); + if (TickSpeed.gTRM().map(trm -> trm.is_superHot).orElse(false)) { Messenger.m(source, "gi Superhot enabled"); } diff --git a/src/main/java/carpet/fakes/MinecraftServerInterface.java b/src/main/java/carpet/fakes/MinecraftServerInterface.java index 8b045436..ce2466d1 100644 --- a/src/main/java/carpet/fakes/MinecraftServerInterface.java +++ b/src/main/java/carpet/fakes/MinecraftServerInterface.java @@ -3,6 +3,7 @@ package carpet.fakes; import java.util.Map; import java.util.function.BooleanSupplier; +import carpet.helpers.TickRateManager; import carpet.script.CarpetScriptServer; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceKey; @@ -23,4 +24,6 @@ public interface MinecraftServerInterface void addScriptServer(CarpetScriptServer scriptServer); CarpetScriptServer getScriptServer(); + + TickRateManager getTickRateManager(); } diff --git a/src/main/java/carpet/helpers/TickRateManager.java b/src/main/java/carpet/helpers/TickRateManager.java new file mode 100644 index 00000000..2666f351 --- /dev/null +++ b/src/main/java/carpet/helpers/TickRateManager.java @@ -0,0 +1,305 @@ +package carpet.helpers; + +import carpet.CarpetServer; +import carpet.network.ServerNetworkHandler; +import carpet.utils.Messenger; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.network.chat.Component; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +public class TickRateManager +{ + public static final int PLAYER_GRACE = 2; + public float tickrate = 20.0f; + public float mspt = 50.0f; + public long time_bias = 0; + public long time_warp_start_time = 0; + public long time_warp_scheduled_ticks = 0; + public ServerPlayer time_advancerer = null; + public String tick_warp_callback = null; + public CommandSourceStack tick_warp_sender = null; + public int player_active_timeout = 0; + public boolean process_entities = true; + private boolean deepFreeze = false; + private boolean is_paused = false; + public boolean is_superHot = false; + + private MinecraftServer server; + + public TickRateManager(MinecraftServer server) { + this.server = server; + } + + + /** + * @return Whether or not the game is in a frozen state. + * You should normally use {@link #process_entities} instead, + * since that one accounts for tick steps and superhot + */ + public boolean isPaused() + { + return is_paused; + } + + /** + * Whether or not the game is deeply frozen. + * This can be used for things that you may not normally want + * to freeze, but may need to in some situations. + * This should be checked with {@link #process_entities} to make sure the + * current tick is actually frozen, not only the game + * + * @return Whether or not the game is deeply frozen. + */ + public boolean deeplyFrozen() + { + return deepFreeze; + } + + /** + * Used to update the frozen state of the game. + * Handles connected clients as well. + * + * @param isPaused Whether or not the game is paused + * @param isDeepFreeze Whether or not the game is deeply frozen + */ + public void setFrozenState(boolean isPaused, boolean isDeepFreeze) + { + is_paused = isPaused; + deepFreeze = isPaused ? isDeepFreeze : false; + ServerNetworkHandler.updateFrozenStateToConnectedPlayers(server); + } + + + public void reset_player_active_timeout() + { + if (player_active_timeout < PLAYER_GRACE) + { + player_active_timeout = PLAYER_GRACE; + ServerNetworkHandler.updateTickPlayerActiveTimeoutToConnectedPlayers(server); + } + } + + public void reset() // do we need reset? + { + tickrate = 20.0f; + mspt = 50.0f; + time_bias = 0; + time_warp_start_time = 0; + time_warp_scheduled_ticks = 0; + time_advancerer = null; + tick_warp_callback = null; + tick_warp_sender = null; + player_active_timeout = 0; + process_entities = true; + deepFreeze = false; + is_paused = false; + is_superHot = false; + notifyTickrateListeners("carpet"); + } + + public void add_ticks_to_run_in_pause(int ticks) + { + player_active_timeout = PLAYER_GRACE + ticks; + ServerNetworkHandler.updateTickPlayerActiveTimeoutToConnectedPlayers(server); + } + + public Component tickrate_advance(ServerPlayer player, int advance, String callback, CommandSourceStack source) + { + if (0 == advance) + { + tick_warp_callback = null; + if (source != tick_warp_sender) + { + tick_warp_sender = null; + } + if (time_bias > 0) + { + finish_time_warp(); + tick_warp_sender = null; + return Messenger.c("gi Warp interrupted"); + } + return Messenger.c("ri No warp in progress"); + } + if (time_bias > 0) + { + String who = "Another player"; + if (time_advancerer != null) + { + who = time_advancerer.getScoreboardName(); + } + return Messenger.c("l " + who + " is already advancing time at the moment. Try later or ask them"); + } + time_advancerer = player; + time_warp_start_time = System.nanoTime(); + time_warp_scheduled_ticks = advance; + time_bias = advance; + tick_warp_callback = callback; + tick_warp_sender = source; + return Messenger.c("gi Warp speed ...."); + } + + public void finish_time_warp() + { + + long completed_ticks = time_warp_scheduled_ticks - time_bias; + double milis_to_complete = System.nanoTime() - time_warp_start_time; + if (milis_to_complete == 0.0) + { + milis_to_complete = 1.0; + } + milis_to_complete /= 1000000.0; + int tps = (int) (1000.0D * completed_ticks / milis_to_complete); + double mspt = (1.0 * milis_to_complete) / completed_ticks; + time_warp_scheduled_ticks = 0; + time_warp_start_time = 0; + if (tick_warp_callback != null) + { + Commands icommandmanager = tick_warp_sender.getServer().getCommands(); + try + { + icommandmanager.performPrefixedCommand(tick_warp_sender, tick_warp_callback); + } + catch (Throwable var23) + { + if (time_advancerer != null) + { + Messenger.m(time_advancerer, "r Command Callback failed - unknown error: ", "rb /" + tick_warp_callback, "/" + tick_warp_callback); + } + } + tick_warp_callback = null; + tick_warp_sender = null; + } + if (time_advancerer != null) + { + Messenger.m(time_advancerer, String.format("gi ... Time warp completed with %d tps, or %.2f mspt", tps, mspt)); + time_advancerer = null; + } + else + { + Messenger.print_server_message(CarpetServer.minecraft_server, String.format("... Time warp completed with %d tps, or %.2f mspt", tps, mspt)); + } + time_bias = 0; + + } + + public boolean continueWarp() + { + if (!process_entities) + // Returning false so we don't have to run at max speed when doing nothing + { + return false; + } + if (time_bias > 0) + { + if (time_bias == time_warp_scheduled_ticks) //first call after previous tick, adjust start time + { + time_warp_start_time = System.nanoTime(); + } + time_bias -= 1; + return true; + } + else + { + finish_time_warp(); + return false; + } + } + + public void tick() + { + if (player_active_timeout > 0) + { + player_active_timeout--; + } + if (is_paused) + { + process_entities = player_active_timeout >= PLAYER_GRACE; + } + else if (is_superHot) + { + process_entities = player_active_timeout > 0; + } + else + { + process_entities = true; + } + } + + /** + * Functional interface that listens for tickrate changes. This is + * implemented to allow tickrate compatibility with other mods etc. + */ + private final Map> tickrateListeners = new HashMap<>(); + private static final float MIN_TICKRATE = 0.01f; + + //unused - mod compat reasons + public void tickrate(float rate) + { + tickrate(rate, true); + } + + public void tickrate(float rate, boolean update) + { + tickrate = rate; + long msptt = (long) (1000.0 / tickrate); + if (msptt <= 0L) + { + msptt = 1L; + tickrate = 1000.0f; + } + + this.mspt = msptt; + + if (update) + { + notifyTickrateListeners("carpet"); + } + } + + private 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 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)); + } + } + } + ServerNetworkHandler.updateTickSpeedToConnectedPlayers(server); + } + + public BiConsumer addTickrateListener(String modId, BiConsumer tickrateListener) + { + synchronized (tickrateListeners) + { + tickrateListeners.put(modId, tickrateListener); + } + return this::tickrateChanged; + } +} diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 04bf36ff..6392b8a5 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -2,7 +2,10 @@ package carpet.helpers; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.function.BiConsumer; + +import carpet.fakes.MinecraftServerInterface; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; @@ -13,40 +16,38 @@ import carpet.utils.Messenger; public class TickSpeed { - public static final int PLAYER_GRACE = 2; - public static float tickrate = 20.0f; - 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; - public static ServerPlayer time_advancerer = null; - public static String tick_warp_callback = null; - public static CommandSourceStack tick_warp_sender = null; - public static int player_active_timeout = 0; - public static boolean process_entities = true; - private static boolean deepFreeze = false; - private static boolean is_paused = false; - public static boolean is_superHot = false; + public static Optional gTRM() { + if (CarpetServer.minecraft_server == null) return Optional.empty(); + return Optional.of(((MinecraftServerInterface)CarpetServer.minecraft_server).getTickRateManager()); + } + + public static boolean process_entities() { + return gTRM().map(trm -> trm.process_entities).orElse(true); + } + + public static float mspt() { + return gTRM().map(trm -> trm.mspt).orElse(50.0f); + } /** * @return Whether or not the game is in a frozen state. - * You should normally use {@link #process_entities} instead, + * You should normally use {@link #process_entities()} instead, * since that one accounts for tick steps and superhot */ public static boolean isPaused() { - return is_paused; + return gTRM().map(TickRateManager::isPaused).orElse(false); } /** * Whether or not the game is deeply frozen. * This can be used for things that you may not normally want * to freeze, but may need to in some situations. - * This should be checked with {@link #process_entities} to make sure the + * This should be checked with {@link #process_entities()} to make sure the * current tick is actually frozen, not only the game * @return Whether or not the game is deeply frozen. */ public static boolean deeplyFrozen() { - return deepFreeze; + return gTRM().map(TickRateManager::deeplyFrozen).orElse(false); } /** @@ -56,9 +57,7 @@ public class TickSpeed * @param isDeepFreeze Whether or not the game is deeply frozen */ public static void setFrozenState(boolean isPaused, boolean isDeepFreeze) { - is_paused = isPaused; - deepFreeze = isPaused ? isDeepFreeze : false; - ServerNetworkHandler.updateFrozenStateToConnectedPlayers(); + gTRM().ifPresent(trm -> trm.setFrozenState(isPaused, isDeepFreeze)); } /** @@ -70,132 +69,111 @@ public class TickSpeed public static void reset_player_active_timeout() { - if (player_active_timeout < PLAYER_GRACE) - { - player_active_timeout = PLAYER_GRACE; - ServerNetworkHandler.updateTickPlayerActiveTimeoutToConnectedPlayers(); - } + gTRM().ifPresent(TickRateManager::reset_player_active_timeout); } public static void reset() { - tickrate = 20.0f; - mspt = 50.0f; - time_bias = 0; - time_warp_start_time = 0; - time_warp_scheduled_ticks = 0; - time_advancerer = null; - tick_warp_callback = null; - tick_warp_sender = null; - player_active_timeout = 0; - process_entities = true; - deepFreeze = false; - is_paused = false; - is_superHot = false; - notifyTickrateListeners("carpet"); + gTRM().ifPresent(TickRateManager::reset); } public static void add_ticks_to_run_in_pause(int ticks) { - player_active_timeout = PLAYER_GRACE+ticks; - ServerNetworkHandler.updateTickPlayerActiveTimeoutToConnectedPlayers(); + gTRM().ifPresent(trm -> trm.add_ticks_to_run_in_pause(ticks)); } public static Component tickrate_advance(ServerPlayer player, int advance, String callback, CommandSourceStack source) { - if (0 == advance) - { - tick_warp_callback = null; - if (source != tick_warp_sender) tick_warp_sender = null; - if (time_bias > 0) - { - finish_time_warp(); - tick_warp_sender = null; - return Messenger.c("gi Warp interrupted"); - } - return Messenger.c("ri No warp in progress"); - } - if (time_bias > 0) - { - String who = "Another player"; - if (time_advancerer != null) who = time_advancerer.getScoreboardName(); - return Messenger.c("l "+who+" is already advancing time at the moment. Try later or ask them"); - } - time_advancerer = player; - time_warp_start_time = System.nanoTime(); - time_warp_scheduled_ticks = advance; - time_bias = advance; - tick_warp_callback = callback; - tick_warp_sender = source; - return Messenger.c("gi Warp speed ...."); + return gTRM().map(trm -> trm.tickrate_advance(player, advance, callback, source)).orElse(Messenger.c("ri Tickrate management not enabled")); } public static void finish_time_warp() { - - long completed_ticks = time_warp_scheduled_ticks - time_bias; - double milis_to_complete = System.nanoTime()-time_warp_start_time; - if (milis_to_complete == 0.0) - { - milis_to_complete = 1.0; - } - milis_to_complete /= 1000000.0; - int tps = (int) (1000.0D*completed_ticks/milis_to_complete); - double mspt = (1.0*milis_to_complete)/completed_ticks; - time_warp_scheduled_ticks = 0; - time_warp_start_time = 0; - if (tick_warp_callback != null) - { - Commands icommandmanager = tick_warp_sender.getServer().getCommands(); - try - { - icommandmanager.performPrefixedCommand(tick_warp_sender, tick_warp_callback); - } - catch (Throwable var23) - { - if (time_advancerer != null) - { - Messenger.m(time_advancerer, "r Command Callback failed - unknown error: ", "rb /"+tick_warp_callback,"/"+tick_warp_callback); - } - } - tick_warp_callback = null; - tick_warp_sender = null; - } - if (time_advancerer != null) - { - Messenger.m(time_advancerer, String.format("gi ... Time warp completed with %d tps, or %.2f mspt",tps, mspt )); - time_advancerer = null; - } - else - { - Messenger.print_server_message(CarpetServer.minecraft_server, String.format("... Time warp completed with %d tps, or %.2f mspt",tps, mspt )); - } - time_bias = 0; - + gTRM().ifPresent(TickRateManager::finish_time_warp); } public static boolean continueWarp() { - if (!process_entities) - // Returning false so we don't have to run at max speed when doing nothing - return false; - if (time_bias > 0) - { - if (time_bias == time_warp_scheduled_ticks) //first call after previous tick, adjust start time - { - time_warp_start_time = System.nanoTime(); - } - time_bias -= 1; - return true; - } - else - { - finish_time_warp(); - return false; - } + return gTRM().map(TickRateManager::continueWarp).orElse(false); } public static void tick() + { + gTRM().ifPresent(TickRateManager::tick); + } + //unused - mod compat reasons + public static void tickrate(float rate) {tickrate(rate, true);} + public static void tickrate(float rate, boolean update) + { + gTRM().ifPresent(trm -> trm.tickrate(rate, update)); + } + + + + + public static BiConsumer addTickrateListener(String modId, BiConsumer tickrateListener) + { + return gTRM().map(trm -> trm.addTickrateListener(modId, tickrateListener)).orElse(null); + } + + + + + // client only + + private static float tickrate = 20.0f; + private static float mspt = 50.0f; + private static int player_active_timeout = 0; + private static boolean process_entities = true; + private static boolean deepFreeze = false; + private static boolean is_paused = false; + private static boolean is_superHot = false; + + public static void tickrateClient(float rate) + { + tickrate = rate; + long msptt = (long) (1000.0 / tickrate); + if (msptt <= 0L) + { + msptt = 1L; + tickrate = 1000.0f; + } + + mspt = msptt; + } + + public static float msptClient() { + return mspt; + } + + public static boolean process_entitiesClient() + { + return process_entities; + } + + public static boolean isIs_superHotClient() + { + return is_superHot; + } + + public static void setPlayer_active_timeoutClient(int timeout) + { + player_active_timeout = timeout; + } + + + public static void setFrozenStateClient(boolean isPaused, boolean isDeepFreeze) + { + is_paused = isPaused; + deepFreeze = isPaused ? isDeepFreeze : false; + } + + public static void setSuperHotClient(boolean isSuperHot) + { + is_superHot = isSuperHot; + } + + public static void tickClient() { if (player_active_timeout > 0) { @@ -203,7 +181,7 @@ public class TickSpeed } if (is_paused) { - process_entities = player_active_timeout >= PLAYER_GRACE; + process_entities = player_active_timeout >= TickRateManager.PLAYER_GRACE; } else if (is_superHot) { @@ -214,62 +192,6 @@ public class TickSpeed process_entities = true; } } - //unused - mod compat reasons - public static void tickrate(float rate) {tickrate(rate, true);} - public static void tickrate(float rate, boolean update) - { - tickrate = rate; - long mspt = (long)(1000.0 / tickrate); - if (mspt <= 0L) - { - mspt = 1L; - tickrate = 1000.0f; - } - - TickSpeed.mspt = mspt; - - if (update) 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)); - } - } - } - ServerNetworkHandler.updateTickSpeedToConnectedPlayers(); - } - - public static BiConsumer addTickrateListener(String modId, BiConsumer tickrateListener) - { - synchronized (tickrateListeners) - { - tickrateListeners.put(modId, tickrateListener); - } - return TickSpeed::tickrateChanged; - } + } diff --git a/src/main/java/carpet/logging/HUDController.java b/src/main/java/carpet/logging/HUDController.java index 31e3735d..1a6bf09f 100644 --- a/src/main/java/carpet/logging/HUDController.java +++ b/src/main/java/carpet/logging/HUDController.java @@ -1,7 +1,9 @@ package carpet.logging; import carpet.CarpetServer; +import carpet.fakes.MinecraftServerInterface; import carpet.helpers.HopperCounter; +import carpet.helpers.TickRateManager; import carpet.helpers.TickSpeed; import carpet.logging.logHelpers.PacketCounter; import carpet.utils.Messenger; @@ -117,16 +119,17 @@ public class HUDController private static Component [] send_tps_display(MinecraftServer server) { final OptionalDouble averageTPS = Arrays.stream(server.tickTimes).average(); + TickRateManager trm = ((MinecraftServerInterface)server).getTickRateManager(); if (averageTPS.isEmpty()) { return new Component[]{Component.literal("No TPS data available")}; } double MSPT = Arrays.stream(server.tickTimes).average().getAsDouble() * 1.0E-6D; - double TPS = 1000.0D / Math.max((TickSpeed.time_warp_start_time != 0)?0.0:TickSpeed.mspt, MSPT); + double TPS = 1000.0D / Math.max((trm.time_warp_start_time != 0)?0.0:trm.mspt, MSPT); if (TickSpeed.isPaused()) { TPS = 0; } - String color = Messenger.heatmap_color(MSPT,TickSpeed.mspt); + String color = Messenger.heatmap_color(MSPT,trm.mspt); return new Component[]{Messenger.c( "g TPS: ", String.format(Locale.US, "%s %.1f",color, TPS), "g MSPT: ", String.format(Locale.US,"%s %.1f", color, MSPT))}; diff --git a/src/main/java/carpet/mixins/BoundTickingBlockEntity_tickMixin.java b/src/main/java/carpet/mixins/BoundTickingBlockEntity_tickMixin.java index 7e0383d2..834c4c3e 100644 --- a/src/main/java/carpet/mixins/BoundTickingBlockEntity_tickMixin.java +++ b/src/main/java/carpet/mixins/BoundTickingBlockEntity_tickMixin.java @@ -34,7 +34,7 @@ public class BoundTickingBlockEntity_tickMixin )) private void checkProcessBEs(BlockEntityTicker blockEntityTicker, Level world, BlockPos pos, BlockState state, T blockEntity) { - if (TickSpeed.process_entities) blockEntityTicker.tick(world, pos, state, blockEntity); + if (TickSpeed.process_entities()) blockEntityTicker.tick(world, pos, state, blockEntity); } @Inject(method = "tick()V", at = @At("RETURN")) diff --git a/src/main/java/carpet/mixins/DistanceManager_tickMixin.java b/src/main/java/carpet/mixins/DistanceManager_tickMixin.java index ff5ca448..19fc1ec3 100644 --- a/src/main/java/carpet/mixins/DistanceManager_tickMixin.java +++ b/src/main/java/carpet/mixins/DistanceManager_tickMixin.java @@ -18,6 +18,6 @@ public class DistanceManager_tickMixin { // pausing expiry of tickets // that will prevent also chunks from unloading, so require a deep frozen state - if (!TickSpeed.process_entities && TickSpeed.deeplyFrozen()) ticketTickCounter--; + if (!TickSpeed.process_entities() && TickSpeed.deeplyFrozen()) ticketTickCounter--; } } diff --git a/src/main/java/carpet/mixins/LevelRenderer_pausedShakeMixin.java b/src/main/java/carpet/mixins/LevelRenderer_pausedShakeMixin.java index 40eb1933..44b99aaa 100644 --- a/src/main/java/carpet/mixins/LevelRenderer_pausedShakeMixin.java +++ b/src/main/java/carpet/mixins/LevelRenderer_pausedShakeMixin.java @@ -25,7 +25,7 @@ public class LevelRenderer_pausedShakeMixin private float changeTickPhase(float previous) { initial = previous; - if (!TickSpeed.process_entities) + if (!TickSpeed.process_entitiesClient()) return ((MinecraftClientInferface)minecraft).getPausedTickDelta(); return previous; } diff --git a/src/main/java/carpet/mixins/Level_tickMixin.java b/src/main/java/carpet/mixins/Level_tickMixin.java index cde0cdc1..18e4447b 100644 --- a/src/main/java/carpet/mixins/Level_tickMixin.java +++ b/src/main/java/carpet/mixins/Level_tickMixin.java @@ -86,8 +86,18 @@ public abstract class Level_tickMixin implements LevelInterface @Inject(method = "guardEntityTick", at = @At("HEAD"), cancellable = true) private void startEntity(Consumer consumer_1, Entity e, CallbackInfo ci) { - if (!(TickSpeed.process_entities || (e instanceof Player) || (TickSpeed.is_superHot && isClientSide && e.getControllingPassenger() instanceof Player))) - ci.cancel(); + // this shows that probably tick speed controller needs to be accessible through level referring to servers on server and client on clientLevel + if (isClientSide) { + if (!(TickSpeed.process_entitiesClient() || (e instanceof Player) || TickSpeed.isIs_superHotClient() && e.getControllingPassenger() instanceof Player)) + { + ci.cancel(); + } + } else { + if (!(TickSpeed.gTRM().map(trm -> trm.process_entities).orElse(true) || (e instanceof Player))) + { + ci.cancel(); + } + } entitySection = CarpetProfiler.start_entity_section((Level) (Object) this, e, CarpetProfiler.TYPE.ENTITY); } diff --git a/src/main/java/carpet/mixins/MinecraftMixin.java b/src/main/java/carpet/mixins/MinecraftMixin.java index 03c086e7..6a871aea 100644 --- a/src/main/java/carpet/mixins/MinecraftMixin.java +++ b/src/main/java/carpet/mixins/MinecraftMixin.java @@ -26,9 +26,15 @@ public class MinecraftMixin @Inject(at = @At("HEAD"), method = "tick") private void onClientTick(CallbackInfo info) { if (this.level != null) { - if (CarpetServer.minecraft_server == null) - TickSpeed.tick(); - if (!TickSpeed.process_entities) + TickSpeed.tickClient(); + if (CarpetServer.minecraft_server == null) // remote client only ? no - now any client + { + + } else { + // hmm, server should tick, rgiht? + //TickSpeed.tick(); + } + if (!TickSpeed.process_entitiesClient()) CarpetClient.shapes.renewShapes(); } } diff --git a/src/main/java/carpet/mixins/MinecraftServer_scarpetMixin.java b/src/main/java/carpet/mixins/MinecraftServer_scarpetMixin.java index 27591cbb..baaae692 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_scarpetMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_scarpetMixin.java @@ -89,7 +89,7 @@ public abstract class MinecraftServer_scarpetMixin extends ReentrantBlockableEve )) public void tickTasks(BooleanSupplier booleanSupplier_1, CallbackInfo ci) { - if (!TickSpeed.process_entities) + if (!TickSpeed.process_entities()) return; TICK.onTick((MinecraftServer) (Object) this); NETHER_TICK.onTick((MinecraftServer) (Object) this); diff --git a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java index aaae5b0f..7ae968b3 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java @@ -1,5 +1,7 @@ package carpet.mixins; +import carpet.fakes.MinecraftServerInterface; +import carpet.helpers.TickRateManager; import carpet.helpers.TickSpeed; import carpet.patches.CopyProfilerResult; import carpet.utils.CarpetProfiler; @@ -25,7 +27,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.function.BooleanSupplier; @Mixin(value = MinecraftServer.class, priority = Integer.MAX_VALUE - 10) -public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableEventLoop +public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableEventLoop implements MinecraftServerInterface { @Shadow private volatile boolean running; @@ -67,6 +69,20 @@ public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableE private float carpetMsptAccum = 0.0f; + private TickRateManager tickRateManager; + + @Inject(method = "", at = @At("RETURN")) + private void onInit(CallbackInfo ci) + { + tickRateManager = new TickRateManager((MinecraftServer)(Object)this); + } + + @Override + public TickRateManager getTickRateManager() + { + return tickRateManager; + } + /** * To ensure compatibility with other mods we should allow milliseconds */ @@ -95,32 +111,33 @@ public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableE } long msThisTick = 0L; long long_1 = 0L; - if (TickSpeed.time_warp_start_time != 0 && TickSpeed.continueWarp()) + float mspt = tickRateManager.mspt; + if (tickRateManager.time_warp_start_time != 0 && TickSpeed.continueWarp()) { //making sure server won't flop after the warp or if the warp is interrupted this.nextTickTime = this.lastOverloadWarning = Util.getMillis(); - carpetMsptAccum = TickSpeed.mspt; + carpetMsptAccum = mspt; } else { - if (Math.abs(carpetMsptAccum - TickSpeed.mspt) > 1.0f) + if (Math.abs(carpetMsptAccum - mspt) > 1.0f) { // Tickrate changed. Ensure that we use the correct value. - carpetMsptAccum = TickSpeed.mspt; + carpetMsptAccum = mspt; } msThisTick = (long)carpetMsptAccum; // regular tick - carpetMsptAccum += TickSpeed.mspt - msThisTick; + carpetMsptAccum += mspt - msThisTick; long_1 = Util.getMillis() - this.nextTickTime; } //end tick deciding //smoothed out delay to include mcpt component. With 50L gives defaults. - if (long_1 > /*2000L*/1000L+20*TickSpeed.mspt && this.nextTickTime - this.lastOverloadWarning >= /*15000L*/10000L+100*TickSpeed.mspt) + if (long_1 > /*2000L*/1000L+20*mspt && this.nextTickTime - this.lastOverloadWarning >= /*15000L*/10000L+100*mspt) { - long long_2 = (long)(long_1 / TickSpeed.mspt);//50L; + long long_2 = (long)(long_1 / mspt);//50L; LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", long_1, long_2); - this.nextTickTime += (long)(long_2 * TickSpeed.mspt);//50L; + this.nextTickTime += (long)(long_2 * mspt);//50L; this.lastOverloadWarning = this.nextTickTime; } @@ -134,9 +151,9 @@ public abstract class MinecraftServer_tickspeedMixin extends ReentrantBlockableE //this.startMonitor(tickDurationMonitor); this.startMetricsRecordingTick(); this.profiler.push("tick"); - this.tickServer(TickSpeed.time_warp_start_time != 0 ? ()->true : this::haveTime); + this.tickServer(TickSpeed.gTRM().map(trm -> trm.time_warp_start_time).orElse(0L) != 0 ? ()->true : this::haveTime); this.profiler.popPush("nextTickWait"); - if (TickSpeed.time_warp_start_time != 0) // clearing all hanging tasks no matter what when warping + if (TickSpeed.gTRM().map(trm -> trm.time_warp_start_time).orElse(0L) != 0) // clearing all hanging tasks no matter what when warping { while(this.runEveryTask()) {Thread.yield();} } diff --git a/src/main/java/carpet/mixins/PlayerTabOverlayMixin.java b/src/main/java/carpet/mixins/PlayerTabOverlayMixin.java index a8fa51db..7fe50203 100644 --- a/src/main/java/carpet/mixins/PlayerTabOverlayMixin.java +++ b/src/main/java/carpet/mixins/PlayerTabOverlayMixin.java @@ -12,6 +12,7 @@ public abstract class PlayerTabOverlayMixin implements PlayerListHudInterface @Shadow private Component header; + @Override public boolean hasFooterOrHeader() { return footer != null || header != null; diff --git a/src/main/java/carpet/mixins/ServerChunkCache_tickMixin.java b/src/main/java/carpet/mixins/ServerChunkCache_tickMixin.java index b82bf3dd..dfbe7e66 100644 --- a/src/main/java/carpet/mixins/ServerChunkCache_tickMixin.java +++ b/src/main/java/carpet/mixins/ServerChunkCache_tickMixin.java @@ -78,7 +78,7 @@ public abstract class ServerChunkCache_tickMixin private boolean skipChunkTicking(ServerLevel serverWorld) { boolean debug = serverWorld.isDebug(); - if (!TickSpeed.process_entities) + if (!TickSpeed.process_entities()) { // simplified chunk tick iteration assuming world is frozen otherwise as suggested by Hadron67 // to be kept in sync with the original injection source diff --git a/src/main/java/carpet/mixins/ServerFunctionManager_tickMixin.java b/src/main/java/carpet/mixins/ServerFunctionManager_tickMixin.java index a1b46112..b4aab974 100644 --- a/src/main/java/carpet/mixins/ServerFunctionManager_tickMixin.java +++ b/src/main/java/carpet/mixins/ServerFunctionManager_tickMixin.java @@ -16,7 +16,7 @@ public class ServerFunctionManager_tickMixin @Inject(method = "tick", at = @At("HEAD"), cancellable = true) private void beforeDatapacks(CallbackInfo ci) { - if (!TickSpeed.process_entities) ci.cancel(); + if (!TickSpeed.process_entities()) ci.cancel(); else currentSection = CarpetProfiler.start_section(null, "Datapacks", CarpetProfiler.TYPE.GENERAL); } diff --git a/src/main/java/carpet/mixins/ServerLevel_tickMixin.java b/src/main/java/carpet/mixins/ServerLevel_tickMixin.java index fd6a8748..23a60e5c 100644 --- a/src/main/java/carpet/mixins/ServerLevel_tickMixin.java +++ b/src/main/java/carpet/mixins/ServerLevel_tickMixin.java @@ -159,13 +159,13 @@ public abstract class ServerLevel_tickMixin extends Level )) private void tickWorldBorder(WorldBorder worldBorder) { - if (TickSpeed.process_entities) worldBorder.tick(); + if (TickSpeed.process_entities()) worldBorder.tick(); } @Inject(method = "advanceWeatherCycle", cancellable = true, at = @At("HEAD")) private void tickWeather(CallbackInfo ci) { - if (!TickSpeed.process_entities) ci.cancel(); + if (!TickSpeed.process_entities()) ci.cancel(); } @Redirect(method = "tick", at = @At( @@ -174,7 +174,7 @@ public abstract class ServerLevel_tickMixin extends Level )) private void tickTimeConditionally(ServerLevel serverWorld) { - if (TickSpeed.process_entities) tickTime(); + if (TickSpeed.process_entities()) tickTime(); } @Redirect(method = "tick", at = @At( @@ -183,7 +183,7 @@ public abstract class ServerLevel_tickMixin extends Level )) private boolean tickPendingBlocks(ServerLevel serverWorld) { - if (!TickSpeed.process_entities) return true; + if (!TickSpeed.process_entities()) return true; return serverWorld.isDebug(); // isDebug() } @@ -193,7 +193,7 @@ public abstract class ServerLevel_tickMixin extends Level )) private void tickConditionally(Raids raidManager) { - if (TickSpeed.process_entities) raidManager.tick(); + if (TickSpeed.process_entities()) raidManager.tick(); } @Redirect(method = "tick", at = @At( @@ -202,6 +202,6 @@ public abstract class ServerLevel_tickMixin extends Level )) private void tickConditionally(ServerLevel serverWorld) { - if (TickSpeed.process_entities) runBlockEvents(); + if (TickSpeed.process_entities()) runBlockEvents(); } } diff --git a/src/main/java/carpet/mixins/Timer_tickSpeedMixin.java b/src/main/java/carpet/mixins/Timer_tickSpeedMixin.java index 57994cac..c8e4f1fe 100644 --- a/src/main/java/carpet/mixins/Timer_tickSpeedMixin.java +++ b/src/main/java/carpet/mixins/Timer_tickSpeedMixin.java @@ -14,9 +14,9 @@ public class Timer_tickSpeedMixin { target = "Lnet/minecraft/client/Timer;msPerTick:F" )) private float adjustTickSpeed(Timer counter) { - if (CarpetSettings.smoothClientAnimations && TickSpeed.process_entities) + if (CarpetSettings.smoothClientAnimations && TickSpeed.process_entitiesClient()) { - return Math.max(50.0f, TickSpeed.mspt); + return Math.max(50.0f, TickSpeed.msptClient()); } return 50f; } diff --git a/src/main/java/carpet/network/ClientNetworkHandler.java b/src/main/java/carpet/network/ClientNetworkHandler.java index 698d8cff..29277402 100644 --- a/src/main/java/carpet/network/ClientNetworkHandler.java +++ b/src/main/java/carpet/network/ClientNetworkHandler.java @@ -65,15 +65,15 @@ public class ClientNetworkHandler } } }); - dataHandlers.put("TickRate", (p, t) -> TickSpeed.tickrate(((NumericTag)t).getAsFloat(), false)); + dataHandlers.put("TickRate", (p, t) -> TickSpeed.tickrateClient(((NumericTag)t).getAsFloat())); dataHandlers.put("TickingState", (p, t) -> { CompoundTag tickingState = (CompoundTag)t; - TickSpeed.setFrozenState(tickingState.getBoolean("is_paused"), tickingState.getBoolean("deepFreeze")); + TickSpeed.setFrozenStateClient(tickingState.getBoolean("is_paused"), tickingState.getBoolean("deepFreeze")); }); dataHandlers.put("SuperHotState", (p, t) -> { - TickSpeed.is_superHot = ((ByteTag) t).equals(ByteTag.ONE); + TickSpeed.setSuperHotClient(((ByteTag) t).equals(ByteTag.ONE)); }); - dataHandlers.put("TickPlayerActiveTimeout", (p, t) -> TickSpeed.player_active_timeout = ((NumericTag)t).getAsInt()); + dataHandlers.put("TickPlayerActiveTimeout", (p, t) -> TickSpeed.setPlayer_active_timeoutClient(((NumericTag)t).getAsInt())); dataHandlers.put("scShape", (p, t) -> { // deprecated // and unused // should remove for 1.17 if (CarpetClient.shapes != null) CarpetClient.shapes.addShape((CompoundTag)t); diff --git a/src/main/java/carpet/network/ServerNetworkHandler.java b/src/main/java/carpet/network/ServerNetworkHandler.java index 7d0fd0f6..7a80ae60 100644 --- a/src/main/java/carpet/network/ServerNetworkHandler.java +++ b/src/main/java/carpet/network/ServerNetworkHandler.java @@ -23,6 +23,7 @@ import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; public class ServerNetworkHandler @@ -144,10 +145,10 @@ public class ServerNetworkHandler } } - public static void updateTickSpeedToConnectedPlayers() + public static void updateTickSpeedToConnectedPlayers(MinecraftServer server) { if (CarpetSettings.superSecretSetting) return; - for (ServerPlayer player : remoteCarpetPlayers.keySet()) + for (ServerPlayer player : validCarpetPlayers) { player.connection.send(new ClientboundCustomPayloadPacket( CarpetClient.CARPET_CHANNEL, @@ -156,10 +157,10 @@ public class ServerNetworkHandler } } - public static void updateFrozenStateToConnectedPlayers() + public static void updateFrozenStateToConnectedPlayers(MinecraftServer server) { if (CarpetSettings.superSecretSetting) return; - for (ServerPlayer player : remoteCarpetPlayers.keySet()) + for (ServerPlayer player : validCarpetPlayers) { player.connection.send(new ClientboundCustomPayloadPacket( CarpetClient.CARPET_CHANNEL, @@ -168,10 +169,10 @@ public class ServerNetworkHandler } } - public static void updateSuperHotStateToConnectedPlayers() + public static void updateSuperHotStateToConnectedPlayers(MinecraftServer server) { if(CarpetSettings.superSecretSetting) return; - for (ServerPlayer player : remoteCarpetPlayers.keySet()) + for (ServerPlayer player : validCarpetPlayers) { player.connection.send(new ClientboundCustomPayloadPacket( CarpetClient.CARPET_CHANNEL, @@ -180,10 +181,10 @@ public class ServerNetworkHandler } } - public static void updateTickPlayerActiveTimeoutToConnectedPlayers() + public static void updateTickPlayerActiveTimeoutToConnectedPlayers(MinecraftServer server) { if (CarpetSettings.superSecretSetting) return; - for (ServerPlayer player : remoteCarpetPlayers.keySet()) + for (ServerPlayer player : validCarpetPlayers) { player.connection.send(new ClientboundCustomPayloadPacket( CarpetClient.CARPET_CHANNEL, @@ -256,7 +257,7 @@ public class ServerNetworkHandler } private DataBuilder withTickRate() { - tag.putFloat("TickRate", TickSpeed.tickrate); + tag.putFloat("TickRate", TickSpeed.gTRM().map(trm -> trm.tickrate).orElse(20.0f)); return this; } private DataBuilder withFrozenState() @@ -269,12 +270,12 @@ public class ServerNetworkHandler } private DataBuilder withSuperHotState() { - tag.putBoolean("SuperHotState", TickSpeed.is_superHot); + tag.putBoolean("SuperHotState", TickSpeed.gTRM().map(trm -> trm.is_superHot).orElse(false)); return this; } private DataBuilder withTickPlayerActiveTimeout() { - tag.putInt("TickPlayerActiveTimeout", TickSpeed.player_active_timeout); + tag.putInt("TickPlayerActiveTimeout", TickSpeed.gTRM().map(trm -> trm.player_active_timeout).orElse(0)); return this; } private DataBuilder withRule(CarpetRule rule) diff --git a/src/main/java/carpet/patches/TickSyncedBorderExtent.java b/src/main/java/carpet/patches/TickSyncedBorderExtent.java index f0c87319..4051dcea 100644 --- a/src/main/java/carpet/patches/TickSyncedBorderExtent.java +++ b/src/main/java/carpet/patches/TickSyncedBorderExtent.java @@ -89,13 +89,13 @@ public class TickSyncedBorderExtent implements WorldBorder.BorderExtent double ms; if (server == null) { - ms = TickSpeed.mspt; + ms = TickSpeed.mspt(); } else { ms = Arrays.stream(server.tickTimes).average().orElseThrow(IllegalStateException::new) * 1.0E-6D; } - double tps = 1_000.0D / Math.max((TickSpeed.time_warp_start_time != 0) ? 0.0 : TickSpeed.mspt, ms); + double tps = 1_000.0D / Math.max((TickSpeed.gTRM().map(trm -> trm.time_warp_start_time).orElse(0L) != 0) ? 0.0 : TickSpeed.mspt(), ms); return (long) ((this.tickDuration - this.ticks) / tps * 1_000); } diff --git a/src/main/java/carpet/script/external/Carpet.java b/src/main/java/carpet/script/external/Carpet.java index 700e7b97..2d3660ea 100644 --- a/src/main/java/carpet/script/external/Carpet.java +++ b/src/main/java/carpet/script/external/Carpet.java @@ -136,7 +136,7 @@ public class Carpet public static boolean isTickProcessingPaused() { - return !TickSpeed.process_entities; + return !TickSpeed.process_entities(); } public static void handleExtensionsAPI(CarpetExpression expression)