From 43a23883e3f35e6dc60e3856c6effb4cd6d7763a Mon Sep 17 00:00:00 2001 From: Mrbysco Date: Tue, 22 Oct 2024 19:48:54 +0200 Subject: [PATCH] Fix village structure --- .../1406a188eb544a1b57b1bc878397d8c7862b79de | 1 + .../data/ActuallyAdditionsData.java | 2 + .../data/StructureUpdater.java | 102 ++++++++++++++++++ .../structure/andrew_period_house.nbt | Bin 6403 -> 6409 bytes 4 files changed, 105 insertions(+) create mode 100644 src/generated/resources/.cache/1406a188eb544a1b57b1bc878397d8c7862b79de create mode 100644 src/main/java/de/ellpeck/actuallyadditions/data/StructureUpdater.java 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 6c06dfe581e6e866f5c8e51e0a9d6b0190e7a9b7..b2122094857c23e749d8734b5bd953c073acdc82 100644 GIT binary patch literal 6409 zcma)A30RZI*0!ycVk3wk1ZAm!EXrcQum#AkQBeVjl_jVwCJM4t+4qDBC2Rqttg<#$ z5m}8W77%EF1QkM93APgeKc`elPj3u-!kI%i+GZ8DQrPkF}rNQ+GH`;4=!g#^a77aid4F-RmV=G<2CD=aiMWE?jFMAL1vc) z<$fmILI;uI^l4zo*cL30cEs_MwlbSn3`^o1=X2-Mu8EnSH%iZ zcACz!x18|m24X*)OFS8J^SYm=+g(~SR=Zy}EujiF`l}YE`g$u?dmmp7S%D&p`?d7% z29oR6nnEgVXA3TxP)da!O~hACY=CK4T3l)AEJ7*_V};2Hn(qG_3}AF+RsOwEbyG~p)zaG< zO4CQA3*1W^5j`CrniI0)g=s2T$@RFg!%vXBrm&omTCY9_}(p4u7u(uol-{>%2 zQ!)PITFl}?M+}Xx#2p^kjv03`Tz!pu-Mh2bI-Xi@H&Gyk3E0UylKe(;>`h2>z7*zZ z8)H4z+wNypbW?ug6?O+A18!{Hv@F@L3?N)|Ln(*RQEll-lA;+guDmy!zM)21kdLfC|+x-N>G(5DBV<>W_E;pg-dsAk`%_$bDW zX_H6vSfp3Hb5|PipzCX~ za~roF>U$#~?7%6v;P9GO46N6Ifj?h3KOK2L84N9Y&AhznB0iuYPY;#G&_+iT(y6u3JVk`RbDBVzJeS}!V=IDL zJ$VKI-1*71iTWaYkR(o+7$^Kh{q-XI8O`tNnmdT+yN<*1P)94yL+1wkw>4%Sk|!i8 zv*TvFbvsP$qA0gIE9Rc(TO9dHBo&p_<-)Dr->QJfFvV+zHT%D3E{T3(mZ(Y8%wLcB zOvr&>-Gdb;{X`4rU3Q461|1n#Tf#?9@)z!JzhKOq;x8ce1w*HgNVYsLt)9olREZ*{S&v|2L(YdeAE2+?lOJBI)G=HK0c zh^i4X+;bx>DI`55L%*?KxQ@P{^&;kfGq8YbtL3v7Q{%3Kp(~J?^B4Nco zILLs(m4l7e4d-=9VM1;OKj2;x1)NQ}{}BEvv1xr+19aN*2~KJIQw#Am*(4MlyJ?vn zPZb!wK6)(~Xjxo9WE4VBf+&9l%%Wke8d5>11a^_MaCPP)72X;HB_h?tgnQ*T{bp?W zxpn-irU<6mxGV(WsJIyzIoUoPq{KVamy7ahmj}s_TL38G6%TO3-_4h7y!yBr8X6L4 zl6^Nj*bO-@TawAS(IJZ?HmKXu_!<Πg88BS~YHzvf{nqZovZGqzNcz{6SwnF>jf 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 DwoJ7G literal 6403 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