From 44f4657f31e8390561825d370de38f49209cd40f Mon Sep 17 00:00:00 2001 From: Goldenfield192 <1437356849@qq.com> Date: Wed, 9 Sep 2026 12:53:32 +0800 Subject: [PATCH] fix: race condition on player loading --- .../java/cam72cam/mod/MinecraftClient.java | 10 +++++- .../MixinMinecraft.java | 35 +++++++++++++++++++ .../mixins.fix.universalmodcore.json | 1 + 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/main/java/cam72cam/mod/mixin/fix/client_player_handling/MixinMinecraft.java diff --git a/src/main/java/cam72cam/mod/MinecraftClient.java b/src/main/java/cam72cam/mod/MinecraftClient.java index 4d7405a6e..d5a5f6499 100644 --- a/src/main/java/cam72cam/mod/MinecraftClient.java +++ b/src/main/java/cam72cam/mod/MinecraftClient.java @@ -8,12 +8,20 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.util.math.RayTraceResult; +import org.jetbrains.annotations.ApiStatus; /** Static Minecraft Client props, don't touch server side */ public class MinecraftClient { /** Minecraft is loaded and has a loaded world */ + private static boolean clientReady; + public static boolean isReady() { - return Minecraft.getMinecraft().player != null; + return clientReady; + } + + @ApiStatus.Internal + public static void setReady(boolean newState) { + clientReady = newState; } private static Player playerCache; diff --git a/src/main/java/cam72cam/mod/mixin/fix/client_player_handling/MixinMinecraft.java b/src/main/java/cam72cam/mod/mixin/fix/client_player_handling/MixinMinecraft.java new file mode 100644 index 000000000..7da85b36f --- /dev/null +++ b/src/main/java/cam72cam/mod/mixin/fix/client_player_handling/MixinMinecraft.java @@ -0,0 +1,35 @@ +package cam72cam.mod.mixin.fix.client_player_handling; + +import cam72cam.mod.MinecraftClient; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.WorldClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * Manually track loading state to avoid race condition on {@link MinecraftClient#isReady()} and actual player spawn + */ +@Mixin(Minecraft.class) +public class MixinMinecraft { + @Inject(method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/multiplayer/WorldClient;spawnEntity(Lnet/minecraft/entity/Entity;)Z")) + public void markReadyWhenLoaded(WorldClient worldClientIn, String loadingMessage, CallbackInfo ci) { + MinecraftClient.setReady(true); + } + + @Inject(method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/storage/ISaveFormat;flushCache()V")) + public void markNotReadyWhenUnloaded(WorldClient worldClientIn, String loadingMessage, CallbackInfo ci) { + MinecraftClient.setReady(false); + } + + @Inject(method = "setDimensionAndSpawnPlayer", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/multiplayer/WorldClient;spawnEntity(Lnet/minecraft/entity/Entity;)Z")) + public void markReadyWhenLoaded(int dimension, CallbackInfo ci) { + MinecraftClient.setReady(true); + } + + @Inject(method = "setDimensionAndSpawnPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/entity/EntityPlayerSP;getEntityId()I")) + public void markNotReadyWhenTransfer(int dimension, CallbackInfo ci) { + MinecraftClient.setReady(false); + } +} diff --git a/src/main/resources/mixins.fix.universalmodcore.json b/src/main/resources/mixins.fix.universalmodcore.json index aca368e9e..ce439cfb4 100644 --- a/src/main/resources/mixins.fix.universalmodcore.json +++ b/src/main/resources/mixins.fix.universalmodcore.json @@ -13,5 +13,6 @@ "multi_release.MixinJarDiscoverer" ], "client": [ + "client_player_handling.MixinMinecraft" ] }