From a643170426cfe57cdfffddde87229b5506c49de5 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 18 May 2025 19:10:11 -0400 Subject: [PATCH] Implement more accurate fix for MC-183518 The game now sleeps precisely till the next tick, rather than still waking up periodically Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> --- .../BlockableEventLoopMixin.java | 23 --------- .../MinecraftServerMixin.java | 48 +++++++++++++++++++ 2 files changed, 48 insertions(+), 23 deletions(-) delete mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/BlockableEventLoopMixin.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/MinecraftServerMixin.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/BlockableEventLoopMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/BlockableEventLoopMixin.java deleted file mode 100644 index fba53257..00000000 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/BlockableEventLoopMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.fix_loop_spin_waiting; - -import net.minecraft.util.thread.BlockableEventLoop; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.LockSupport; - -// This should fix https://bugs.mojang.com/browse/MC-183518 -@Mixin(value = BlockableEventLoop.class, priority = 500) -public class BlockableEventLoopMixin { - private static final long MFIX$TICK_WAIT_TIME = TimeUnit.MILLISECONDS.toNanos(2); - - /** - * @author embeddedt - * @reason yielding the thread is pretty pointless if we're about to park anyway - */ - @Overwrite - protected void waitForTasks() { - LockSupport.parkNanos("waiting for tasks", MFIX$TICK_WAIT_TIME); - } -} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/MinecraftServerMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/MinecraftServerMixin.java new file mode 100644 index 00000000..e7ae6924 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/MinecraftServerMixin.java @@ -0,0 +1,48 @@ +package org.embeddedt.modernfix.common.mixin.perf.fix_loop_spin_waiting; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.Util; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.thread.BlockableEventLoop; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.concurrent.locks.LockSupport; +import java.util.function.BooleanSupplier; + +@Mixin(value = MinecraftServer.class, priority = 500) +public abstract class MinecraftServerMixin extends BlockableEventLoop { + @Shadow private long nextTickTime; + + protected MinecraftServerMixin(String name) { + super(name); + } + + @Unique + private boolean mfix$isWaitingForNextTick = false; + + @WrapOperation( + method = "waitUntilNextTick", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;managedBlock(Ljava/util/function/BooleanSupplier;)V") + ) + private void managedBlock(MinecraftServer instance, BooleanSupplier isDone, Operation original) { + try { + this.mfix$isWaitingForNextTick = true; + original.call(instance, isDone); + } finally { + this.mfix$isWaitingForNextTick = false; + } + } + + @Override + protected void waitForTasks() { + if (this.mfix$isWaitingForNextTick) { + LockSupport.parkNanos("waiting for tasks", (this.nextTickTime * 1000000L) - Util.getNanos()); + } else { + super.waitForTasks(); + } + } +}