diff --git a/Fabric/src/main/java/vazkii/patchouli/fabric/common/FabricModInitializer.java b/Fabric/src/main/java/vazkii/patchouli/fabric/common/FabricModInitializer.java index 7a830a8d..599e4b8f 100644 --- a/Fabric/src/main/java/vazkii/patchouli/fabric/common/FabricModInitializer.java +++ b/Fabric/src/main/java/vazkii/patchouli/fabric/common/FabricModInitializer.java @@ -12,6 +12,7 @@ import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTabs; +import vazkii.patchouli.common.advancement.PatchouliCriteriaTriggers; import vazkii.patchouli.common.base.PatchouliSounds; import vazkii.patchouli.common.book.BookRegistry; import vazkii.patchouli.common.command.OpenBookCommand; @@ -30,6 +31,7 @@ public void onInitialize() { CommandRegistrationCallback.EVENT.register((disp, buildCtx, selection) -> OpenBookCommand.register(disp)); UseBlockCallback.EVENT.register(LecternEventHandler::rightClick); + PatchouliCriteriaTriggers.init(); BookRegistry.INSTANCE.init(); ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, _r, success) -> { diff --git a/Forge/src/main/java/vazkii/patchouli/forge/common/ForgeModInitializer.java b/Forge/src/main/java/vazkii/patchouli/forge/common/ForgeModInitializer.java index 8963c5ce..98130ff5 100644 --- a/Forge/src/main/java/vazkii/patchouli/forge/common/ForgeModInitializer.java +++ b/Forge/src/main/java/vazkii/patchouli/forge/common/ForgeModInitializer.java @@ -15,6 +15,7 @@ import net.minecraftforge.registries.RegisterEvent; import vazkii.patchouli.api.PatchouliAPI; +import vazkii.patchouli.common.advancement.PatchouliCriteriaTriggers; import vazkii.patchouli.common.base.PatchouliSounds; import vazkii.patchouli.common.book.BookRegistry; import vazkii.patchouli.common.command.OpenBookCommand; @@ -73,6 +74,7 @@ public static void onInitialize(FMLCommonSetupEvent evt) { ForgeNetworkHandler.registerMessages(); + PatchouliCriteriaTriggers.init(); BookRegistry.INSTANCE.init(); MinecraftForge.EVENT_BUS.addListener((ServerStartedEvent e) -> ReloadContentsHandler.dataReloaded(e.getServer())); diff --git a/Xplat/src/main/java/vazkii/patchouli/common/advancement/PatchouliBookOpenTrigger.java b/Xplat/src/main/java/vazkii/patchouli/common/advancement/PatchouliBookOpenTrigger.java new file mode 100644 index 00000000..4e0aafcd --- /dev/null +++ b/Xplat/src/main/java/vazkii/patchouli/common/advancement/PatchouliBookOpenTrigger.java @@ -0,0 +1,105 @@ +package vazkii.patchouli.common.advancement; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import net.minecraft.advancements.critereon.*; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; + +import vazkii.patchouli.api.PatchouliAPI; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PatchouliBookOpenTrigger extends SimpleCriterionTrigger { + public static final ResourceLocation ID = new ResourceLocation(PatchouliAPI.MOD_ID, "open_book"); + public static final PatchouliBookOpenTrigger INSTANCE = new PatchouliBookOpenTrigger(); + + private PatchouliBookOpenTrigger() {} + + @NotNull + @Override + public ResourceLocation getId() { + return ID; + } + + @NotNull + @Override + protected PatchouliBookOpenTrigger.Instance createInstance(@NotNull JsonObject json, @NotNull ContextAwarePredicate playerPred, @NotNull DeserializationContext conditions) { + JsonElement bookElement = json.get("book"); + ResourceLocation book = bookElement != null && bookElement.isJsonPrimitive() ? new ResourceLocation(bookElement.getAsString()) : null; + JsonElement entryElement = json.get("entry"); + ResourceLocation entry = entryElement != null && entryElement.isJsonPrimitive() ? new ResourceLocation(entryElement.getAsString()) : null; + JsonElement pageElement = json.get("page"); + int page = pageElement != null && pageElement.isJsonPrimitive() ? pageElement.getAsInt() : 0; + return new PatchouliBookOpenTrigger.Instance(playerPred, book, entry, page); + } + + public void trigger(@NotNull ServerPlayer player, @NotNull ResourceLocation book) { + trigger(player, instance -> instance.test(book, null, 0)); + } + + public void trigger(@NotNull ServerPlayer player, @NotNull ResourceLocation book, @Nullable ResourceLocation entry, int page) { + trigger(player, instance -> instance.test(book, entry, page)); + } + + public static class Instance extends AbstractCriterionTriggerInstance { + private final ResourceLocation book; + private final ResourceLocation entry; + private final int page; + + public Instance(@NotNull ContextAwarePredicate playerPred, @Nullable ResourceLocation book, @Nullable ResourceLocation entry, int page) { + super(ID, playerPred); + this.book = book; + this.entry = entry; + this.page = page; + } + + public Instance(@NotNull ContextAwarePredicate playerPred, @NotNull ResourceLocation book) { + this(playerPred, book, null, 0); + } + + @NotNull + @Override + public ResourceLocation getCriterion() { + return ID; + } + + @Nullable + public ResourceLocation getBook() { + return this.book; + } + + @Nullable + public ResourceLocation getEntry() { + return this.entry; + } + + public int getPage() { + return this.page; + } + + boolean test(ResourceLocation bookId, ResourceLocation entry, int page) { + return this.book != null && this.book.equals(bookId) + && (this.entry == null || this.entry.equals(entry)) + && (this.page > 0 && this.page == page); + } + + @NotNull + @Override + public JsonObject serializeToJson(@NotNull SerializationContext serializationContext) { + JsonObject json = super.serializeToJson(serializationContext); + if (book != null) { + json.addProperty("book", book.toString()); + } + if (entry != null) { + json.addProperty("entry", entry.toString()); + } + if (page != -1) { + json.addProperty("page", page); + } + return json; + } + } +} diff --git a/Xplat/src/main/java/vazkii/patchouli/common/advancement/PatchouliCriteriaTriggers.java b/Xplat/src/main/java/vazkii/patchouli/common/advancement/PatchouliCriteriaTriggers.java new file mode 100644 index 00000000..9f781c79 --- /dev/null +++ b/Xplat/src/main/java/vazkii/patchouli/common/advancement/PatchouliCriteriaTriggers.java @@ -0,0 +1,9 @@ +package vazkii.patchouli.common.advancement; + +import vazkii.patchouli.mixin.AccessorCriteriaTriggers; + +public class PatchouliCriteriaTriggers { + public static void init() { + AccessorCriteriaTriggers.patchouli$register(PatchouliBookOpenTrigger.INSTANCE); + } +} diff --git a/Xplat/src/main/java/vazkii/patchouli/common/base/PatchouliAPIImpl.java b/Xplat/src/main/java/vazkii/patchouli/common/base/PatchouliAPIImpl.java index e6b41701..49b745ae 100644 --- a/Xplat/src/main/java/vazkii/patchouli/common/base/PatchouliAPIImpl.java +++ b/Xplat/src/main/java/vazkii/patchouli/common/base/PatchouliAPIImpl.java @@ -28,6 +28,7 @@ import vazkii.patchouli.client.book.template.BookTemplate; import vazkii.patchouli.client.book.text.BookTextParser; import vazkii.patchouli.client.handler.MultiblockVisualizationHandler; +import vazkii.patchouli.common.advancement.PatchouliBookOpenTrigger; import vazkii.patchouli.common.book.Book; import vazkii.patchouli.common.book.BookRegistry; import vazkii.patchouli.common.item.ItemModBook; @@ -80,11 +81,13 @@ public boolean getConfigFlag(String flag) { @Override public void openBookGUI(ServerPlayer player, ResourceLocation book) { + PatchouliBookOpenTrigger.INSTANCE.trigger(player, book); IXplatAbstractions.INSTANCE.sendOpenBookGui(player, book, null, 0); } @Override public void openBookEntry(ServerPlayer player, ResourceLocation book, ResourceLocation entry, int page) { + PatchouliBookOpenTrigger.INSTANCE.trigger(player, book, entry, page); IXplatAbstractions.INSTANCE.sendOpenBookGui(player, book, entry, page); } diff --git a/Xplat/src/main/java/vazkii/patchouli/mixin/AccessorCriteriaTriggers.java b/Xplat/src/main/java/vazkii/patchouli/mixin/AccessorCriteriaTriggers.java new file mode 100644 index 00000000..e23e60f1 --- /dev/null +++ b/Xplat/src/main/java/vazkii/patchouli/mixin/AccessorCriteriaTriggers.java @@ -0,0 +1,15 @@ +package vazkii.patchouli.mixin; + +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.advancements.CriterionTrigger; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(CriteriaTriggers.class) +public interface AccessorCriteriaTriggers { + @Invoker("register") + static > T patchouli$register(T thing) { + throw new IllegalStateException(); + } +} diff --git a/Xplat/src/main/resources/patchouli_xplat.mixins.json b/Xplat/src/main/resources/patchouli_xplat.mixins.json index 4c8b5544..2c06c86b 100644 --- a/Xplat/src/main/resources/patchouli_xplat.mixins.json +++ b/Xplat/src/main/resources/patchouli_xplat.mixins.json @@ -4,6 +4,7 @@ "package": "vazkii.patchouli.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "AccessorCriteriaTriggers", "AccessorSmithingTransformRecipe", "AccessorSmithingTrimRecipe" ],