Fix potential stronghold cache corruption if player exits world too quickly

This commit is contained in:
embeddedt 2026-05-23 16:32:56 -04:00
parent f8d2425242
commit 7c45564979
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
3 changed files with 15 additions and 10 deletions

View File

@ -4,9 +4,9 @@ import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import net.minecraft.Util;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.*;
import net.minecraft.resources.RegistryOps;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
@ -41,22 +41,23 @@ public class ChunkGeneratorMixin implements IChunkGenerator {
private BiomeSource biomeSource;
private Path mfix$dimensionPath;
private RegistryAccess.Frozen mfix$registryAccess;
private MinecraftServer mfix$server;
private SoftReference<Map<String, List<ChunkPos>>> mfix$cachedPositions = new SoftReference<>(null);
private static final String CACHE_FILENAME = "mfix_stronghold_cache_v2.nbt";
@Override
public void mfix$setStrongholdCachePath(Path cachePath, RegistryAccess.Frozen registryAccess) {
public void mfix$setStrongholdCachePath(Path cachePath, MinecraftServer server) {
this.mfix$dimensionPath = cachePath;
this.mfix$registryAccess = registryAccess;
this.mfix$server = server;
}
@WrapMethod(method = "generateRingPositions")
private CompletableFuture<List<ChunkPos>> modernfix$cacheRingPositions(Holder<StructureSet> structureSet,
ConcentricRingsStructurePlacement placement,
Operation<CompletableFuture<List<ChunkPos>>> original) {
if (this.mfix$registryAccess == null || this.mfix$dimensionPath == null) {
if (this.mfix$server == null || this.mfix$dimensionPath == null) {
return original.call(structureSet, placement);
}
@ -69,14 +70,18 @@ public class ChunkGeneratorMixin implements IChunkGenerator {
return CompletableFuture.completedFuture(List.copyOf(cached));
}
var server = this.mfix$server;
return original.call(structureSet, placement).thenApplyAsync(positions -> {
// Skip write if server exited before we finished
if (server.isRunning()) {
mfix$writeToCache(cacheKey, positions);
}
return positions;
}, Util.ioPool());
}
private String mfix$makeCacheKey(ConcentricRingsStructurePlacement placement) {
RegistryOps<Tag> ops = RegistryOps.create(NbtOps.INSTANCE, this.mfix$registryAccess);
RegistryOps<Tag> ops = RegistryOps.create(NbtOps.INSTANCE, this.mfix$server.registryAccess());
String placementKey = ConcentricRingsStructurePlacement.CODEC.encodeStart(ops, placement)
.result().map(Tag::toString).orElse(null);
String biomeSourceKey = BiomeSource.CODEC.encodeStart(ops, this.biomeSource)

View File

@ -24,7 +24,7 @@ public class ServerLevelMixin {
@Local(ordinal = 0, argsOnly = true) LevelStorageSource.LevelStorageAccess levelStorageAccess,
@Local(ordinal = 0, argsOnly = true) ResourceKey<Level> dimension,
@Local(ordinal = 0, argsOnly = true) MinecraftServer server) {
((IChunkGenerator)instance).mfix$setStrongholdCachePath(levelStorageAccess.getDimensionPath(dimension), server.registryAccess());
((IChunkGenerator)instance).mfix$setStrongholdCachePath(levelStorageAccess.getDimensionPath(dimension), server);
original.call(instance);
}
}

View File

@ -1,9 +1,9 @@
package org.embeddedt.modernfix.duck;
import net.minecraft.core.RegistryAccess;
import net.minecraft.server.MinecraftServer;
import java.nio.file.Path;
public interface IChunkGenerator {
void mfix$setStrongholdCachePath(Path cachePath, RegistryAccess.Frozen registryAccess);
void mfix$setStrongholdCachePath(Path cachePath, MinecraftServer server);
}