diff --git a/src/main/java/net/ltxprogrammer/changed/datagen/GatherData.java b/src/main/java/net/ltxprogrammer/changed/datagen/GatherData.java index a2b405624..c8b20e233 100644 --- a/src/main/java/net/ltxprogrammer/changed/datagen/GatherData.java +++ b/src/main/java/net/ltxprogrammer/changed/datagen/GatherData.java @@ -1,5 +1,7 @@ package net.ltxprogrammer.changed.datagen; +import net.ltxprogrammer.changed.datagen.ability.AbilityNodesProvider; +import net.ltxprogrammer.changed.datagen.ability.AbilityTreeProvider; import net.minecraft.core.HolderLookup; import net.minecraft.data.DataGenerator; import net.minecraft.data.PackOutput; @@ -29,6 +31,8 @@ public static void onGatherData(GatherDataEvent event) { generator.addProvider(event.includeServer(), new DatapackEntriesProvider(packOutput, lookupProvider)).getRegistryProvider(); generator.addProvider(event.includeServer(), new DamageTypeTagProvider(packOutput, lookup0, helper)); + generator.addProvider(event.includeServer(), new AbilityNodesProvider(packOutput)); + generator.addProvider(event.includeServer(), new AbilityTreeProvider(packOutput)); // BlockTagsProvider blocks = new BlockTagsProvider(packOutput, lookupProvider, helper); // generator.addProvider(true, blocks); diff --git a/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodeDataProvider.java b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodeDataProvider.java new file mode 100644 index 000000000..303ca4df1 --- /dev/null +++ b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodeDataProvider.java @@ -0,0 +1,159 @@ +package net.ltxprogrammer.changed.datagen.ability; + +import com.google.gson.JsonElement; +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.JsonOps; +import net.ltxprogrammer.changed.ability.tree.*; +import net.ltxprogrammer.changed.ability.tree.PartialNode.TreeReference; +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataProvider; +import net.minecraft.data.PackOutput; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.NotNull; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +public abstract class AbilityNodeDataProvider implements DataProvider { + protected final PackOutput output; + protected final String modid; + private final Map nodeBuilders = new HashMap<>(); + + public AbilityNodeDataProvider(PackOutput output, String modid) { + this.output = output; + this.modid = modid; + } + + protected abstract void addNodes(); + + protected AbilityNodeBuilder addNode(ResourceLocation loc){ + return nodeBuilders.computeIfAbsent(loc, l -> new AbilityNodeBuilder()); + } + + @Override + public @NotNull CompletableFuture run(@NotNull CachedOutput cache) { + addNodes(); + + List> futures = new ArrayList<>(); + + Path outFolder = output.getOutputFolder(), path; + AbilityNode node; + JsonElement json; + for (var entry : nodeBuilders.entrySet()) { + ResourceLocation loc = entry.getKey(); + node = entry.getValue().build(loc); + + path = outFolder.resolve("data/" + modid + "/ability/nodes/" + loc.getPath() + ".json"); + + json = AbilityNode.CODEC.encodeStart(JsonOps.INSTANCE, node) + .result() + .orElseThrow(() -> new IllegalStateException("Failed to encode AbilityNode: " + loc)); + + futures.add(DataProvider.saveStable(cache, json, path)); + } + + return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)); + } + + @Override + public @NotNull String getName() { + return "Ability Node Provider"; + } + + public static final class AbilityNodeBuilder { + private Either parent; + private NodeDisplayInfo displayInfo = NodeDisplayInfo.MISSING; + private final List occludes = new ArrayList<>(); + private String titleId = ""; + private String requirementsId = ""; + private String descriptionId = ""; + private String flavorId = ""; + private int price = 0; + private int groupDiscount = 0; + private final List acquiredEffects = new ArrayList<>(); + private final List missingEffects = new ArrayList<>(); + + private AbilityNodeBuilder() {} + + public AbilityNodeBuilder parent(ResourceLocation parentNode) { + this.parent = Either.left(parentNode); + return this; + } + + public AbilityNodeBuilder parent(TreeReference treeRootReference) { + this.parent = Either.right(treeRootReference); + return this; + } + + public AbilityNodeBuilder display(NodeDisplayInfo displayInfo) { + this.displayInfo = displayInfo; + return this; + } + + public AbilityNodeBuilder occludes(ResourceLocation nodeLocation) { + this.occludes.add(nodeLocation); + return this; + } + + public AbilityNodeBuilder title(String titleId) { + this.titleId = titleId; + return this; + } + + public AbilityNodeBuilder requirements(String requirementsId) { + this.requirementsId = requirementsId; + return this; + } + + public AbilityNodeBuilder description(String descriptionId) { + this.descriptionId = descriptionId; + return this; + } + + public AbilityNodeBuilder flavor(String flavorId) { + this.flavorId = flavorId; + return this; + } + + public AbilityNodeBuilder price(int price) { + this.price = price; + return this; + } + + public AbilityNodeBuilder groupDiscount(int groupDiscount) { + this.groupDiscount = groupDiscount; + return this; + } + + public AbilityNodeBuilder acquiredEffect(NodeEffect effect) { + this.acquiredEffects.add(effect); + return this; + } + + public AbilityNodeBuilder missingEffect(NodeEffect effect) { + this.missingEffects.add(effect); + return this; + } + + private AbilityNode build(ResourceLocation loc) { + if (this.parent == null) { + throw new IllegalStateException("AbilityNode '" + loc + "' must have a defined parent!"); + } + if (this.titleId.isEmpty()) { + this.titleId = "ability.node." + loc.getNamespace() + "." + loc.getPath(); + } + + AbilityNode node = new AbilityNode( + parent, displayInfo, occludes, + titleId, requirementsId, descriptionId, flavorId, + price, groupDiscount, acquiredEffects, missingEffects + ); + node.setNodeLocation(loc); + return node; + } + } +} diff --git a/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodeProvider.java b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodeProvider.java deleted file mode 100644 index 241e857bb..000000000 --- a/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodeProvider.java +++ /dev/null @@ -1,82 +0,0 @@ -package net.ltxprogrammer.changed.datagen.ability; - -import com.google.gson.JsonElement; -import com.mojang.serialization.JsonOps; -import net.ltxprogrammer.changed.ability.tree.AbilityNode; -import net.ltxprogrammer.changed.ability.tree.AbilityTree; -import net.ltxprogrammer.changed.data.RegistryElementPredicate; -import net.ltxprogrammer.changed.entity.variant.TransfurVariant; -import net.minecraft.data.CachedOutput; -import net.minecraft.data.DataProvider; -import net.minecraft.data.PackOutput; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -public abstract class AbilityNodeProvider implements DataProvider { - protected final PackOutput output; - protected final String modid; - private final Map nodeBuilders = new HashMap<>(); - - public AbilityNodeProvider(PackOutput output, String modid) { - this.output = output; - this.modid = modid; - } - - protected abstract void addNodes(); - - protected AbilityNodeBuilder addNode(ResourceLocation loc, List>> variants){ - return nodeBuilders.computeIfAbsent(loc, l -> new AbilityNodeBuilder(variants)); - } - - @Override - public @NotNull CompletableFuture run(@NotNull CachedOutput cache) { - addNodes(); - - List> futures = new ArrayList<>(); - - Path outFolder = output.getOutputFolder(), path; - AbilityNode node; - JsonElement json; - for (var entry : nodeBuilders.entrySet()) { - ResourceLocation loc = entry.getKey(); - node = entry.getValue().build(loc); - - path = outFolder.resolve("data/" + modid + "/ability/nodes/" + loc.getPath() + ".json"); - - json = AbilityNode.CODEC.encodeStart(JsonOps.INSTANCE, node) - .result() - .orElseThrow(() -> new IllegalStateException("Failed to encode AbilityNode: " + loc)); - - futures.add(DataProvider.saveStable(cache, json, path)); - } - - return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)); - } - - @Override - public @NotNull String getName() { - return "Ability Node Provider"; - } - - public static final class AbilityNodeBuilder { - private final List>> variants; - - private AbilityNodeBuilder(List>> variants){ - this.variants = variants; - } - - private AbilityNode build(ResourceLocation loc) { - /*AbilityNode tree = new AbilityNode(variants); - tree.setNodeLocation(loc); - return tree;*/ - return null; // TODO - } - } -} diff --git a/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodesProvider.java b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodesProvider.java new file mode 100644 index 000000000..33e0cf218 --- /dev/null +++ b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityNodesProvider.java @@ -0,0 +1,16 @@ +package net.ltxprogrammer.changed.datagen.ability; + +import net.ltxprogrammer.changed.Changed; +import net.minecraft.data.PackOutput; + +public class AbilityNodesProvider extends AbilityNodeDataProvider { + + + public AbilityNodesProvider(PackOutput output) { + super(output, Changed.MODID); + } + + @Override + protected void addNodes() { + } +} diff --git a/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityTreeDataProvider.java b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityTreeDataProvider.java new file mode 100644 index 000000000..1f202146a --- /dev/null +++ b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityTreeDataProvider.java @@ -0,0 +1,142 @@ +package net.ltxprogrammer.changed.datagen.ability; + +import com.google.gson.JsonElement; +import com.mojang.serialization.JsonOps; +import net.ltxprogrammer.changed.ability.tree.AbilityTree; +import net.ltxprogrammer.changed.ability.tree.events.AbstractPointEvent; +import net.ltxprogrammer.changed.data.RegistryElementPredicate; +import net.ltxprogrammer.changed.entity.variant.TransfurVariant; +import net.ltxprogrammer.changed.init.ChangedRegistry; +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataProvider; +import net.minecraft.data.PackOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraftforge.registries.IForgeRegistry; +import org.jetbrains.annotations.NotNull; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +public abstract class AbilityTreeDataProvider implements DataProvider { + protected final PackOutput output; + protected final String modid; + protected final Map treeBuilders = new HashMap<>(); + protected final IForgeRegistry> registry; + + public AbilityTreeDataProvider(PackOutput output, String modid) { + this.output = output; + this.modid = modid; + registry = ChangedRegistry.TRANSFUR_VARIANT.get(); + } + + protected abstract void addTrees(); + + protected AbilityTreeBuilder addTree(ResourceLocation loc, List>> variants) { + return treeBuilders.computeIfAbsent(loc, l -> new AbilityTreeBuilder(variants)); + } + + protected void addTree(ResourceLocation loc, AbilityTreeBuilder abilityTreeBuilder) { + this.treeBuilders.putIfAbsent(loc, abilityTreeBuilder); + } + + protected @NotNull List>> getPredicatesFromVariantList(List> variants) { + return variants.stream() + .map(variant -> RegistryElementPredicate.forID(registry, ChangedRegistry.TRANSFUR_VARIANT.getKey(variant))).toList(); + } + + protected RegistryElementPredicate> getPredicatesFromVariantTag(TagKey> variantTag) { + return RegistryElementPredicate.forTag(registry, variantTag); + } + + @Override + public @NotNull CompletableFuture run(@NotNull CachedOutput cache) { + addTrees(); + + List> futures = new ArrayList<>(); + + Path outFolder = output.getOutputFolder(), path; + AbilityTree tree; + JsonElement json; + for (var entry : treeBuilders.entrySet()) { + ResourceLocation loc = entry.getKey(); + tree = entry.getValue().build(loc); + + path = outFolder.resolve("data/" + modid + "/ability/trees/" + loc.getPath() + ".json"); + + json = AbilityTree.CODEC.encodeStart(JsonOps.INSTANCE, tree) + .result() + .orElseThrow(() -> new IllegalStateException("Failed to encode AbilityTree: " + loc)); + + futures.add(DataProvider.saveStable(cache, json, path)); + } + + return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)); + } + + @Override + public @NotNull String getName() { + return "Ability Tree Provider"; + } + + public static final class AbilityTreeBuilder { + private List>> variants; + private final List> pointEvents = new ArrayList<>(); + private String titleId = ""; + private String flavorId = ""; + private boolean hidden = false; + + public AbilityTreeBuilder(List>> variants) { + this.variants = variants; + } + + public AbilityTreeBuilder withVariants(List>> variants) { + this.variants = variants; + return this; + } + + public AbilityTreeBuilder addVariants(List>> variants) { + this.variants.addAll(variants); + return this; + } + + public AbilityTreeBuilder pointEvent(AbstractPointEvent event) { + this.pointEvents.add(event); + return this; + } + + public AbilityTreeBuilder pointEvents(List> events) { + this.pointEvents.addAll(events); + return this; + } + + public AbilityTreeBuilder title(String titleId) { + this.titleId = titleId; + return this; + } + + public AbilityTreeBuilder flavor(String flavorId) { + this.flavorId = flavorId; + return this; + } + + public AbilityTreeBuilder hidden(boolean hidden) { + this.hidden = hidden; + return this; + } + + public AbilityTree build(ResourceLocation loc) { + if (this.titleId.isEmpty()) { + // Fallback automático ou padrão para facilitar a criação de chaves de tradução + this.titleId = "ability.tree." + loc.getNamespace() + "." + loc.getPath(); + } + AbilityTree tree = new AbilityTree(variants, pointEvents, titleId, flavorId, hidden); + tree.setTreeLocation(loc); + return tree; + } + } +} diff --git a/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityTreeProvider.java b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityTreeProvider.java index fe048bec2..0951a1aff 100644 --- a/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityTreeProvider.java +++ b/src/main/java/net/ltxprogrammer/changed/datagen/ability/AbilityTreeProvider.java @@ -1,81 +1,63 @@ package net.ltxprogrammer.changed.datagen.ability; -import com.google.gson.JsonElement; -import com.mojang.serialization.JsonOps; -import net.ltxprogrammer.changed.ability.tree.AbilityTree; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import net.ltxprogrammer.changed.Changed; +import net.ltxprogrammer.changed.ability.tree.PartialNode.TreeReference; import net.ltxprogrammer.changed.data.RegistryElementPredicate; +import net.ltxprogrammer.changed.entity.ChangedEntity; import net.ltxprogrammer.changed.entity.variant.TransfurVariant; -import net.minecraft.data.CachedOutput; -import net.minecraft.data.DataProvider; +import net.ltxprogrammer.changed.init.ChangedRegistry; +import net.ltxprogrammer.changed.init.ChangedTransfurVariants; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.registries.IForgeRegistry; +import net.minecraftforge.registries.RegistryObject; import org.jetbrains.annotations.NotNull; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; -public abstract class AbilityTreeProvider implements DataProvider { - protected final PackOutput output; - protected final String modid; - private final Map treeBuilders = new HashMap<>(); +public class AbilityTreeProvider extends AbilityTreeDataProvider { - public AbilityTreeProvider(PackOutput output, String modid) { - this.output = output; - this.modid = modid; - } + public static final Multimap>> treeForVariants = ArrayListMultimap.create(); - protected abstract void addTrees(); + public static final TreeReference LATEX = new TreeReference(Changed.modResource("latex")); - protected AbilityTreeBuilder addTree(ResourceLocation loc, List>> variants){ - return treeBuilders.computeIfAbsent(loc, l -> new AbilityTreeBuilder(variants)); + public AbilityTreeProvider(PackOutput output) { + super(output, Changed.MODID); } @Override - public @NotNull CompletableFuture run(@NotNull CachedOutput cache) { - addTrees(); - - List> futures = new ArrayList<>(); - - Path outFolder = output.getOutputFolder(), path; - AbilityTree tree; - JsonElement json; - for (var entry : treeBuilders.entrySet()) { - ResourceLocation loc = entry.getKey(); - tree = entry.getValue().build(loc); - - path = outFolder.resolve("data/" + modid + "/ability/trees/" + loc.getPath() + ".json"); - - json = AbilityTree.CODEC.encodeStart(JsonOps.INSTANCE, tree) - .result() - .orElseThrow(() -> new IllegalStateException("Failed to encode AbilityTree: " + loc)); - - futures.add(DataProvider.saveStable(cache, json, path)); - } - - return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)); + protected void addTrees() { + addVariantsToCurrentTrees(); } - @Override - public @NotNull String getName() { - return "Ability Tree Provider"; + @SuppressWarnings("unchecked") + public static void addEntry(TreeReference reference, RegistryObject> register) { + // O cast para (RegistryObject) remove a invariância estrita e permite converter para a assinatura com o wildcard + AbilityTreeProvider.treeForVariants.put(reference, (RegistryObject>) (RegistryObject) register); } - public static final class AbilityTreeBuilder { - private final List>> variants; + // Call this after all tree registrations or else it will fail. + private void addVariantsToCurrentTrees() { + var registry = ChangedRegistry.TRANSFUR_VARIANT.get(); + for (TreeReference treeReference : treeForVariants.keySet()) { + ResourceLocation treeLoc = treeReference.treeName(); + AbilityTreeBuilder builder = this.treeBuilders.get(treeLoc); - private AbilityTreeBuilder(List>> variants){ - this.variants = variants; - } + if (builder != null) { + Collection>> registeredVariants = treeForVariants.get(treeReference); + + List>> predicates = registeredVariants.stream() + .map(variant -> RegistryElementPredicate.forID(registry, variant.getId())) + .collect(Collectors.toList()); - private AbilityTree build(ResourceLocation loc) { - /*AbilityTree tree = new AbilityTree(variants); - tree.setTreeLocation(loc); - return tree;*/ - return null; // TODO + builder.withVariants(predicates); + } else { + Changed.LOGGER.warn("Attempted to inject variants into non-existent ability tree: {}", treeLoc); + } } } -} +} \ No newline at end of file diff --git a/src/main/java/net/ltxprogrammer/changed/datagen/ability/README.md b/src/main/java/net/ltxprogrammer/changed/datagen/ability/README.md new file mode 100644 index 000000000..b825d5f1f --- /dev/null +++ b/src/main/java/net/ltxprogrammer/changed/datagen/ability/README.md @@ -0,0 +1 @@ +TODO: Explain how to use the datagen. \ No newline at end of file diff --git a/src/main/java/net/ltxprogrammer/changed/init/ChangedTransfurVariants.java b/src/main/java/net/ltxprogrammer/changed/init/ChangedTransfurVariants.java index 7db79d685..dcfb0b8d8 100644 --- a/src/main/java/net/ltxprogrammer/changed/init/ChangedTransfurVariants.java +++ b/src/main/java/net/ltxprogrammer/changed/init/ChangedTransfurVariants.java @@ -1,6 +1,10 @@ package net.ltxprogrammer.changed.init; import net.ltxprogrammer.changed.Changed; +import net.ltxprogrammer.changed.ability.tree.PartialNode; +import net.ltxprogrammer.changed.ability.tree.PartialNode.TreeReference; +import net.ltxprogrammer.changed.datagen.ability.AbilityTreeDataProvider; +import net.ltxprogrammer.changed.datagen.ability.AbilityTreeProvider; import net.ltxprogrammer.changed.entity.*; import net.ltxprogrammer.changed.entity.ai.EntityAssimilationBehavior; import net.ltxprogrammer.changed.entity.ai.TransfurDecider; @@ -205,6 +209,14 @@ private static RegistryObject> regi return REGISTRY.register(name, builder::build); } + private static RegistryObject> registerWithAbilityTree(String name, TransfurVariant.Builder builder, TreeReference... treeReference) { + RegistryObject> register = REGISTRY.register(name, builder::build); + for (TreeReference reference : treeReference) { + AbilityTreeProvider.addEntry(reference, register); + } + return register; + } + public static class Gendered { private static final List> PAIRS = new ArrayList<>(); diff --git a/src/main/resources/assets/changed/lang/sr_sp.json b/src/main/resources/assets/changed/lang/sr_sp.json index c21917ca0..088da31aa 100644 --- a/src/main/resources/assets/changed/lang/sr_sp.json +++ b/src/main/resources/assets/changed/lang/sr_sp.json @@ -317,6 +317,11 @@ "block.changed.red_pillow": "Црвени јастук", "block.changed.white_pillow": "Бели јастук", "block.changed.yellow_pillow": "Жути јастук", + "block.changed.dark_latex_fluid": "Тамна латекс течност", + "block.changed.skunk_gas": "Твор гас", + "block.changed.tiger_gas": "Тигар гас", + "block.changed.white_latex_fluid": "Бела латекс течност", + "block.changed.wolf_gas": "вучји гас", "fluid.changed.dark_latex": "Течни тамни латекс", "fluid.changed.white_latex": "Течни бели латекс", @@ -402,6 +407,7 @@ "entity.changed.phage_latex_wolf_female": "Латекс вукица-бактериофаг", "entity.changed.phage_latex_wolf_male": "Латекс вук-бактериофаг", "entity.changed.pure_white_latex_wolf": "Чисти латекс вук", + "entity.changed.pure_white_latex_cerberus": "Церберус направљен од лаког латекса", "item.changed.gas_wolf_spawn_egg": "Јаје призивања Гасни вук", "item.changed.dark_latex_wolf_female_spawn_egg": "Јаје призивања Вукица од тамног латекса", @@ -472,6 +478,7 @@ "item.changed.phage_latex_wolf_female_spawn_egg": "Јаје призивања Латекс вукица-бактериофаг", "item.changed.phage_latex_wolf_male_spawn_egg": "Јаје призивања Латекс вук-бактериофаг", "item.changed.pure_white_latex_wolf_spawn_egg": "Јаје призивања Чисти латекс вук", + "item.changed.pure_white_latex_cerberus_spawn_egg": "Јаје призивања Церберус направљен од лаког латекса", "changed.patreon.level0": "Члан Дисцорд сервера", "changed.patreon.level1": "I Левел",