Skip to content

Commit ce7b7cb

Browse files
committed
Merge 1.19.4 into 1.20
2 parents f7097ec + fa5b947 commit ce7b7cb

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.embeddedt.modernfix.forge.mixin.bugfix.chunk_deadlock;
2+
3+
import net.minecraft.server.level.ChunkHolder;
4+
import net.minecraft.server.level.ServerChunkCache;
5+
import net.minecraft.world.level.ChunkPos;
6+
import net.minecraft.world.level.chunk.ChunkAccess;
7+
import net.minecraft.world.level.chunk.ChunkStatus;
8+
import net.minecraft.world.level.chunk.LevelChunk;
9+
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
10+
import org.jetbrains.annotations.Nullable;
11+
import org.spongepowered.asm.mixin.Mixin;
12+
import org.spongepowered.asm.mixin.Shadow;
13+
import org.spongepowered.asm.mixin.injection.At;
14+
import org.spongepowered.asm.mixin.injection.Inject;
15+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
16+
17+
import java.lang.invoke.MethodHandle;
18+
import java.lang.invoke.MethodHandles;
19+
import java.lang.reflect.Field;
20+
21+
@Mixin(ServerChunkCache.class)
22+
public abstract class ServerChunkCache_CurrentLoadingMixin {
23+
@Shadow @Nullable protected abstract ChunkHolder getVisibleChunkIfPresent(long l);
24+
25+
private static final MethodHandle CURRENTLY_LOADING;
26+
27+
static {
28+
try {
29+
Field currentlyLoadingField = ObfuscationReflectionHelper.findField(ChunkHolder.class, "currentlyLoading");
30+
currentlyLoadingField.setAccessible(true);
31+
CURRENTLY_LOADING = MethodHandles.lookup().unreflectGetter(currentlyLoadingField);
32+
} catch(Exception e) {
33+
throw new RuntimeException("Failed to get currentlyLoading field", e);
34+
}
35+
}
36+
37+
/**
38+
* Check the currentlyLoading field before going to the future chain, as was done in 1.16. In 1.18 upstream seems
39+
* to have only applied this to getChunkNow().
40+
*/
41+
@Inject(method = "getChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;getChunkFutureMainThread(IILnet/minecraft/world/level/chunk/ChunkStatus;Z)Ljava/util/concurrent/CompletableFuture;"), cancellable = true)
42+
private void checkCurrentlyLoading(int chunkX, int chunkZ, ChunkStatus requiredStatus, boolean load, CallbackInfoReturnable<ChunkAccess> cir) {
43+
long i = ChunkPos.asLong(chunkX, chunkZ);
44+
ChunkHolder holder = this.getVisibleChunkIfPresent(i);
45+
if(holder != null) {
46+
LevelChunk c;
47+
try {
48+
c = (LevelChunk)CURRENTLY_LOADING.invokeExact(holder);
49+
} catch(Throwable e) {
50+
e.printStackTrace();
51+
c = null;
52+
}
53+
if(c != null)
54+
cir.setReturnValue(c);
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)