Port stronghold caching to 1.18

This commit is contained in:
embeddedt 2023-02-25 19:27:57 -05:00
parent 963394c558
commit 6aed33a5d7
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
4 changed files with 71 additions and 48 deletions

View File

@ -0,0 +1,7 @@
package org.embeddedt.modernfix.duck;
import net.minecraft.server.level.ServerLevel;
public interface IChunkGenerator {
void mfix$setAssociatedServerLevel(ServerLevel level);
}

View File

@ -1,67 +1,67 @@
package org.embeddedt.modernfix.mixin.perf.cache_strongholds; 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.MinecraftServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGenerator; 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.ModernFix;
import org.embeddedt.modernfix.duck.IChunkGenerator;
import org.embeddedt.modernfix.duck.IServerLevel; import org.embeddedt.modernfix.duck.IServerLevel;
import org.embeddedt.modernfix.world.StrongholdLocationCache; import org.embeddedt.modernfix.world.StrongholdLocationCache;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; 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.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.CompletableFuture;
@Mixin(ChunkGenerator.class) @Mixin(ChunkGenerator.class)
public class ChunkGeneratorMixin { public class ChunkGeneratorMixin implements IChunkGenerator {
@Shadow @Final private List<ChunkPos> strongholdPositions; private WeakReference<ServerLevel> mfix$serverLevel;
@Inject(method = "generateStrongholds", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Lists;newArrayList()Ljava/util/ArrayList;", ordinal = 0), cancellable = true) @Override
private void useCachedDataIfAvailable(CallbackInfo ci) { public void mfix$setAssociatedServerLevel(ServerLevel level) {
ServerLevel level = searchLevel(); mfix$serverLevel = new WeakReference<>(level);
if(level == null) { }
ModernFix.LOGGER.error("Can't find server level for " + this);
@Inject(method = "generateRingPositions", at = @At("HEAD"), cancellable = true)
private void useCachedDataIfAvailable(Holder<StructureSet> setHolder, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable<CompletableFuture<List<ChunkPos>>> cir) {
if(placement.count() == 0)
return;
ServerLevel level = searchLevel();
if(level == null)
return; return;
}
StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache(); StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache();
List<ChunkPos> positions = cache.getChunkPosList(); List<ChunkPos> positions = cache.getChunkPosList();
if(positions.isEmpty()) if(positions.isEmpty())
return; return;
ModernFix.LOGGER.debug("Loaded stronghold cache for dimension {} with {} positions", level.dimension().location(), positions.size()); ModernFix.LOGGER.debug("Loaded stronghold cache for dimension {} with {} positions", level.dimension().location(), positions.size());
this.strongholdPositions.addAll(positions); cir.setReturnValue(CompletableFuture.completedFuture(positions));
ci.cancel();
} }
private ServerLevel searchLevel() { private ServerLevel searchLevel() {
MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); return mfix$serverLevel.get();
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;
} }
@Inject(method = "generateStrongholds", at = @At("TAIL")) @Inject(method = "generateRingPositions", at = @At("RETURN"), cancellable = true)
private void saveCachedData(CallbackInfo ci) { private void saveCachedData(Holder<StructureSet> setHolder, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable<CompletableFuture<List<ChunkPos>>> cir) {
if(this.strongholdPositions.size() > 0) { cir.setReturnValue(cir.getReturnValue().thenApplyAsync(list -> {
if(list.size() == 0)
return list;
ServerLevel level = searchLevel(); ServerLevel level = searchLevel();
if(level != null) { if(level != null) {
StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache(); StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache();
cache.setChunkPosList(this.strongholdPositions); cache.setChunkPosList(list);
ModernFix.LOGGER.debug("Saved stronghold cache for dimension {}", level.dimension().location()); ModernFix.LOGGER.debug("Saved stronghold cache for dimension {}", level.dimension().location());
} }
} return list;
}, Util.backgroundExecutor()));
} }
} }

View File

@ -1,5 +1,6 @@
package org.embeddedt.modernfix.mixin.perf.cache_strongholds; package org.embeddedt.modernfix.mixin.perf.cache_strongholds;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; 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.LevelStorageSource;
import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData; import net.minecraft.world.level.storage.WritableLevelData;
import org.embeddedt.modernfix.duck.IChunkGenerator;
import org.embeddedt.modernfix.duck.IServerLevel; import org.embeddedt.modernfix.duck.IServerLevel;
import org.embeddedt.modernfix.world.StrongholdLocationCache; import org.embeddedt.modernfix.world.StrongholdLocationCache;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List; import java.util.List;
@ -27,7 +30,7 @@ import java.util.function.Supplier;
@Mixin(ServerLevel.class) @Mixin(ServerLevel.class)
public abstract class ServerLevelMixin extends Level implements IServerLevel { public abstract class ServerLevelMixin extends Level implements IServerLevel {
protected ServerLevelMixin(WritableLevelData arg, ResourceKey<Level> arg2, DimensionType arg3, Supplier<ProfilerFiller> supplier, boolean bl, boolean bl2, long l) { protected ServerLevelMixin(WritableLevelData arg, ResourceKey<Level> arg2, Holder<DimensionType> arg3, Supplier<ProfilerFiller> supplier, boolean bl, boolean bl2, long l) {
super(arg, arg2, arg3, supplier, bl, bl2, 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; private StrongholdLocationCache mfix$strongholdCache;
@Inject(method = "<init>", at = @At("RETURN")) /**
private void addStrongholdCache(MinecraftServer minecraftServer, Executor executor, LevelStorageSource.LevelStorageAccess arg, * Initialize the stronghold cache but don't force any structure generation yet.
ServerLevelData arg2, ResourceKey<Level> arg3, DimensionType arg4, ChunkProgressListener arg5, */
ChunkGenerator arg6, boolean bl, long l, List<CustomSpawner> list, boolean bl2, CallbackInfo ci) { @Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkGenerator;ensureStructuresGenerated()V"))
mfix$strongholdCache = this.getDataStorage().computeIfAbsent(() -> new StrongholdLocationCache((ServerLevel)(Object)this), StrongholdLocationCache.getFileId(this.dimensionType())); private void hookStrongholdCache(ChunkGenerator generator) {
((IChunkGenerator)generator).mfix$setAssociatedServerLevel((ServerLevel)(Object)this);
}
/**
* Now start the stronghold generation process.
*/
@Inject(method = "<init>", at = @At("TAIL"))
private void ensureGeneration(MinecraftServer minecraftServer, Executor executor, LevelStorageSource.LevelStorageAccess arg, ServerLevelData arg2, ResourceKey<Level> arg3, Holder<DimensionType> arg4, ChunkProgressListener arg5, ChunkGenerator arg6, boolean bl, long l, List<CustomSpawner> list, boolean bl2, CallbackInfo ci) {
mfix$strongholdCache = this.getDataStorage().computeIfAbsent(StrongholdLocationCache::load,
StrongholdLocationCache::new,
StrongholdLocationCache.getFileId(this.dimensionTypeRegistration()));
arg6.ensureStructuresGenerated();
} }
@Override @Override

View File

@ -1,19 +1,19 @@
package org.embeddedt.modernfix.world; package org.embeddedt.modernfix.world;
import net.minecraft.core.Holder;
import net.minecraft.nbt.CompoundTag; 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.ChunkPos;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.saveddata.SavedData; import net.minecraft.world.level.saveddata.SavedData;
import net.minecraftforge.common.util.Constants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class StrongholdLocationCache extends SavedData { public class StrongholdLocationCache extends SavedData {
private List<ChunkPos> chunkPosList; private List<ChunkPos> chunkPosList;
public StrongholdLocationCache(ServerLevel level) { public StrongholdLocationCache() {
super(getFileId(level.dimensionType())); super();
chunkPosList = new ArrayList<>(); chunkPosList = new ArrayList<>();
} }
@ -26,14 +26,15 @@ public class StrongholdLocationCache extends SavedData {
this.setDirty(); this.setDirty();
} }
@Override public static StrongholdLocationCache load(CompoundTag arg) {
public void load(CompoundTag arg) { StrongholdLocationCache cache = new StrongholdLocationCache();
if(arg.contains("Positions", Constants.NBT.TAG_LONG_ARRAY)) { if(arg.contains("Positions", Tag.TAG_LONG_ARRAY)) {
long[] positions = arg.getLongArray("Positions"); long[] positions = arg.getLongArray("Positions");
for(long position : positions) { for(long position : positions) {
chunkPosList.add(new ChunkPos(position)); cache.chunkPosList.add(new ChunkPos(position));
} }
} }
return cache;
} }
@Override @Override
@ -47,7 +48,7 @@ public class StrongholdLocationCache extends SavedData {
return compoundTag; return compoundTag;
} }
public static String getFileId(DimensionType dimensionType) { public static String getFileId(Holder<DimensionType> dimensionType) {
return "mfix_strongholds" + dimensionType.getFileSuffix(); return "mfix_strongholds";
} }
} }