Remove upgraded structure caching
Performance improvement is minimal with rewritten DFU and it breaks structure generation on 1.21 for some reason
This commit is contained in:
parent
a6e0785252
commit
180606eea1
|
|
@ -2,58 +2,9 @@ package org.embeddedt.modernfix.command;
|
|||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.structure.CachingStructureManager;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class ModernFixCommands {
|
||||
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
dispatcher.register(literal("modernfix")
|
||||
.then(literal("upgradeStructures")
|
||||
.requires(source -> source.hasPermission(3))
|
||||
.executes(context -> {
|
||||
ServerLevel level = context.getSource().getLevel();
|
||||
if(level == null) {
|
||||
context.getSource().sendFailure(Component.literal("Couldn't find server level"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ResourceManager manager = level.getServer().resources.resourceManager();
|
||||
Map<ResourceLocation, Resource> structures = manager.listResources("structures", p -> p.getPath().endsWith(".nbt"));
|
||||
int upgradedNum = 0;
|
||||
Pattern pathPattern = Pattern.compile("^structures/(.*)\\.nbt$");
|
||||
for(Map.Entry<ResourceLocation, Resource> entry : structures.entrySet()) {
|
||||
upgradedNum++;
|
||||
ResourceLocation found = entry.getKey();
|
||||
Matcher matcher = pathPattern.matcher(found.getPath());
|
||||
if(!matcher.matches())
|
||||
continue;
|
||||
ResourceLocation structureLocation = ResourceLocation.fromNamespaceAndPath(found.getNamespace(), matcher.group(1));
|
||||
try(InputStream resource = entry.getValue().open()) {
|
||||
CachingStructureManager.readStructureTag(structureLocation, level.getServer().getFixerUpper(), resource);
|
||||
Component msg = Component.literal("checked " + structureLocation + " (" + upgradedNum + "/" + structures.size() + ")");
|
||||
context.getSource().sendSuccess(() -> msg, false);
|
||||
} catch(Throwable e) {
|
||||
ModernFix.LOGGER.error("Couldn't upgrade structure " + found, e);
|
||||
context.getSource().sendFailure(Component.literal("error reading " + structureLocation + " (" + upgradedNum + "/" + structures.size() + ")"));
|
||||
}
|
||||
}
|
||||
|
||||
context.getSource().sendSuccess(() -> Component.literal("All structures upgraded"), false);
|
||||
|
||||
return 1;
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
package org.embeddedt.modernfix.common.mixin.perf.cache_upgraded_structures;
|
||||
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import net.minecraft.core.HolderGetter;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.structure.CachingStructureManager;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(StructureTemplateManager.class)
|
||||
public class StructureManagerMixin {
|
||||
@Shadow @Final private DataFixer fixerUpper;
|
||||
|
||||
@Shadow private ResourceManager resourceManager;
|
||||
|
||||
@Shadow @Final private HolderGetter<Block> blockLookup;
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason use our own manager to avoid needless DFU updates
|
||||
*/
|
||||
@Overwrite
|
||||
private Optional<StructureTemplate> loadFromResource(ResourceLocation id) {
|
||||
ResourceLocation arg = ResourceLocation.fromNamespaceAndPath(id.getNamespace(), "structures/" + id.getPath() + ".nbt");
|
||||
try(InputStream stream = this.resourceManager.open(arg)) {
|
||||
return Optional.of(CachingStructureManager.readStructure(id, this.fixerUpper, stream, this.blockLookup));
|
||||
} catch(FileNotFoundException e) {
|
||||
return Optional.empty();
|
||||
} catch(IOException e) {
|
||||
ModernFix.LOGGER.error("Can't read structure", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
package org.embeddedt.modernfix.structure;
|
||||
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.HolderGetter;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtAccounter;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.datafix.DataFixTypes;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
|
||||
import org.embeddedt.modernfix.util.FileUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Set;
|
||||
|
||||
public class CachingStructureManager {
|
||||
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-256");
|
||||
} catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
private static final File STRUCTURE_CACHE_FOLDER = FileUtil.childFile(ModernFixPlatformHooks.INSTANCE.getGameDirectory().resolve("modernfix").resolve("structureCacheV1").toFile());
|
||||
|
||||
static {
|
||||
STRUCTURE_CACHE_FOLDER.mkdirs();
|
||||
}
|
||||
|
||||
public static StructureTemplate readStructure(ResourceLocation location, DataFixer datafixer, InputStream stream, HolderGetter<Block> blockGetter) throws IOException {
|
||||
CompoundTag tag = readStructureTag(location, datafixer, stream);
|
||||
StructureTemplate template = new StructureTemplate();
|
||||
template.load(blockGetter, tag);
|
||||
return template;
|
||||
}
|
||||
|
||||
private static String encodeHex(byte[] byteArray) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(byte b : byteArray) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static final Set<String> laggyStructureMods = new ObjectOpenHashSet<>();
|
||||
|
||||
private static final int MAX_HASH_LENGTH = 9;
|
||||
|
||||
private static String truncateHash(String hash) {
|
||||
return hash.substring(0, MAX_HASH_LENGTH + 1);
|
||||
}
|
||||
|
||||
public static CompoundTag readStructureTag(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException {
|
||||
byte[] structureBytes = toBytes(stream);
|
||||
CompoundTag currentTag = NbtIo.readCompressed(new ByteArrayInputStream(structureBytes), NbtAccounter.unlimitedHeap());
|
||||
if (!currentTag.contains("DataVersion", 99)) {
|
||||
currentTag.putInt("DataVersion", 500);
|
||||
}
|
||||
int currentDataVersion = currentTag.getInt("DataVersion");
|
||||
int requiredMinimumDataVersion = SharedConstants.getCurrentVersion().getDataVersion().getVersion();
|
||||
if(currentDataVersion < requiredMinimumDataVersion) {
|
||||
/* Needs upgrade, try looking up from cache */
|
||||
MessageDigest hasher = digestThreadLocal.get();
|
||||
hasher.reset();
|
||||
String hash = encodeHex(hasher.digest(structureBytes));
|
||||
CompoundTag cachedUpgraded = getCachedUpgraded(location, truncateHash(hash));
|
||||
if(cachedUpgraded == null)
|
||||
cachedUpgraded = getCachedUpgraded(location, hash); /* pick up old cache */
|
||||
if(cachedUpgraded != null && cachedUpgraded.getInt("DataVersion") == requiredMinimumDataVersion) {
|
||||
ModernFix.LOGGER.debug("Using cached upgraded version of {}", location);
|
||||
currentTag = cachedUpgraded;
|
||||
} else {
|
||||
/*
|
||||
synchronized (laggyStructureMods) {
|
||||
if(laggyStructureMods.add(location.getNamespace())) {
|
||||
ModernFix.LOGGER.warn("The namespace {} contains an outdated structure file, which can cause worldgen lag. Please view debug.log for the full filename, determine which mod provides the structure, and report to the mod/datapack author, including the debug log.", location.getNamespace());
|
||||
}
|
||||
}
|
||||
*/
|
||||
ModernFix.LOGGER.debug("Structure {} is being run through DFU (hash {}), this will cause launch time delays", location, hash);
|
||||
currentTag = DataFixTypes.STRUCTURE.update(datafixer, currentTag, currentDataVersion,
|
||||
SharedConstants.getCurrentVersion().getDataVersion().getVersion());
|
||||
currentTag.putInt("DataVersion", SharedConstants.getCurrentVersion().getDataVersion().getVersion());
|
||||
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(FileInputStream stream = new FileInputStream(theFile)) {
|
||||
return NbtIo.readCompressed(stream, NbtAccounter.unlimitedHeap());
|
||||
} 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, truncateHash(hash));
|
||||
try(FileOutputStream stream = new FileOutputStream(theFile)) {
|
||||
NbtIo.writeCompressed(tagToSave, stream);
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user