From 0feb152eac409e90c2ffd3768c48dbb06421e1a5 Mon Sep 17 00:00:00 2001 From: lcy0x1 Date: Thu, 27 Jun 2024 11:38:08 +0800 Subject: [PATCH] bring back advancements --- .gitignore | 1 + .../advancements/AdvancementGenerator.java | 163 ++++++++++++++++++ .../serial/advancements/BaseCriterion.java | 24 +++ .../advancements/BaseCriterionInstance.java | 18 ++ .../serial/advancements/CriterionBuilder.java | 118 +++++++++++++ .../serial/advancements/IAdvBuilder.java | 14 ++ .../serial/advancements/ModLoadedAdv.java | 18 ++ .../serial/advancements/RewardBuilder.java | 27 +++ .../serial/advancements/package-info.java | 8 + 9 files changed, 391 insertions(+) create mode 100644 src/main/java/dev/xkmc/l2core/serial/advancements/AdvancementGenerator.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/advancements/BaseCriterion.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/advancements/BaseCriterionInstance.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/advancements/CriterionBuilder.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/advancements/IAdvBuilder.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/advancements/ModLoadedAdv.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/advancements/RewardBuilder.java create mode 100644 src/main/java/dev/xkmc/l2core/serial/advancements/package-info.java diff --git a/.gitignore b/.gitignore index b18a17a..86a60ab 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ hs_err_pid* .idea .gradle build +runs run .DS_Store diff --git a/src/main/java/dev/xkmc/l2core/serial/advancements/AdvancementGenerator.java b/src/main/java/dev/xkmc/l2core/serial/advancements/AdvancementGenerator.java new file mode 100644 index 0000000..0529c87 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/advancements/AdvancementGenerator.java @@ -0,0 +1,163 @@ +package dev.xkmc.l2core.serial.advancements; + +import com.tterrag.registrate.providers.RegistrateAdvancementProvider; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementHolder; +import net.minecraft.advancements.AdvancementType; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +@SuppressWarnings("unused") +public class AdvancementGenerator { + + private final RegistrateAdvancementProvider pvd; + private final String modid; + + public AdvancementGenerator(RegistrateAdvancementProvider pvd, String modid) { + this.pvd = pvd; + this.modid = modid; + } + + public class TabBuilder { + + private final String tab; + private final ResourceLocation bg; + + private Entry root; + + public TabBuilder(String tab) { + this.tab = tab; + this.bg = ResourceLocation.fromNamespaceAndPath(modid, "textures/gui/advancements/backgrounds/" + tab + ".png"); + } + + public void build() { + root.build(); + } + + public Entry root(String id, Item item, CriterionBuilder builder, String title, String desc) { + return root(id, item.getDefaultInstance(), builder, title, desc); + } + + public Entry root(String id, ItemStack item, CriterionBuilder builder, String title, String desc) { + if (root == null) { + root = new Entry(new EntryData(id, item, builder, title, desc), null); + } + return root; + } + + public Entry hidden(String id, CriterionBuilder builder) { + return new Entry(new EntryData(id, ItemStack.EMPTY, builder, "", ""), null); + } + + public class Entry { + + private final List children = new ArrayList<>(); + private final EntryData data; + private final ResourceLocation rl; + private final Entry parent; + + private AdvancementType type = AdvancementType.TASK; + private boolean showToast = true, announce = true, hidden = false; + private AdvancementHolder result; + + private Entry(EntryData data, @Nullable Entry parent) { + this.data = data; + this.parent = parent; + if (parent == null) { + showToast = false; + announce = false; + rl = bg; + } else { + rl = null; + } + } + + public Entry create(String id, Item item, CriterionBuilder builder, String title, String desc) { + return create(id, item.getDefaultInstance(), builder, title, desc); + } + + public Entry create(String id, ItemStack item, CriterionBuilder builder, String title, String desc) { + Entry sub = new Entry(new EntryData(id, item, builder, title, desc), this); + children.add(sub); + return sub; + } + + /*TODO + public Entry patchouli(L2Registrate reg, CriterionBuilder builder, ResourceLocation book, String title, String desc) { + ItemStack stack = PatchouliHelper.getBook(book); + return create("patchouli", stack, builder, title, desc) + .add(new ModLoadedAdv("patchouli")) + .add(new RewardBuilder(reg, 0, book, () -> PatchouliHelper.getBookLoot(book))); + }*/ + + public Entry root() { + return root; + } + + public Entry enter() { + return children.getLast(); + } + + public Entry type(AdvancementType type) { + this.type = type; + return this; + } + + public Entry type(AdvancementType type, boolean showToast, boolean announce, boolean hidden) { + this.type = type; + this.showToast = showToast; + this.announce = announce; + this.hidden = hidden; + return this; + } + + public Entry add(IAdvBuilder builder) { + data.builder.add(builder); + return this; + } + + public void build() { + var builder = Advancement.Builder.advancement(); + if (!data.item.isEmpty()) { + builder.display(data.item, + pvd.title(modid, "advancements." + tab + "." + data.id, data.title), + pvd.desc(modid, "advancements." + tab + "." + data.id, data.desc), + rl, type, showToast, announce, hidden); + } + if (parent != null) { + builder.parent(parent.result); + } + + String uid = modid + ":" + tab + "/" + data.id; + for (var e : data.builder) { + e.modify(uid, builder); + e.onBuild(); + } + result = builder.save(pvd, uid); + for (Entry e : children) { + e.build(); + } + } + + public void finish() { + TabBuilder.this.build(); + } + + } + + } + + private record EntryData(String id, ItemStack item, List builder, String title, String desc) { + + EntryData(String id, ItemStack item, IAdvBuilder builder, String title, String desc) { + this(id, item, new ArrayList<>(List.of(builder)), title, desc); + } + + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/advancements/BaseCriterion.java b/src/main/java/dev/xkmc/l2core/serial/advancements/BaseCriterion.java new file mode 100644 index 0000000..1a155f0 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/advancements/BaseCriterion.java @@ -0,0 +1,24 @@ +package dev.xkmc.l2core.serial.advancements; + +import com.mojang.serialization.Codec; +import dev.xkmc.l2serial.serialization.codec.CodecAdaptor; +import net.minecraft.advancements.critereon.ContextAwarePredicate; +import net.minecraft.advancements.critereon.SimpleCriterionTrigger; +import net.minecraft.resources.ResourceLocation; + +import java.util.function.BiFunction; + +public class BaseCriterion, R extends BaseCriterion> extends SimpleCriterionTrigger { + + private final Codec codec; + + public BaseCriterion(Class cls) { + this.codec = new CodecAdaptor<>(cls); + } + + @Override + public Codec codec() { + return codec; + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/advancements/BaseCriterionInstance.java b/src/main/java/dev/xkmc/l2core/serial/advancements/BaseCriterionInstance.java new file mode 100644 index 0000000..f22ce53 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/advancements/BaseCriterionInstance.java @@ -0,0 +1,18 @@ +package dev.xkmc.l2core.serial.advancements; + +import dev.xkmc.l2serial.serialization.marker.SerialClass; +import net.minecraft.advancements.critereon.ContextAwarePredicate; +import net.minecraft.advancements.critereon.SimpleCriterionTrigger; + +import java.util.Optional; + +@SerialClass +public class BaseCriterionInstance, R extends BaseCriterion> + implements SimpleCriterionTrigger.SimpleInstance { + + @Override + public Optional player() { + return Optional.empty(); + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/advancements/CriterionBuilder.java b/src/main/java/dev/xkmc/l2core/serial/advancements/CriterionBuilder.java new file mode 100644 index 0000000..ab6722e --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/advancements/CriterionBuilder.java @@ -0,0 +1,118 @@ +package dev.xkmc.l2core.serial.advancements; + +import com.mojang.datafixers.util.Pair; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementRequirements; +import net.minecraft.advancements.Criterion; +import net.minecraft.advancements.critereon.*; +import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponentPredicate; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.level.ItemLike; + +import java.util.ArrayList; +import java.util.List; + +public class CriterionBuilder implements IAdvBuilder { + + @Deprecated + public static CriterionBuilder none() { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item())); + } + + public static CriterionBuilder item(Item item) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(item)); + } + + public static CriterionBuilder item(TagKey item, DataComponentPredicate tag) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item().of(item).hasComponents(tag).build())); + } + + public static CriterionBuilder item(ItemLike item, DataComponentPredicate tag) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item().of(item).hasComponents(tag).build())); + } + + public static CriterionBuilder items(Item... item) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item().of(item).build())); + } + + public static CriterionBuilder item(TagKey item) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item().of(item).build())); + } + + public static CriterionBuilder book(Holder enchantment) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item() + .withSubPredicate(ItemSubPredicates.STORED_ENCHANTMENTS, + ItemEnchantmentsPredicate.storedEnchantments(List.of( + new EnchantmentPredicate(enchantment, MinMaxBounds.Ints.ANY)))))); + } + + public static CriterionBuilder enchanted(Holder enchantment) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item() + .withSubPredicate(ItemSubPredicates.ENCHANTMENTS, + ItemEnchantmentsPredicate.enchantments(List.of( + new EnchantmentPredicate(enchantment, MinMaxBounds.Ints.ANY)))))); + } + + public static CriterionBuilder enchanted(ItemLike item, Holder enchantment) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item().of(item) + .withSubPredicate(ItemSubPredicates.ENCHANTMENTS, + ItemEnchantmentsPredicate.enchantments(List.of( + new EnchantmentPredicate(enchantment, MinMaxBounds.Ints.ANY)))))); + } + + public static CriterionBuilder enchanted(TagKey item, Holder enchantment) { + return one(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item().of(item) + .withSubPredicate(ItemSubPredicates.ENCHANTMENTS, + ItemEnchantmentsPredicate.enchantments(List.of( + new EnchantmentPredicate(enchantment, MinMaxBounds.Ints.ANY)))))); + } + + public static CriterionBuilder one(Criterion instance) { + return new CriterionBuilder(RequirementsStrategy.AND).add(instance); + } + + public enum RequirementsStrategy { + AND, OR; + } + + public static CriterionBuilder and() { + return new CriterionBuilder(RequirementsStrategy.AND); + } + + public static CriterionBuilder or() { + return new CriterionBuilder(RequirementsStrategy.OR); + } + + private final RequirementsStrategy req; + private final List>> list = new ArrayList<>(); + + private CriterionBuilder(RequirementsStrategy req) { + this.req = req; + } + + public CriterionBuilder add(Criterion instance) { + return add(list.size() + "", instance); + } + + public CriterionBuilder add(String str, Criterion instance) { + list.add(Pair.of(str, instance)); + return this; + } + + public void modify(String id, Advancement.Builder builder) { + if (list.size() > 1) { + var ids = list.stream().map(Pair::getFirst).toList(); + builder.requirements(req == RequirementsStrategy.AND ? + AdvancementRequirements.allOf(ids) : + AdvancementRequirements.anyOf(ids) + ); + } + for (var c : list) { + builder.addCriterion(c.getFirst(), c.getSecond()); + } + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/advancements/IAdvBuilder.java b/src/main/java/dev/xkmc/l2core/serial/advancements/IAdvBuilder.java new file mode 100644 index 0000000..b76f2b5 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/advancements/IAdvBuilder.java @@ -0,0 +1,14 @@ +package dev.xkmc.l2core.serial.advancements; + +import net.minecraft.advancements.Advancement; + +public interface IAdvBuilder { + + default void modify(String id, Advancement.Builder builder) { + + } + + default void onBuild() { + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/advancements/ModLoadedAdv.java b/src/main/java/dev/xkmc/l2core/serial/advancements/ModLoadedAdv.java new file mode 100644 index 0000000..04e24a0 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/advancements/ModLoadedAdv.java @@ -0,0 +1,18 @@ +package dev.xkmc.l2core.serial.advancements; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +public record ModLoadedAdv(String... modid) implements IAdvBuilder { + + @Override + public void addConditions(JsonArray conditions) { + for (String str : modid) { + JsonObject condition = new JsonObject(); + condition.addProperty("type", "forge:mod_loaded"); + condition.addProperty("modid", str); + conditions.add(condition); + } + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/advancements/RewardBuilder.java b/src/main/java/dev/xkmc/l2core/serial/advancements/RewardBuilder.java new file mode 100644 index 0000000..d571ba4 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/advancements/RewardBuilder.java @@ -0,0 +1,27 @@ +package dev.xkmc.l2core.serial.advancements; + +import com.tterrag.registrate.providers.ProviderType; +import dev.xkmc.l2core.init.reg.registrate.L2Registrate; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementRewards; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.storage.loot.LootTable; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + +import java.util.function.Supplier; + +public record RewardBuilder(L2Registrate reg, int exp, ResourceKey loot, + Supplier sup) implements IAdvBuilder { + + @Override + public void modify(String id, Advancement.Builder builder) { + builder.rewards(AdvancementRewards.Builder.loot(loot).addExperience(exp).build()); + } + + @Override + public void onBuild() { + reg.addDataGenerator(ProviderType.LOOT, e -> e.addLootAction(LootContextParamSets.EMPTY, + x -> x.accept(loot, sup.get()))); + } + +} diff --git a/src/main/java/dev/xkmc/l2core/serial/advancements/package-info.java b/src/main/java/dev/xkmc/l2core/serial/advancements/package-info.java new file mode 100644 index 0000000..9cefa92 --- /dev/null +++ b/src/main/java/dev/xkmc/l2core/serial/advancements/package-info.java @@ -0,0 +1,8 @@ +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault + +package dev.xkmc.l2core.serial.advancements; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file