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;
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<ChunkPos> strongholdPositions;
public class ChunkGeneratorMixin implements IChunkGenerator {
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)
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<StructureSet> setHolder, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable<CompletableFuture<List<ChunkPos>>> cir) {
if(placement.count() == 0)
return;
ServerLevel level = searchLevel();
if(level == null)
return;
}
StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache();
List<ChunkPos> 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<StructureSet> setHolder, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable<CompletableFuture<List<ChunkPos>>> 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()));
}
}

View File

@ -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<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);
}
@ -35,11 +38,23 @@ public abstract class ServerLevelMixin extends Level implements IServerLevel {
private StrongholdLocationCache mfix$strongholdCache;
@Inject(method = "<init>", at = @At("RETURN"))
private void addStrongholdCache(MinecraftServer minecraftServer, Executor executor, LevelStorageSource.LevelStorageAccess arg,
ServerLevelData arg2, ResourceKey<Level> arg3, DimensionType arg4, ChunkProgressListener arg5,
ChunkGenerator arg6, boolean bl, long l, List<CustomSpawner> 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 = "<init>", 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 = "<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

View File

@ -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<ChunkPos> 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> dimensionType) {
return "mfix_strongholds";
}
}