diff --git a/src/main/java/com/simibubi/create/foundation/mixin/fabric/BlockableEventLoopAccessor.java b/src/main/java/com/simibubi/create/foundation/mixin/fabric/BlockableEventLoopAccessor.java new file mode 100644 index 0000000000..e4634d4e56 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/fabric/BlockableEventLoopAccessor.java @@ -0,0 +1,14 @@ +package com.simibubi.create.foundation.mixin.fabric; + +import java.util.concurrent.CompletableFuture; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.util.thread.BlockableEventLoop; + +@Mixin(BlockableEventLoop.class) +public interface BlockableEventLoopAccessor { + @Invoker + CompletableFuture callSubmitAsync(Runnable task); +} diff --git a/src/main/java/com/simibubi/create/foundation/networking/SimplePacketBase.java b/src/main/java/com/simibubi/create/foundation/networking/SimplePacketBase.java index ad51d3a03f..5f413d5104 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/SimplePacketBase.java +++ b/src/main/java/com/simibubi/create/foundation/networking/SimplePacketBase.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.networking; -import java.util.concurrent.Executor; +import com.simibubi.create.foundation.mixin.fabric.BlockableEventLoopAccessor; import org.jetbrains.annotations.Nullable; @@ -15,6 +15,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.util.thread.BlockableEventLoop; public abstract class SimplePacketBase implements C2SPacket, S2CPacket { @@ -42,9 +43,16 @@ public enum NetworkDirection { PLAY_TO_SERVER } - public record Context(Executor exec, PacketListener listener, @Nullable ServerPlayer sender) { + public record Context(BlockableEventLoop executor, PacketListener listener, @Nullable ServerPlayer sender) { public void enqueueWork(Runnable runnable) { - exec().execute(runnable); + // Matches Forge's enqueueWork behavior. + // MC will sometimes defer tasks even if already on the right thread. + if (executor.isSameThread()) { + runnable.run(); + } else { + // skip extra checks + ((BlockableEventLoopAccessor) executor).callSubmitAsync(runnable); + } } @Nullable diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 9691a4ef56..908cc69b68 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -23,6 +23,7 @@ "accessor.ServerLevelAccessor", "accessor.SystemReportAccessor", "fabric.AbstractMinecartMixin", + "fabric.BlockableEventLoopAccessor", "fabric.EntityMixin", "fabric.RegistryMixin", "fabric.ServerGamePacketListenerImplAccessor",