diff --git a/src/generated/resources/.cache/1406a188eb544a1b57b1bc878397d8c7862b79de b/src/generated/resources/.cache/1406a188eb544a1b57b1bc878397d8c7862b79de new file mode 100644 index 000000000..5721dccc6 --- /dev/null +++ b/src/generated/resources/.cache/1406a188eb544a1b57b1bc878397d8c7862b79de @@ -0,0 +1 @@ +// 1.21.1 2024-10-22T19:46:05.5548254 Update structure files in /structure diff --git a/src/main/java/de/ellpeck/actuallyadditions/data/ActuallyAdditionsData.java b/src/main/java/de/ellpeck/actuallyadditions/data/ActuallyAdditionsData.java index d0779d836..a8c580497 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/data/ActuallyAdditionsData.java +++ b/src/main/java/de/ellpeck/actuallyadditions/data/ActuallyAdditionsData.java @@ -1,5 +1,6 @@ package de.ellpeck.actuallyadditions.data; +import de.ellpeck.actuallyadditions.api.ActuallyAdditionsAPI; import de.ellpeck.actuallyadditions.data.patchouli.PatchouliGenerator; import de.ellpeck.actuallyadditions.mod.ActuallyAdditions; import de.ellpeck.actuallyadditions.mod.gen.ActuallyBiomeModifiers; @@ -72,6 +73,7 @@ public class ActuallyAdditionsData { generator.addProvider(event.includeServer(), new DatapackBuiltinEntriesProvider( packOutput, patchedProvider, Set.of(ActuallyAdditions.MODID))); + generator.addProvider(true, new StructureUpdater("structure", ActuallyAdditionsAPI.MOD_ID, helper, packOutput)); generator.addProvider(true, new Curios(packOutput, helper, lookupProvider)); } diff --git a/src/main/java/de/ellpeck/actuallyadditions/data/StructureUpdater.java b/src/main/java/de/ellpeck/actuallyadditions/data/StructureUpdater.java new file mode 100644 index 000000000..251ba949b --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/data/StructureUpdater.java @@ -0,0 +1,102 @@ +package de.ellpeck.actuallyadditions.data; + +/* + * BluSunrize + * Copyright (c) 2021 + * + * This code is licensed under "Blu's License of Common Sense". + * Class written by malte0811 and BluSunrize, and used with malte's permission. + */ + +import com.google.common.hash.Hashing; +import com.mojang.datafixers.DataFixer; +import com.mojang.datafixers.DataFixerUpper; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataProvider; +import net.minecraft.data.PackOutput; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtAccounter; +import net.minecraft.nbt.NbtIo; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.MultiPackResourceManager; +import net.minecraft.server.packs.resources.Resource; +import net.minecraft.util.datafix.DataFixTypes; +import net.minecraft.util.datafix.DataFixers; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.neoforged.neoforge.common.data.ExistingFileHelper; + +import javax.annotation.Nonnull; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.concurrent.CompletableFuture; + +public class StructureUpdater implements DataProvider { + private final String basePath; + private final String modid; + private final PackOutput output; + private final MultiPackResourceManager resources; + + public StructureUpdater( + String basePath, String modid, ExistingFileHelper helper, PackOutput output + ) { + this.basePath = basePath; + this.modid = modid; + this.output = output; + try { + Field serverData = ExistingFileHelper.class.getDeclaredField("serverData"); + serverData.setAccessible(true); + resources = (MultiPackResourceManager) serverData.get(helper); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + @Override + public CompletableFuture run(@Nonnull CachedOutput cache) { + try { + for (var entry : resources.listResources(basePath, $ -> true).entrySet()) + if (entry.getKey().getNamespace().equals(modid)) + process(entry.getKey(), entry.getValue(), cache); + return CompletableFuture.completedFuture(null); + } catch (IOException x) { + return CompletableFuture.failedFuture(x); + } + } + + private void process(ResourceLocation loc, Resource resource, CachedOutput cache) throws IOException { + CompoundTag inputNBT = NbtIo.readCompressed(resource.open(), NbtAccounter.unlimitedHeap()); + CompoundTag converted = updateNBT(inputNBT); + if (!converted.equals(inputNBT)) { + Class fixerClass = DataFixers.getDataFixer().getClass(); + if (!fixerClass.equals(DataFixerUpper.class)) + throw new RuntimeException("Structures are not up to date, but unknown data fixer is in use: " + fixerClass.getName()); + writeNBTTo(loc, converted, cache); + } + } + + private void writeNBTTo(ResourceLocation loc, CompoundTag data, CachedOutput cache) throws IOException { + ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); + NbtIo.writeCompressed(data, bytearrayoutputstream); + byte[] bytes = bytearrayoutputstream.toByteArray(); + Path outputPath = output.getOutputFolder().resolve("data/" + loc.getNamespace() + "/" + loc.getPath()); + cache.writeIfNeeded(outputPath, bytes, Hashing.sha1().hashBytes(bytes)); + } + + private static CompoundTag updateNBT(CompoundTag nbt) { + final CompoundTag updatedNBT = DataFixTypes.STRUCTURE.updateToCurrentVersion( + DataFixers.getDataFixer(), nbt, nbt.getInt("DataVersion") + ); + StructureTemplate template = new StructureTemplate(); + template.load(BuiltInRegistries.BLOCK.asLookup(), updatedNBT); + return template.save(new CompoundTag()); + } + + @Nonnull + @Override + public String getName() { + return "Update structure files in /" + basePath + "/"; + } +} \ No newline at end of file diff --git a/src/main/resources/data/actuallyadditions/structure/andrew_period_house.nbt b/src/main/resources/data/actuallyadditions/structure/andrew_period_house.nbt index 6c06dfe58..b21220948 100644 Binary files a/src/main/resources/data/actuallyadditions/structure/andrew_period_house.nbt and b/src/main/resources/data/actuallyadditions/structure/andrew_period_house.nbt differ