Cache upgraded structures instead of running them through DFU every time
Fixes https://github.com/TelepathicGrunt/RepurposedStructures/issues/264 and similar issues
This commit is contained in:
parent
314a1e27cc
commit
5c853a7259
|
|
@ -29,6 +29,7 @@ public class ModernFixEarlyConfig {
|
||||||
this.addMixinRule("perf.parallelize_model_loading", true);
|
this.addMixinRule("perf.parallelize_model_loading", true);
|
||||||
this.addMixinRule("perf.parallelize_model_loading.multipart", false);
|
this.addMixinRule("perf.parallelize_model_loading.multipart", false);
|
||||||
this.addMixinRule("perf.cache_strongholds", true);
|
this.addMixinRule("perf.cache_strongholds", true);
|
||||||
|
this.addMixinRule("perf.cache_upgraded_structures", true);
|
||||||
this.addMixinRule("bugfix.concurrency", true);
|
this.addMixinRule("bugfix.concurrency", true);
|
||||||
this.addMixinRule("bugfix.edge_chunk_not_saved", true);
|
this.addMixinRule("bugfix.edge_chunk_not_saved", true);
|
||||||
this.addMixinRule("bugfix.packet_leak", false);
|
this.addMixinRule("bugfix.packet_leak", false);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.embeddedt.modernfix.mixin.perf.cache_upgraded_structures;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.DataFixer;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||||
|
import org.embeddedt.modernfix.structure.CachingStructureManager;
|
||||||
|
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.Redirect;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@Mixin(StructureManager.class)
|
||||||
|
public class StructureManagerMixin {
|
||||||
|
@Shadow @Final private DataFixer fixerUpper;
|
||||||
|
|
||||||
|
@Redirect(method = "loadFromResource", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructureManager;readStructure(Ljava/io/InputStream;)Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate;"))
|
||||||
|
private StructureTemplate readViaCache(StructureManager manager, InputStream stream, ResourceLocation arg) throws IOException {
|
||||||
|
return CachingStructureManager.readStructure(arg, this.fixerUpper, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package org.embeddedt.modernfix.structure;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.DataFixer;
|
||||||
|
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||||
|
import net.minecraft.SharedConstants;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.NbtIo;
|
||||||
|
import net.minecraft.nbt.NbtUtils;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.util.datafix.DataFixTypes;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||||
|
import net.minecraftforge.fml.loading.FMLPaths;
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
|
import org.embeddedt.modernfix.util.FileUtil;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
|
public class CachingStructureManager {
|
||||||
|
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> LamdbaExceptionUtils.uncheck(() -> MessageDigest.getInstance("SHA-256")));
|
||||||
|
private static final File STRUCTURE_CACHE_FOLDER = FileUtil.childFile(FMLPaths.GAMEDIR.get().resolve("modernfix").resolve("structureCacheV1").toFile());
|
||||||
|
|
||||||
|
static {
|
||||||
|
STRUCTURE_CACHE_FOLDER.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StructureTemplate readStructure(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException {
|
||||||
|
CompoundTag tag = readStructureTag(location, datafixer, stream);
|
||||||
|
StructureTemplate template = new StructureTemplate();
|
||||||
|
template.load(tag);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CompoundTag readStructureTag(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException {
|
||||||
|
byte[] structureBytes = toBytes(stream);
|
||||||
|
CompoundTag currentTag = NbtIo.readCompressed(new ByteArrayInputStream(structureBytes));
|
||||||
|
if (!currentTag.contains("DataVersion", 99)) {
|
||||||
|
currentTag.putInt("DataVersion", 500);
|
||||||
|
}
|
||||||
|
int currentDataVersion = currentTag.getInt("DataVersion");
|
||||||
|
if(currentDataVersion < SharedConstants.getCurrentVersion().getWorldVersion()) {
|
||||||
|
/* Needs upgrade, try looking up from cache */
|
||||||
|
MessageDigest hasher = digestThreadLocal.get();
|
||||||
|
hasher.reset();
|
||||||
|
String hash = new String(Hex.encodeHex(hasher.digest(structureBytes)));
|
||||||
|
CompoundTag cachedUpgraded = getCachedUpgraded(location, hash);
|
||||||
|
if(cachedUpgraded != null && cachedUpgraded.getInt("DataVersion") == SharedConstants.getCurrentVersion().getWorldVersion()) {
|
||||||
|
ModernFix.LOGGER.warn("Using cached upgraded version of {}", location);
|
||||||
|
currentTag = cachedUpgraded;
|
||||||
|
} else {
|
||||||
|
currentTag = NbtUtils.update(datafixer, DataFixTypes.STRUCTURE, currentTag, currentDataVersion,
|
||||||
|
SharedConstants.getCurrentVersion().getWorldVersion());
|
||||||
|
saveCachedUpgraded(location, hash, currentTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File getCachePath(ResourceLocation location, String hash) {
|
||||||
|
String fileName = location.getNamespace() + "_" + location.getPath().replace('/', '_') + "_" + hash + ".nbt";
|
||||||
|
return new File(STRUCTURE_CACHE_FOLDER, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized CompoundTag getCachedUpgraded(ResourceLocation location, String hash) {
|
||||||
|
File theFile = getCachePath(location, hash);
|
||||||
|
try {
|
||||||
|
return NbtIo.readCompressed(theFile);
|
||||||
|
} catch(FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized void saveCachedUpgraded(ResourceLocation location, String hash, CompoundTag tagToSave) {
|
||||||
|
File theFile = getCachePath(location, hash);
|
||||||
|
try {
|
||||||
|
NbtIo.writeCompressed(tagToSave, theFile);
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] toBytes(InputStream stream) throws IOException {
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
byte[] tmp = new byte[16384];
|
||||||
|
int n;
|
||||||
|
while ((n = stream.read(tmp, 0, tmp.length)) != -1) {
|
||||||
|
buffer.write(tmp, 0, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
"perf.kubejs.CustomIngredientMixin",
|
"perf.kubejs.CustomIngredientMixin",
|
||||||
"perf.fast_registry_validation.ForgeRegistryMixin",
|
"perf.fast_registry_validation.ForgeRegistryMixin",
|
||||||
"perf.cache_strongholds.ChunkGeneratorMixin",
|
"perf.cache_strongholds.ChunkGeneratorMixin",
|
||||||
|
"perf.cache_upgraded_structures.StructureManagerMixin",
|
||||||
"perf.cache_strongholds.ServerLevelMixin"
|
"perf.cache_strongholds.ServerLevelMixin"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user