diff --git a/gradle.properties b/gradle.properties index 8c444153..dc4ec7e8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.7.3+build.176 # Mod Properties - mod_version = 1.3.2+v191230 + mod_version = 1.3.3+v200103 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 697631e0..3e241a51 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -31,7 +31,7 @@ import static carpet.settings.RuleCategory.DISPENSER; public class CarpetSettings { - public static final String carpetVersion = "1.3.2+v191230"; + public static final String carpetVersion = "1.3.3+v200103"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 8cf8982d..79d05576 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 addTickrateListener(String modId, BiConsumer tickrateListener) + { + synchronized (tickrateListeners) + { + tickrateListeners.put(modId, tickrateListener); + } + return TickSpeed::tickrateChanged; } } diff --git a/src/main/java/carpet/mixins/ClientPlayNetworkHandler_smoothClientAnimationsMixin.java b/src/main/java/carpet/mixins/ClientPlayNetworkHandler_smoothClientAnimationsMixin.java new file mode 100644 index 00000000..43b44256 --- /dev/null +++ b/src/main/java/carpet/mixins/ClientPlayNetworkHandler_smoothClientAnimationsMixin.java @@ -0,0 +1,51 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.PistonBlockEntity; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.packet.ChunkDataS2CPacket; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.Iterator; + +@Mixin(ClientPlayNetworkHandler.class) +public class ClientPlayNetworkHandler_smoothClientAnimationsMixin +{ + @Shadow private ClientWorld world; + // fix as suggested by G4me4u + @Inject( method = "onChunkData", locals = LocalCapture.CAPTURE_FAILHARD, require = 0, at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/world/ClientWorld;getBlockEntity(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/entity/BlockEntity;", + shift = At.Shift.AFTER + )) + private void recreateMovingPistons(ChunkDataS2CPacket packet, CallbackInfo ci, + Iterator var5, CompoundTag tag, BlockPos blockPos) + { + if (CarpetSettings.smoothClientAnimations) + { + BlockEntity blockEntity = world.getBlockEntity(blockPos); + if (blockEntity == null && "minecraft:piston".equals(tag.getString("id"))) + { + BlockState blockState = world.getBlockState(blockPos); + if (blockState.getBlock() == Blocks.MOVING_PISTON) { + tag.putFloat("progress", Math.min(tag.getFloat("progress") + 0.5F, 1.0F)); + blockEntity = new PistonBlockEntity(); + blockEntity.fromTag(tag); + world.setBlockEntity(blockPos, blockEntity); + blockEntity.resetBlock(); + } + } + } + } +} diff --git a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java index 50e24ba2..d6629d10 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java @@ -45,6 +45,12 @@ public abstract class MinecraftServer_tickspeedMixin 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")) private boolean cancelRunLoop(MinecraftServer server) @@ -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 = Util.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 = Util.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(Util.getMeasuringTimeMs() + /*50L*/ mspt, this.timeReference); + this.field_19248 = Math.max(Util.getMeasuringTimeMs() + /*50L*/ msThisTick, this.timeReference); this.method_16208(); this.profiler.pop(); this.profiler.endTick(); diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index e7ecf2a7..ed086c4d 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -154,7 +154,8 @@ "IntegratedServerMixin", "InGameHudMixin", "PlayerListHudMixin", - "PistonBlockEntityRenderer_movableTEMixin" + "PistonBlockEntityRenderer_movableTEMixin", + "ClientPlayNetworkHandler_smoothClientAnimationsMixin" ], "server": [ "MinecraftDedicatedServerMixin" diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2ba6dd24..a5a1b410 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.2", + "version": "1.3.3", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric",