diff --git a/src/main/java/org/embeddedt/modernfix/duck/IChunkGenerator.java b/src/main/java/org/embeddedt/modernfix/duck/IChunkGenerator.java new file mode 100644 index 00000000..5f48ba9e --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/duck/IChunkGenerator.java @@ -0,0 +1,7 @@ +package org.embeddedt.modernfix.duck; + +import net.minecraft.server.level.ServerLevel; + +public interface IChunkGenerator { + void mfix$setAssociatedServerLevel(ServerLevel level); +} diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/cache_strongholds/ChunkGeneratorMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/cache_strongholds/ChunkGeneratorMixin.java index a72df465..887dc952 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/cache_strongholds/ChunkGeneratorMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/cache_strongholds/ChunkGeneratorMixin.java @@ -1,67 +1,67 @@ package org.embeddedt.modernfix.mixin.perf.cache_strongholds; +import net.minecraft.Util; +import net.minecraft.core.Holder; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraftforge.fml.server.ServerLifecycleHooks; +import net.minecraft.world.level.levelgen.structure.StructureSet; +import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; +import net.minecraftforge.server.ServerLifecycleHooks; import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.duck.IChunkGenerator; import org.embeddedt.modernfix.duck.IServerLevel; import org.embeddedt.modernfix.world.StrongholdLocationCache; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.lang.ref.WeakReference; import java.util.List; -import java.util.concurrent.ExecutionException; +import java.util.concurrent.CompletableFuture; @Mixin(ChunkGenerator.class) -public class ChunkGeneratorMixin { - @Shadow @Final private List strongholdPositions; +public class ChunkGeneratorMixin implements IChunkGenerator { + private WeakReference mfix$serverLevel; - @Inject(method = "generateStrongholds", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Lists;newArrayList()Ljava/util/ArrayList;", ordinal = 0), cancellable = true) - private void useCachedDataIfAvailable(CallbackInfo ci) { - ServerLevel level = searchLevel(); - if(level == null) { - ModernFix.LOGGER.error("Can't find server level for " + this); + @Override + public void mfix$setAssociatedServerLevel(ServerLevel level) { + mfix$serverLevel = new WeakReference<>(level); + } + + @Inject(method = "generateRingPositions", at = @At("HEAD"), cancellable = true) + private void useCachedDataIfAvailable(Holder setHolder, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable>> cir) { + if(placement.count() == 0) + return; + ServerLevel level = searchLevel(); + if(level == null) return; - } StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache(); List positions = cache.getChunkPosList(); if(positions.isEmpty()) return; ModernFix.LOGGER.debug("Loaded stronghold cache for dimension {} with {} positions", level.dimension().location(), positions.size()); - this.strongholdPositions.addAll(positions); - ci.cancel(); + cir.setReturnValue(CompletableFuture.completedFuture(positions)); } private ServerLevel searchLevel() { - MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - if(server != null) { - ServerLevel ourLevel = null; - for (ServerLevel level : server.getAllLevels()) { - if (level.getChunkSource().getGenerator() == ((ChunkGenerator) (Object) this)) { - ourLevel = level; - break; - } - } - return ourLevel; - } else - return null; + return mfix$serverLevel.get(); } - @Inject(method = "generateStrongholds", at = @At("TAIL")) - private void saveCachedData(CallbackInfo ci) { - if(this.strongholdPositions.size() > 0) { + @Inject(method = "generateRingPositions", at = @At("RETURN"), cancellable = true) + private void saveCachedData(Holder setHolder, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable>> cir) { + cir.setReturnValue(cir.getReturnValue().thenApplyAsync(list -> { + if(list.size() == 0) + return list; ServerLevel level = searchLevel(); if(level != null) { StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache(); - cache.setChunkPosList(this.strongholdPositions); + cache.setChunkPosList(list); ModernFix.LOGGER.debug("Saved stronghold cache for dimension {}", level.dimension().location()); } - } + return list; + }, Util.backgroundExecutor())); } } diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/cache_strongholds/ServerLevelMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/cache_strongholds/ServerLevelMixin.java index 57332c5e..4144c333 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/cache_strongholds/ServerLevelMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/cache_strongholds/ServerLevelMixin.java @@ -1,5 +1,6 @@ package org.embeddedt.modernfix.mixin.perf.cache_strongholds; +import net.minecraft.core.Holder; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -13,12 +14,14 @@ import net.minecraft.world.level.storage.DimensionDataStorage; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.WritableLevelData; +import org.embeddedt.modernfix.duck.IChunkGenerator; import org.embeddedt.modernfix.duck.IServerLevel; import org.embeddedt.modernfix.world.StrongholdLocationCache; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.List; @@ -27,7 +30,7 @@ import java.util.function.Supplier; @Mixin(ServerLevel.class) public abstract class ServerLevelMixin extends Level implements IServerLevel { - protected ServerLevelMixin(WritableLevelData arg, ResourceKey arg2, DimensionType arg3, Supplier supplier, boolean bl, boolean bl2, long l) { + protected ServerLevelMixin(WritableLevelData arg, ResourceKey arg2, Holder arg3, Supplier supplier, boolean bl, boolean bl2, long l) { super(arg, arg2, arg3, supplier, bl, bl2, l); } @@ -35,11 +38,23 @@ public abstract class ServerLevelMixin extends Level implements IServerLevel { private StrongholdLocationCache mfix$strongholdCache; - @Inject(method = "", at = @At("RETURN")) - private void addStrongholdCache(MinecraftServer minecraftServer, Executor executor, LevelStorageSource.LevelStorageAccess arg, - ServerLevelData arg2, ResourceKey arg3, DimensionType arg4, ChunkProgressListener arg5, - ChunkGenerator arg6, boolean bl, long l, List list, boolean bl2, CallbackInfo ci) { - mfix$strongholdCache = this.getDataStorage().computeIfAbsent(() -> new StrongholdLocationCache((ServerLevel)(Object)this), StrongholdLocationCache.getFileId(this.dimensionType())); + /** + * Initialize the stronghold cache but don't force any structure generation yet. + */ + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkGenerator;ensureStructuresGenerated()V")) + private void hookStrongholdCache(ChunkGenerator generator) { + ((IChunkGenerator)generator).mfix$setAssociatedServerLevel((ServerLevel)(Object)this); + } + + /** + * Now start the stronghold generation process. + */ + @Inject(method = "", at = @At("TAIL")) + private void ensureGeneration(MinecraftServer minecraftServer, Executor executor, LevelStorageSource.LevelStorageAccess arg, ServerLevelData arg2, ResourceKey arg3, Holder arg4, ChunkProgressListener arg5, ChunkGenerator arg6, boolean bl, long l, List list, boolean bl2, CallbackInfo ci) { + mfix$strongholdCache = this.getDataStorage().computeIfAbsent(StrongholdLocationCache::load, + StrongholdLocationCache::new, + StrongholdLocationCache.getFileId(this.dimensionTypeRegistration())); + arg6.ensureStructuresGenerated(); } @Override diff --git a/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java b/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java index cb408664..4ffafada 100644 --- a/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java +++ b/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java @@ -1,19 +1,19 @@ package org.embeddedt.modernfix.world; +import net.minecraft.core.Holder; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerLevel; +import net.minecraft.nbt.Tag; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.saveddata.SavedData; -import net.minecraftforge.common.util.Constants; import java.util.ArrayList; import java.util.List; public class StrongholdLocationCache extends SavedData { private List chunkPosList; - public StrongholdLocationCache(ServerLevel level) { - super(getFileId(level.dimensionType())); + public StrongholdLocationCache() { + super(); chunkPosList = new ArrayList<>(); } @@ -26,14 +26,15 @@ public class StrongholdLocationCache extends SavedData { this.setDirty(); } - @Override - public void load(CompoundTag arg) { - if(arg.contains("Positions", Constants.NBT.TAG_LONG_ARRAY)) { + public static StrongholdLocationCache load(CompoundTag arg) { + StrongholdLocationCache cache = new StrongholdLocationCache(); + if(arg.contains("Positions", Tag.TAG_LONG_ARRAY)) { long[] positions = arg.getLongArray("Positions"); for(long position : positions) { - chunkPosList.add(new ChunkPos(position)); + cache.chunkPosList.add(new ChunkPos(position)); } } + return cache; } @Override @@ -47,7 +48,7 @@ public class StrongholdLocationCache extends SavedData { return compoundTag; } - public static String getFileId(DimensionType dimensionType) { - return "mfix_strongholds" + dimensionType.getFileSuffix(); + public static String getFileId(Holder dimensionType) { + return "mfix_strongholds"; } }