From 2b1c64495f533d1e577b101565fb2d682ef3687f Mon Sep 17 00:00:00 2001 From: Aurora Dawn <131844170+StellarWitch7@users.noreply.github.com> Date: Thu, 22 Aug 2024 17:19:13 -0400 Subject: [PATCH 1/8] Squishy --- .../resources/trickster.client.mixins.json | 4 ++-- .../27614340de28b382d5f7ae74366bcf39e2ac3aeb | 6 +++--- .../trickster/mixin/tooltip/ItemMixin.java | 19 ++++++++++++++++--- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/client/resources/trickster.client.mixins.json b/src/client/resources/trickster.client.mixins.json index 30cdcbf1..71fe8776 100644 --- a/src/client/resources/trickster.client.mixins.json +++ b/src/client/resources/trickster.client.mixins.json @@ -14,9 +14,9 @@ "SillyHairsFeatureRendererMixin", "WorldRendererAccessor", "accessories.AccessoriesScreenMixin", + "figura.AvatarManagerMixin", "sodium.WorldSliceMixin", - "tooltip.TooltipComponentMixin", - "figura.AvatarManagerMixin" + "tooltip.TooltipComponentMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/generated/.cache/27614340de28b382d5f7ae74366bcf39e2ac3aeb b/src/main/generated/.cache/27614340de28b382d5f7ae74366bcf39e2ac3aeb index 7b4a9a02..489144db 100644 --- a/src/main/generated/.cache/27614340de28b382d5f7ae74366bcf39e2ac3aeb +++ b/src/main/generated/.cache/27614340de28b382d5f7ae74366bcf39e2ac3aeb @@ -1,3 +1,3 @@ -// 1.21 2024-07-15T21:34:42.9793041 Trickster/Model Definitions -b9b893ec0a8cd31d7398651d871e15a392ea76b2 assets\trickster\models\item\spell_resonator.json -9d5d343103d621d1a2f492cec156c06274efdc15 assets\trickster\blockstates\spell_resonator.json +// 1.21 2024-08-22T17:14:21.48955409 Trickster/Model Definitions +b9b893ec0a8cd31d7398651d871e15a392ea76b2 assets/trickster/models/item/spell_resonator.json +9d5d343103d621d1a2f492cec156c06274efdc15 assets/trickster/blockstates/spell_resonator.json diff --git a/src/main/java/dev/enjarai/trickster/mixin/tooltip/ItemMixin.java b/src/main/java/dev/enjarai/trickster/mixin/tooltip/ItemMixin.java index a98daa39..e68cd2f0 100644 --- a/src/main/java/dev/enjarai/trickster/mixin/tooltip/ItemMixin.java +++ b/src/main/java/dev/enjarai/trickster/mixin/tooltip/ItemMixin.java @@ -1,24 +1,37 @@ package dev.enjarai.trickster.mixin.tooltip; - import dev.enjarai.trickster.SpellTooltipData; import dev.enjarai.trickster.item.component.ModComponents; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.tooltip.TooltipData; +import net.minecraft.item.tooltip.TooltipType; +import net.minecraft.text.Style; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.List; import java.util.Optional; - @Mixin(Item.class) public abstract class ItemMixin { + @Inject(method = "appendTooltip", at = @At("HEAD")) + private void addGarble(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type, CallbackInfo ci) { + var spellComponent = stack.get(ModComponents.SPELL); + + if (spellComponent != null && spellComponent.closed()) { + tooltip.add(Text.literal("Mortal eyes upon my carvings").setStyle(Style.EMPTY.withObfuscated(true))); + } + } + @Inject(method = "getTooltipData", at = @At("HEAD"), cancellable = true) - private void trickster$getSpellTooltipData(ItemStack stack, CallbackInfoReturnable> cir) { + private void trickster$getSpellTooltipData(ItemStack stack, CallbackInfoReturnable> cir) { var spellComponent = stack.get(ModComponents.SPELL); + if (spellComponent != null && !spellComponent.spell().isEmpty() && !spellComponent.closed()) { cir.setReturnValue(Optional.of(new SpellTooltipData(spellComponent.spell()))); } From 1dc4d6502a7ed1e9072c00caa9e1f6cc98a3e597 Mon Sep 17 00:00:00 2001 From: Aurora Dawn <131844170+StellarWitch7@users.noreply.github.com> Date: Thu, 22 Aug 2024 22:15:46 -0400 Subject: [PATCH 2/8] It has been foretold in the carvings of the ancients! --- .../dev/enjarai/trickster/item/ModItems.java | 1 + .../item/component/SpellComponent.java | 16 +++--- .../item/recipe/ScrollEnhancingRecipe.java | 4 +- .../mixin/AnvilScreenHandlerMixin.java | 55 +++++++++++++++++++ .../mixin/{tooltip => }/ItemMixin.java | 19 ++++++- .../trickster/net/SignScrollPacket.java | 4 +- .../screen/ScrollAndQuillScreenHandler.java | 5 +- .../spell/fragment/FragmentType.java | 1 + .../spell/fragment/StringFragment.java | 28 ++++++++++ .../spell/trick/basic/WriteSpellTrick.java | 45 +++++++++++---- .../trickster/tags/item/no_spell_glint.json | 7 +++ src/main/resources/trickster.mixins.json | 3 +- 12 files changed, 161 insertions(+), 27 deletions(-) create mode 100644 src/main/java/dev/enjarai/trickster/mixin/AnvilScreenHandlerMixin.java rename src/main/java/dev/enjarai/trickster/mixin/{tooltip => }/ItemMixin.java (62%) create mode 100644 src/main/java/dev/enjarai/trickster/spell/fragment/StringFragment.java create mode 100644 src/main/resources/data/trickster/tags/item/no_spell_glint.json diff --git a/src/main/java/dev/enjarai/trickster/item/ModItems.java b/src/main/java/dev/enjarai/trickster/item/ModItems.java index 66878298..59c2039c 100644 --- a/src/main/java/dev/enjarai/trickster/item/ModItems.java +++ b/src/main/java/dev/enjarai/trickster/item/ModItems.java @@ -63,6 +63,7 @@ public class ModItems { public static final TagKey SCROLLS = TagKey.of(RegistryKeys.ITEM, Trickster.id("scrolls")); // public static final TagKey IMMUTABLE_SPELL_HOLDERS = TagKey.of(RegistryKeys.ITEM, Trickster.id("immutable_spell_holders")); public static final TagKey SPELL_COST = TagKey.of(RegistryKeys.ITEM, Trickster.id("spell_cost")); + public static final TagKey NO_SPELL_GLINT = TagKey.of(RegistryKeys.ITEM, Trickster.id("no_spell_glint")); public static final TagKey CONJURABLE_FLOWERS = TagKey.of(RegistryKeys.BLOCK, Trickster.id("conjurable_flowers")); public static final ItemGroup ITEM_GROUP = FabricItemGroup.builder() diff --git a/src/main/java/dev/enjarai/trickster/item/component/SpellComponent.java b/src/main/java/dev/enjarai/trickster/item/component/SpellComponent.java index b3945ed7..d32321d3 100644 --- a/src/main/java/dev/enjarai/trickster/item/component/SpellComponent.java +++ b/src/main/java/dev/enjarai/trickster/item/component/SpellComponent.java @@ -9,6 +9,7 @@ import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.ContainerComponent; import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; import java.util.ArrayList; import java.util.Optional; @@ -16,23 +17,24 @@ import java.util.function.Function; import java.util.stream.Collectors; -public record SpellComponent(SpellPart spell, boolean immutable, boolean closed) { +public record SpellComponent(SpellPart spell, Optional name, boolean immutable, boolean closed) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( CodecUtils.toCodec(SpellPart.ENDEC).fieldOf("spell").forGetter(SpellComponent::spell), + Codec.STRING.optionalFieldOf("name").forGetter(SpellComponent::name), Codec.BOOL.optionalFieldOf("immutable", false).forGetter(SpellComponent::immutable), Codec.BOOL.optionalFieldOf("closed", false).forGetter(SpellComponent::closed) ).apply(instance, SpellComponent::new)); public SpellComponent(SpellPart spell) { - this(spell, false, false); + this(spell, Optional.empty(), false, false); } public SpellComponent(SpellPart spell, boolean immutable) { - this(spell, immutable, false); + this(spell, Optional.empty(), immutable, false); } - public SpellComponent withClosed() { - return new SpellComponent(spell, immutable, true); + public SpellComponent withClosed(Optional name) { + return new SpellComponent(spell, name, immutable, true); } public static Optional getSpellPart(ItemStack stack) { @@ -43,13 +45,13 @@ public static Optional getSpellPart(ItemStack stack) { .map(SpellComponent::spell); } - public static boolean setSpellPart(ItemStack stack, SpellPart spell, boolean closed) { + public static boolean setSpellPart(ItemStack stack, SpellPart spell, Optional name, boolean closed) { return modifyReferencedStack(stack, stack2 -> { if (stack2.contains(ModComponents.SPELL) && stack2.get(ModComponents.SPELL).immutable()) { return false; } - stack2.set(ModComponents.SPELL, new SpellComponent(spell, false, closed)); + stack2.set(ModComponents.SPELL, new SpellComponent(spell, name, false, closed)); return true; }); } diff --git a/src/main/java/dev/enjarai/trickster/item/recipe/ScrollEnhancingRecipe.java b/src/main/java/dev/enjarai/trickster/item/recipe/ScrollEnhancingRecipe.java index 57d0725a..35507132 100644 --- a/src/main/java/dev/enjarai/trickster/item/recipe/ScrollEnhancingRecipe.java +++ b/src/main/java/dev/enjarai/trickster/item/recipe/ScrollEnhancingRecipe.java @@ -13,6 +13,8 @@ import net.minecraft.util.collection.DefaultedList; import net.minecraft.world.World; +import java.util.Optional; + public class ScrollEnhancingRecipe extends SpecialCraftingRecipe { public ScrollEnhancingRecipe(CraftingRecipeCategory craftingRecipeCategory) { super(craftingRecipeCategory); @@ -71,7 +73,7 @@ public ItemStack craft(CraftingRecipeInput craftingRecipeInput, RegistryWrapper. var spell = itemStack.get(ModComponents.SPELL); if (!itemStack.isEmpty() && i > 0 && meta != null && spell != null) { var newMeta = meta.withExecutable(i * 100); - var newSpell = spell.withClosed(); + var newSpell = spell.withClosed(Optional.empty()); ItemStack itemStack3 = itemStack.copyWithCount(1); itemStack3.set(ModComponents.WRITTEN_SCROLL_META, newMeta); itemStack3.set(ModComponents.SPELL, newSpell); diff --git a/src/main/java/dev/enjarai/trickster/mixin/AnvilScreenHandlerMixin.java b/src/main/java/dev/enjarai/trickster/mixin/AnvilScreenHandlerMixin.java new file mode 100644 index 00000000..99db93e5 --- /dev/null +++ b/src/main/java/dev/enjarai/trickster/mixin/AnvilScreenHandlerMixin.java @@ -0,0 +1,55 @@ +package dev.enjarai.trickster.mixin; + +import dev.enjarai.trickster.item.component.ModComponents; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.screen.*; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(AnvilScreenHandler.class) +public abstract class AnvilScreenHandlerMixin extends ForgingScreenHandler { + @Shadow + @Final + private Property levelCost; + + public AnvilScreenHandlerMixin(@Nullable ScreenHandlerType type, int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) { + super(type, syncId, playerInventory, context); + } + + @Inject(method = "updateResult", at = @At("RETURN")) + private void ensureValidity(CallbackInfo ci) { + var left = this.input.getStack(0); + var middle = this.input.getStack(1); + var spellComponent = middle.get(ModComponents.SPELL); + + if (!left.isEmpty() && middle.isOf(Items.ENCHANTED_BOOK) && spellComponent != null && this.levelCost.get() <= 0) { + var newStack = left.copy(); + newStack.set(ModComponents.SPELL, spellComponent); + this.output.setStack(0, newStack); + this.levelCost.set(1); + } + } + + @ModifyArg( + method = "updateResult", + at = @At(value = "INVOKE", target = "Lnet/minecraft/inventory/CraftingResultInventory;setStack(ILnet/minecraft/item/ItemStack;)V"), + index = 1 + ) + private ItemStack applySpell(ItemStack stack) { + var spellComponent = this.input.getStack(1).get(ModComponents.SPELL); + + if (spellComponent != null) { + stack.set(ModComponents.SPELL, spellComponent); + } + + return stack; + } +} diff --git a/src/main/java/dev/enjarai/trickster/mixin/tooltip/ItemMixin.java b/src/main/java/dev/enjarai/trickster/mixin/ItemMixin.java similarity index 62% rename from src/main/java/dev/enjarai/trickster/mixin/tooltip/ItemMixin.java rename to src/main/java/dev/enjarai/trickster/mixin/ItemMixin.java index e68cd2f0..eb2f79cb 100644 --- a/src/main/java/dev/enjarai/trickster/mixin/tooltip/ItemMixin.java +++ b/src/main/java/dev/enjarai/trickster/mixin/ItemMixin.java @@ -1,7 +1,10 @@ -package dev.enjarai.trickster.mixin.tooltip; +package dev.enjarai.trickster.mixin; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import dev.enjarai.trickster.SpellTooltipData; +import dev.enjarai.trickster.item.ModItems; import dev.enjarai.trickster.item.component.ModComponents; +import dev.enjarai.trickster.item.component.SpellComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.tooltip.TooltipData; @@ -19,12 +22,22 @@ @Mixin(Item.class) public abstract class ItemMixin { + @ModifyReturnValue(method = "hasGlint", at = @At("RETURN")) + private boolean thing(boolean original, ItemStack stack) { + return original + || (stack.get(ModComponents.SPELL) instanceof SpellComponent spellComponent) + && !spellComponent.spell().isEmpty() + && !stack.isIn(ModItems.NO_SPELL_GLINT); + } + @Inject(method = "appendTooltip", at = @At("HEAD")) private void addGarble(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type, CallbackInfo ci) { var spellComponent = stack.get(ModComponents.SPELL); - if (spellComponent != null && spellComponent.closed()) { - tooltip.add(Text.literal("Mortal eyes upon my carvings").setStyle(Style.EMPTY.withObfuscated(true))); + if (spellComponent != null && !spellComponent.spell().isEmpty() && spellComponent.closed()) { + tooltip.add(spellComponent.name() + .flatMap(str -> Optional.of(Text.literal(str))) + .orElse(Text.literal("Mortal eyes upon my carvings").setStyle(Style.EMPTY.withObfuscated(true)))); } } diff --git a/src/main/java/dev/enjarai/trickster/net/SignScrollPacket.java b/src/main/java/dev/enjarai/trickster/net/SignScrollPacket.java index d5f332a3..6cb75604 100644 --- a/src/main/java/dev/enjarai/trickster/net/SignScrollPacket.java +++ b/src/main/java/dev/enjarai/trickster/net/SignScrollPacket.java @@ -7,6 +7,8 @@ import io.wispforest.owo.network.ServerAccess; import net.minecraft.util.Hand; +import java.util.Optional; + public record SignScrollPacket(Hand hand, String name) { public void handleServer(ServerAccess access) { var player = access.player(); @@ -20,7 +22,7 @@ public void handleServer(ServerAccess access) { var newStack = ModItems.WRITTEN_SCROLL.getDefaultStack(); - newStack.set(ModComponents.SPELL, new SpellComponent(component.spell(), true, component.closed())); + newStack.set(ModComponents.SPELL, new SpellComponent(component.spell(), Optional.empty(), true, component.closed())); newStack.set(ModComponents.WRITTEN_SCROLL_META, new WrittenScrollMetaComponent( name(), player.getName().getString(), 0 )); diff --git a/src/main/java/dev/enjarai/trickster/screen/ScrollAndQuillScreenHandler.java b/src/main/java/dev/enjarai/trickster/screen/ScrollAndQuillScreenHandler.java index ba667ca5..83eaa214 100644 --- a/src/main/java/dev/enjarai/trickster/screen/ScrollAndQuillScreenHandler.java +++ b/src/main/java/dev/enjarai/trickster/screen/ScrollAndQuillScreenHandler.java @@ -27,6 +27,7 @@ import net.minecraft.text.Text; import java.util.List; +import java.util.Optional; import java.util.function.Consumer; public class ScrollAndQuillScreenHandler extends ScreenHandler implements RevisionContext { @@ -103,7 +104,7 @@ public void updateSpell(SpellPart spell) { spell.brutallyMurderEphemerals(); } - SpellComponent.setSpellPart(scrollStack, spell, false); + SpellComponent.setSpellPart(scrollStack, spell, Optional.empty(), false); }); } } else { @@ -121,7 +122,7 @@ public void updateOtherHandSpell(SpellPart spell) { var server = player().getServer(); if (server != null) { server.execute(() -> { - SpellComponent.setSpellPart(otherHandStack, spell, false); + SpellComponent.setSpellPart(otherHandStack, spell, Optional.empty(), false); otherHandSpell.set(spell); }); } diff --git a/src/main/java/dev/enjarai/trickster/spell/fragment/FragmentType.java b/src/main/java/dev/enjarai/trickster/spell/fragment/FragmentType.java index a5c26da1..d7b3a022 100644 --- a/src/main/java/dev/enjarai/trickster/spell/fragment/FragmentType.java +++ b/src/main/java/dev/enjarai/trickster/spell/fragment/FragmentType.java @@ -54,6 +54,7 @@ public RegistryEntry.Reference> add(RegistryKey> public static final FragmentType BLOCK_TYPE = register("block_type", BlockTypeFragment.ENDEC, 0x44aa33); public static final FragmentType ENTITY_TYPE = register("entity_type", EntityTypeFragment.ENDEC, 0x8877bb); public static final FragmentType DIMENSION = register("dimension", DimensionFragment.ENDEC, 0xdd55bb); + public static final FragmentType STRING = register("string", StringFragment.ENDEC /*TODO: color*/); private static FragmentType register(String name, StructEndec codec, int color) { return Registry.register(REGISTRY, Trickster.id(name), new FragmentType<>(codec, OptionalInt.of(color))); diff --git a/src/main/java/dev/enjarai/trickster/spell/fragment/StringFragment.java b/src/main/java/dev/enjarai/trickster/spell/fragment/StringFragment.java new file mode 100644 index 00000000..9410ffe1 --- /dev/null +++ b/src/main/java/dev/enjarai/trickster/spell/fragment/StringFragment.java @@ -0,0 +1,28 @@ +package dev.enjarai.trickster.spell.fragment; + +import dev.enjarai.trickster.spell.Fragment; +import io.wispforest.endec.StructEndec; +import io.wispforest.endec.impl.StructEndecBuilder; +import net.minecraft.text.Text; + +public record StringFragment(String value) implements Fragment { + public static final StructEndec ENDEC = StructEndecBuilder.of( + StructEndec.STRING.fieldOf("value", StringFragment::value), + StringFragment::new + ); + + @Override + public FragmentType type() { + return FragmentType.STRING; + } + + @Override + public Text asText() { + return Text.literal("\"").append(value).append("\""); + } + + @Override + public BooleanFragment asBoolean() { + return new BooleanFragment(!value.isEmpty()); + } +} diff --git a/src/main/java/dev/enjarai/trickster/spell/trick/basic/WriteSpellTrick.java b/src/main/java/dev/enjarai/trickster/spell/trick/basic/WriteSpellTrick.java index b6fc635b..57e4d69a 100644 --- a/src/main/java/dev/enjarai/trickster/spell/trick/basic/WriteSpellTrick.java +++ b/src/main/java/dev/enjarai/trickster/spell/trick/basic/WriteSpellTrick.java @@ -1,5 +1,6 @@ package dev.enjarai.trickster.spell.trick.basic; +import com.ibm.icu.impl.Pair; import dev.enjarai.trickster.item.component.ModComponents; import dev.enjarai.trickster.item.component.SpellComponent; import dev.enjarai.trickster.spell.Fragment; @@ -10,6 +11,10 @@ import dev.enjarai.trickster.spell.trick.Trick; import dev.enjarai.trickster.spell.trick.blunder.BlunderException; import dev.enjarai.trickster.spell.trick.blunder.ImmutableItemBlunder; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.ItemEnchantmentsComponent; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.Items; import java.util.List; import java.util.Optional; @@ -25,25 +30,41 @@ public Fragment activate(SpellContext ctx, List fragments) throws Blun } public Fragment activate(SpellContext ctx, List fragments, boolean closed) throws BlunderException { - var spell = supposeInput(fragments, 0).flatMap(s -> supposeType(s, FragmentType.SPELL_PART)); var player = ctx.source().getPlayer(); + var spell = supposeInput(fragments, 0).flatMap(s -> supposeType(s, FragmentType.SPELL_PART)).map(s -> { + var n = s.deepClone(); + n.brutallyMurderEphemerals(); + return n; + }); - return player.flatMap(serverPlayerEntity -> Optional.of(serverPlayerEntity.getOffHandStack())).map(stack -> { - var newSpell = spell.map(s -> { - var n = s.deepClone(); - n.brutallyMurderEphemerals(); - return n; - }); + return player.map(serverPlayerEntity -> Pair.of(serverPlayerEntity, serverPlayerEntity.getOffHandStack())).map(pair -> { + var serverPlayer = pair.first; + var stack = pair.second; + + spell.ifPresentOrElse(s -> { + var stack2 = stack; + + if (stack2.isOf(Items.BOOK)) { + serverPlayer.equipStack(EquipmentSlot.OFFHAND, stack2.withItem(Items.ENCHANTED_BOOK)); + stack2 = serverPlayer.getOffHandStack(); + } - newSpell.ifPresentOrElse(s -> { - if (!SpellComponent.setSpellPart(stack, s, closed)) { + if (!SpellComponent.setSpellPart(stack2, s, supposeInput(fragments, FragmentType.STRING, 1).flatMap(str -> Optional.of(str.value())), closed)) { throw new ImmutableItemBlunder(this); } }, () -> { - if (!SpellComponent.modifyReferencedStack(stack, s -> { - if (s.get(ModComponents.SPELL).immutable()) { + var stack2 = stack; + + if (stack2.isOf(Items.ENCHANTED_BOOK) && (stack.get(DataComponentTypes.STORED_ENCHANTMENTS) instanceof ItemEnchantmentsComponent enchants) && enchants.isEmpty()) { + serverPlayer.equipStack(EquipmentSlot.OFFHAND, stack2.withItem(Items.BOOK)); + stack2 = serverPlayer.getOffHandStack(); + } + + if (!SpellComponent.modifyReferencedStack(stack2, s -> { + var spellComponent = s.get(ModComponents.SPELL); + + if (spellComponent == null || spellComponent.immutable()) return false; - } s.remove(ModComponents.SPELL); return true; diff --git a/src/main/resources/data/trickster/tags/item/no_spell_glint.json b/src/main/resources/data/trickster/tags/item/no_spell_glint.json new file mode 100644 index 00000000..46c6fb99 --- /dev/null +++ b/src/main/resources/data/trickster/tags/item/no_spell_glint.json @@ -0,0 +1,7 @@ +{ + "values": [ + "trickster:mirror_of_evaluation", + "trickster:scroll_and_quill", + "trickster:written_scroll" + ] +} \ No newline at end of file diff --git a/src/main/resources/trickster.mixins.json b/src/main/resources/trickster.mixins.json index 689eda75..d9963a89 100644 --- a/src/main/resources/trickster.mixins.json +++ b/src/main/resources/trickster.mixins.json @@ -5,6 +5,7 @@ "plugin": "dev.enjarai.trickster.ConditionalMixins", "mixins": [ "AbstractBlockStateMixin", + "AnvilScreenHandlerMixin", "EntityMixin", "LivingEntityMixin", "WorldChunkMixin", @@ -14,7 +15,7 @@ "event.EntityMixin", "event.ItemStackMixin", "event.ServerPlayerInteractionManagerMixin", - "tooltip.ItemMixin" + "ItemMixin" ], "injectors": { "defaultRequire": 1 From 7be19527eac55bdd453669528fc68384b30371b2 Mon Sep 17 00:00:00 2001 From: enjarai Date: Fri, 23 Aug 2024 11:47:39 +0200 Subject: [PATCH 3/8] Polish the funny capitalism a bit --- .../mixin/AnvilScreenHandlerMixin.java | 24 +++++++++---------- .../trickster/net/SignScrollPacket.java | 2 +- .../spell/fragment/FragmentType.java | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/dev/enjarai/trickster/mixin/AnvilScreenHandlerMixin.java b/src/main/java/dev/enjarai/trickster/mixin/AnvilScreenHandlerMixin.java index 99db93e5..162d080a 100644 --- a/src/main/java/dev/enjarai/trickster/mixin/AnvilScreenHandlerMixin.java +++ b/src/main/java/dev/enjarai/trickster/mixin/AnvilScreenHandlerMixin.java @@ -1,5 +1,8 @@ package dev.enjarai.trickster.mixin; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef; +import com.llamalad7.mixinextras.sugar.ref.LocalIntRef; import dev.enjarai.trickster.item.component.ModComponents; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; @@ -12,29 +15,26 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(AnvilScreenHandler.class) public abstract class AnvilScreenHandlerMixin extends ForgingScreenHandler { - @Shadow - @Final - private Property levelCost; - public AnvilScreenHandlerMixin(@Nullable ScreenHandlerType type, int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) { super(type, syncId, playerInventory, context); } - @Inject(method = "updateResult", at = @At("RETURN")) - private void ensureValidity(CallbackInfo ci) { + @Inject( + method = "updateResult", + at = @At(value = "INVOKE", target = "Lnet/minecraft/component/type/ItemEnchantmentsComponent;getEnchantmentEntries()Ljava/util/Set;") + ) + private void enableSpellTransfer(CallbackInfo ci, @Local(ordinal = 0) LocalIntRef i, @Local(ordinal = 1) LocalBooleanRef bl2) { var left = this.input.getStack(0); var middle = this.input.getStack(1); - var spellComponent = middle.get(ModComponents.SPELL); - if (!left.isEmpty() && middle.isOf(Items.ENCHANTED_BOOK) && spellComponent != null && this.levelCost.get() <= 0) { - var newStack = left.copy(); - newStack.set(ModComponents.SPELL, spellComponent); - this.output.setStack(0, newStack); - this.levelCost.set(1); + if (middle.contains(ModComponents.SPELL) && left.getCount() <= 1 && !left.isOf(Items.BOOK)) { + i.set(i.get() + 1); + bl2.set(true); } } diff --git a/src/main/java/dev/enjarai/trickster/net/SignScrollPacket.java b/src/main/java/dev/enjarai/trickster/net/SignScrollPacket.java index 6cb75604..b556a01d 100644 --- a/src/main/java/dev/enjarai/trickster/net/SignScrollPacket.java +++ b/src/main/java/dev/enjarai/trickster/net/SignScrollPacket.java @@ -22,7 +22,7 @@ public void handleServer(ServerAccess access) { var newStack = ModItems.WRITTEN_SCROLL.getDefaultStack(); - newStack.set(ModComponents.SPELL, new SpellComponent(component.spell(), Optional.empty(), true, component.closed())); + newStack.set(ModComponents.SPELL, new SpellComponent(component.spell(), component.name(), true, component.closed())); newStack.set(ModComponents.WRITTEN_SCROLL_META, new WrittenScrollMetaComponent( name(), player.getName().getString(), 0 )); diff --git a/src/main/java/dev/enjarai/trickster/spell/fragment/FragmentType.java b/src/main/java/dev/enjarai/trickster/spell/fragment/FragmentType.java index d7b3a022..fa72170f 100644 --- a/src/main/java/dev/enjarai/trickster/spell/fragment/FragmentType.java +++ b/src/main/java/dev/enjarai/trickster/spell/fragment/FragmentType.java @@ -54,7 +54,7 @@ public RegistryEntry.Reference> add(RegistryKey> public static final FragmentType BLOCK_TYPE = register("block_type", BlockTypeFragment.ENDEC, 0x44aa33); public static final FragmentType ENTITY_TYPE = register("entity_type", EntityTypeFragment.ENDEC, 0x8877bb); public static final FragmentType DIMENSION = register("dimension", DimensionFragment.ENDEC, 0xdd55bb); - public static final FragmentType STRING = register("string", StringFragment.ENDEC /*TODO: color*/); + public static final FragmentType STRING = register("string", StringFragment.ENDEC, 0xaabb77); private static FragmentType register(String name, StructEndec codec, int color) { return Registry.register(REGISTRY, Trickster.id(name), new FragmentType<>(codec, OptionalInt.of(color))); From d2e83aa1298416a8a7e01a06ef0f5b0ae452e461 Mon Sep 17 00:00:00 2001 From: enjarai Date: Fri, 23 Aug 2024 16:05:16 +0200 Subject: [PATCH 4/8] Second tutoal --- .../screen/owo/SpellPreviewComponent.java | 7 +- .../entries/tome_of_tomfoolery/editing.md | 51 +-------- .../tutorials/2_first_spell.md | 105 ++++++++++++++++++ .../assets/trickster/owo_ui/templates.xml | 36 +++--- 4 files changed, 133 insertions(+), 66 deletions(-) diff --git a/src/client/java/dev/enjarai/trickster/screen/owo/SpellPreviewComponent.java b/src/client/java/dev/enjarai/trickster/screen/owo/SpellPreviewComponent.java index b0f21992..45578ba3 100644 --- a/src/client/java/dev/enjarai/trickster/screen/owo/SpellPreviewComponent.java +++ b/src/client/java/dev/enjarai/trickster/screen/owo/SpellPreviewComponent.java @@ -64,7 +64,12 @@ public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partial @Override public void mount(ParentComponent parent, int x, int y) { super.mount(parent, x, y); - parent.childById(ButtonComponent.class, "load-button").onPress(this::loadSpellToGame); + + + var loadButton = parent.childById(ButtonComponent.class, "load-button"); + if (loadButton != null) { + loadButton.onPress(this::loadSpellToGame); + } } public void loadSpellToGame(ButtonComponent button) { diff --git a/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/editing.md b/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/editing.md index b5c70d2d..0fecf1ad 100644 --- a/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/editing.md +++ b/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/editing.md @@ -6,22 +6,6 @@ } ``` -Right-clicking a [Scroll and Quill](^trickster:basics/scroll_and_quill) will open the spell-scribing interface. -Spells consist of a tree-like structure of intersecting circles, and each circle contains a center glyph to denote its function. - - -When first opening a new scroll, you will see just one circle. This is the **root node**. -Every other circle in your spell originates from it. - -;;;;; - -To begin writing a spell, so-called scribing patterns or revisions can be used add, remove, and move around circles. - - -The following page contains the most basic revision, with all others coming later in this chapter. - -;;;;; - <|pattern@trickster:templates|pattern=0\,4\,8\,7,title=Extensive Revision|> {gray}(Scribing pattern){} @@ -29,7 +13,6 @@ The following page contains the most basic revision, with all others coming late --- Can be used to add a new subcircle to any circle. -Being a Scribing pattern, this pattern acts instantly when drawn. ;;;;; @@ -39,38 +22,6 @@ When Extensive Revision is drawn in the blue circle, the green circle will be cr ;;;;; -Most patterns will not activate instantly like this. -Instead, they will stay in their circle and, -when the spell is cast, take their inputs from connected subcircles, perform an operation, and/or output to a parent circle. - - -Think of a spell like a tree with many splitting branches. -First, the leaves of the tree (the most deeply nested circles) create or read values from the world. -These can be constants or, for example, your position. - -;;;;; - -At each point where the branches of the tree split sits a Glyph (Usually a pattern). -This glyph can then read the values coming in from its child branches, and perform an operation on them, outputting a new value to its parent. - - -Some glyphs may not return a value, these are often called [Ploys](^trickster:ploys). -These glyphs will have an effect in the world, which is usually the end goal of the entire spell. - -;;;;; - -The final ploy of a spell may be its root node (the trunk of the tree), but it doesn't have to be. -This is because while empty circles perform no operation on their inputs, they still ensure all their children get evaluated. - - -As such, a spell with multiple effects may use an empty root node to evaluate multiple trees of logic. - -;;;;; - -The following pages will list some potentially useful scribing patterns. - -;;;;; - <|pattern@trickster:templates|pattern=0\,4\,8\,5,title=Inner Revision|> {gray}(Scribing pattern){} @@ -89,7 +40,7 @@ When Inner Revision is drawn in the outer blue circle, the green circle will be ;;;;; -As explained briefly on the last page, an inner circle acts like a glyph, +An inner circle acts like a glyph, either returning its value, or being executed with arguments. diff --git a/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/tutorials/2_first_spell.md b/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/tutorials/2_first_spell.md index 211e9470..f352e013 100644 --- a/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/tutorials/2_first_spell.md +++ b/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/tutorials/2_first_spell.md @@ -7,4 +7,109 @@ } ``` +Now that you've got a [Scroll](^trickster:basics/scroll_and_quill) you can right-click it to open the spell-scribing interface. +Spells consist of a tree-like structure of intersecting circles, and each circle contains a center glyph to denote its function. +;;;;; + +When first opening a new scroll, you will see just one circle. This is the **root node**. +Every other circle in your spell originates from it. + + +To begin writing a spell, so-called scribing patterns or revisions can be used to add, remove, and move around circles. +The most basic scribing pattern is [Extensive Revision](^trickster:editing#1), +which adds one extra subcircle to the circle it's drawn in. + +;;;;; + +Unlike most patterns, revisions activate instantly when drawn at any point in either a scroll or mirror. +They are the only way to directly affect the shape of your spell. + + +Another scribing pattern that may be useful for basic spells is [Grafting Revision](^trickster:editing#12), +which removes excess circles from the hierarchy. + + +With that out of the way, try to recreate the following spell in your scroll: + +;;;;; + +<|spell-preview-unloadable@trickster:templates|spell=YwyT9+YP6GBjZQQxGFwOMIAZHCEMDAwA8vUGkRwAAAA=|> + +{gray}(Drag to pan and scroll to zoom){} + +;;;;; + +Once that's done, hold the scroll in your offhand, and draw the following spell in your mirror: + +<|spell-preview-unloadable@trickster:templates|spell=YwyT9+bf6MPEyghiMLo0tTIAADybrxgTAAAA|> + +;;;;; + +You may notice that, while drawing, the top pattern gets replaced with the spell from your scroll. + + +Afterward, if you did everything correctly, the spell should have targeted and broken the block you were looking at! +This is the most basic way of spellcasting, write the spell in a scroll, and cast it using your mirror. + + +**But why did this work?** + +;;;;; + +When a spell is cast, drawn glyphs will take the output from connected subcircles as input, +perform an operation, and output to their parent circle. + + +Think of a spell like a tree with many splitting branches. +First, the leaves of the tree (the most deeply nested circles) create or read values from the world. +These can be constants or, for example, a reference to the caster. +These are called [Delusions](^trickster:delusions_ingresses). + +;;;;; + +After this, intermediate glyphs process the information into an appropriate format, +for example taking a reference to a creature, and returning its position. +These are either [Distortions](^trickster:distortions) or [Ingresses](^trickster:delusions_ingresses). + + +Some glyphs may not return a value, often called [Ploys](^trickster:ploys). +These glyphs will affect the world, which is usually the end goal of the entire spell. + +;;;;; + +With this information in mind, we can take a look back at the spell in our scroll, +and recognise three types of glyphs (also known as tricks). + + +The most deeply nested glyph must be a Delusion, as it takes no inputs. +Meanwhile, the glyph in the root node has to be a Ploy, since it only takes inputs, and provides no output. +Which means the intermediate circle must contain either a Distortion or an Ingress. + +;;;;; + +If you were to look up these patterns in the [Tricks](^trickster:tricks) section of this book, +you'd see this assessment is correct. From smallest to largest circle, this spell is made up of: + +- [Reflection Delusion](^trickster:delusions_ingresses/caster_tricks#4) +- [Archer's Ingress](^trickster:delusions_ingresses/raycast#2) +- and [Ploy of Destruction](^trickster:ploys/block#2) + +Take a look at the inputs and outputs listed for these tricks, and try to understand how this spell combines them! + +;;;;; + +**Okay, but how did we cast it?** + + +Well, we took advantage of the mirror's tendency to cast anything it touches. +The patterns we drew in the mirror are [Notulist's Delusion](^trickster:tricks/basic#3) and [Grand Stratagem](^trickster:distortions/functions#3). +The former returns any spell held in the caster's offhand as data, while the latter takes a spell as data and casts it. + + +Yes, spells can cast other spells. + +;;;;; + +This chapter covered the basic concepts you need to know to start making simple spells of your own. +Go experiment, and see what's possible! diff --git a/src/main/resources/assets/trickster/owo_ui/templates.xml b/src/main/resources/assets/trickster/owo_ui/templates.xml index 6254e50f..29cc1e34 100644 --- a/src/main/resources/assets/trickster/owo_ui/templates.xml +++ b/src/main/resources/assets/trickster/owo_ui/templates.xml @@ -78,21 +78,6 @@ + \ No newline at end of file From c15598144d9bffa416c674422d8cb5cd91bddfca Mon Sep 17 00:00:00 2001 From: Aurora Dawn <131844170+StellarWitch7@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:31:37 -0400 Subject: [PATCH 5/8] Getting somewhere --- .../java/dev/enjarai/trickster/Trickster.java | 11 +++++ .../trickster/cca/CasterComponent.java | 3 +- .../trickster/item/WrittenScrollItem.java | 3 +- .../enjarai/trickster/mixin/ItemMixin.java | 20 ++++++--- .../trickster/mixin/LivingEntityMixin.java | 23 +++++++++- .../trickster/mixin/event/EntityMixin.java | 25 ----------- .../trickster/mixin/event/ItemStackMixin.java | 22 --------- .../mixin/event/ServerPlayerEntityMixin.java | 32 +++++++++++++ .../ServerPlayerInteractionManagerMixin.java | 9 +--- .../trickster/spell/ItemTriggerHelper.java | 45 +++++++++++++++++++ .../trickster/spell/ItemTriggerProvider.java | 44 ------------------ .../execution/SpellExecutionManager.java | 4 +- src/main/resources/trickster.mixins.json | 7 ++- 13 files changed, 134 insertions(+), 114 deletions(-) delete mode 100644 src/main/java/dev/enjarai/trickster/mixin/event/EntityMixin.java delete mode 100644 src/main/java/dev/enjarai/trickster/mixin/event/ItemStackMixin.java create mode 100644 src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerEntityMixin.java create mode 100644 src/main/java/dev/enjarai/trickster/spell/ItemTriggerHelper.java delete mode 100644 src/main/java/dev/enjarai/trickster/spell/ItemTriggerProvider.java diff --git a/src/main/java/dev/enjarai/trickster/Trickster.java b/src/main/java/dev/enjarai/trickster/Trickster.java index ee4329ce..a3b98f21 100644 --- a/src/main/java/dev/enjarai/trickster/Trickster.java +++ b/src/main/java/dev/enjarai/trickster/Trickster.java @@ -13,11 +13,15 @@ import dev.enjarai.trickster.net.ModNetworking; import dev.enjarai.trickster.particle.ModParticles; import dev.enjarai.trickster.screen.ModScreenHandlers; +import dev.enjarai.trickster.spell.ItemTriggerHelper; +import dev.enjarai.trickster.spell.fragment.VectorFragment; import dev.enjarai.trickster.spell.trick.Tricks; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; import net.minecraft.entity.attribute.EntityAttributeModifier; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import nl.enjarai.cicada.api.util.ProperLogger; import org.slf4j.Logger; @@ -54,6 +58,13 @@ public void onInitialize() { Tricks.register(); ModCriteria.register(); + PlayerBlockBreakEvents.BEFORE.register((world, player, pos, state, blockEntity) -> { + if (player instanceof ServerPlayerEntity serverPlayer) + ItemTriggerHelper.triggerMainHand(serverPlayer, VectorFragment.of(pos)); + + return true; + }); + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { TricksterCommand.register(dispatcher); }); diff --git a/src/main/java/dev/enjarai/trickster/cca/CasterComponent.java b/src/main/java/dev/enjarai/trickster/cca/CasterComponent.java index deb37908..04debd7f 100644 --- a/src/main/java/dev/enjarai/trickster/cca/CasterComponent.java +++ b/src/main/java/dev/enjarai/trickster/cca/CasterComponent.java @@ -25,6 +25,7 @@ import org.ladysnake.cca.api.v3.component.sync.AutoSyncedComponent; import org.ladysnake.cca.api.v3.component.tick.ServerTickingComponent; +import javax.swing.text.html.Option; import java.util.List; import java.util.Map; import java.util.Objects; @@ -135,7 +136,7 @@ public boolean queueSpell(SpellPart spell, List arguments) { return executionManager.queue(spell, arguments); } - public SpellQueueResult queueSpellAndCast(SpellPart spell, List arguments, ManaPool poolOverride) { + public SpellQueueResult queueSpellAndCast(SpellPart spell, List arguments, Optional poolOverride) { playCastSound(0.8f, 0.1f); return executionManager.queueAndCast(spell, arguments, poolOverride); } diff --git a/src/main/java/dev/enjarai/trickster/item/WrittenScrollItem.java b/src/main/java/dev/enjarai/trickster/item/WrittenScrollItem.java index 9af5c763..d3d3eca5 100644 --- a/src/main/java/dev/enjarai/trickster/item/WrittenScrollItem.java +++ b/src/main/java/dev/enjarai/trickster/item/WrittenScrollItem.java @@ -21,6 +21,7 @@ import net.minecraft.world.World; import java.util.List; +import java.util.Optional; public class WrittenScrollItem extends Item { public WrittenScrollItem(Settings settings) { @@ -38,7 +39,7 @@ public TypedActionResult use(World world, PlayerEntity user, Hand han if (!world.isClient()) { var spell = stack.get(ModComponents.SPELL); if (spell != null) { - var result = ModEntityCumponents.CASTER.get(user).queueSpellAndCast(spell.spell(), List.of(), SimpleManaPool.getSingleUse(meta.mana())); + var result = ModEntityCumponents.CASTER.get(user).queueSpellAndCast(spell.spell(), List.of(), Optional.of(SimpleManaPool.getSingleUse(meta.mana()))); if (result.type() != SpellQueueResult.Type.NOT_QUEUED && result.state().hasUsedMana()) stack.decrement(1); diff --git a/src/main/java/dev/enjarai/trickster/mixin/ItemMixin.java b/src/main/java/dev/enjarai/trickster/mixin/ItemMixin.java index eb2f79cb..b88dc73b 100644 --- a/src/main/java/dev/enjarai/trickster/mixin/ItemMixin.java +++ b/src/main/java/dev/enjarai/trickster/mixin/ItemMixin.java @@ -22,26 +22,36 @@ @Mixin(Item.class) public abstract class ItemMixin { - @ModifyReturnValue(method = "hasGlint", at = @At("RETURN")) - private boolean thing(boolean original, ItemStack stack) { + @ModifyReturnValue( + method = "hasGlint", + at = @At("RETURN") + ) + private boolean spellGlint(boolean original, ItemStack stack) { return original || (stack.get(ModComponents.SPELL) instanceof SpellComponent spellComponent) && !spellComponent.spell().isEmpty() && !stack.isIn(ModItems.NO_SPELL_GLINT); } - @Inject(method = "appendTooltip", at = @At("HEAD")) + @Inject( + method = "appendTooltip", + at = @At("HEAD") + ) private void addGarble(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type, CallbackInfo ci) { var spellComponent = stack.get(ModComponents.SPELL); - if (spellComponent != null && !spellComponent.spell().isEmpty() && spellComponent.closed()) { + if (spellComponent != null && /*!spellComponent.spell().isEmpty() &&*/ spellComponent.closed()) { tooltip.add(spellComponent.name() .flatMap(str -> Optional.of(Text.literal(str))) .orElse(Text.literal("Mortal eyes upon my carvings").setStyle(Style.EMPTY.withObfuscated(true)))); } } - @Inject(method = "getTooltipData", at = @At("HEAD"), cancellable = true) + @Inject( + method = "getTooltipData", + at = @At("HEAD"), + cancellable = true + ) private void trickster$getSpellTooltipData(ItemStack stack, CallbackInfoReturnable> cir) { var spellComponent = stack.get(ModComponents.SPELL); diff --git a/src/main/java/dev/enjarai/trickster/mixin/LivingEntityMixin.java b/src/main/java/dev/enjarai/trickster/mixin/LivingEntityMixin.java index c56abd5c..f3b224b3 100644 --- a/src/main/java/dev/enjarai/trickster/mixin/LivingEntityMixin.java +++ b/src/main/java/dev/enjarai/trickster/mixin/LivingEntityMixin.java @@ -4,6 +4,9 @@ import dev.enjarai.trickster.ModAttachments; import dev.enjarai.trickster.cca.ModChunkCumponents; import dev.enjarai.trickster.cca.ModEntityCumponents; +import dev.enjarai.trickster.spell.ItemTriggerHelper; +import dev.enjarai.trickster.spell.fragment.NumberFragment; +import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -16,6 +19,7 @@ import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.EmptyChunk; @@ -33,10 +37,12 @@ @SuppressWarnings("UnstableApiUsage") @Mixin(LivingEntity.class) public abstract class LivingEntityMixin extends Entity { - @Shadow public abstract AttributeContainer getAttributes(); - @Unique private static final StatusEffectInstance PERM_BLINDNESS = new StatusEffectInstance(StatusEffects.BLINDNESS, 100, 2); + + @Shadow + public abstract AttributeContainer getAttributes(); + @Unique private boolean inShadowBlock; @@ -75,6 +81,19 @@ public StatusEffectInstance getStatusEffect(StatusEffectInstance original, Regis return original; } + @Inject( + method = "fall", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/entity/LivingEntity;applyMovementEffects(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/util/math/BlockPos;)V" + ) + ) + private void triggerBoots(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition, CallbackInfo ci) { + if ((LivingEntity)(Object)this instanceof ServerPlayerEntity player) { + ItemTriggerHelper.triggerBoots(player, new NumberFragment(this.fallDistance)); + } + } + @Inject( method = "tick", at = @At("TAIL") diff --git a/src/main/java/dev/enjarai/trickster/mixin/event/EntityMixin.java b/src/main/java/dev/enjarai/trickster/mixin/event/EntityMixin.java deleted file mode 100644 index 6c81bec9..00000000 --- a/src/main/java/dev/enjarai/trickster/mixin/event/EntityMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.enjarai.trickster.mixin.event; - -import dev.enjarai.trickster.spell.ItemTriggerProvider; -import dev.enjarai.trickster.spell.fragment.NumberFragment; -import net.minecraft.entity.Entity; -import net.minecraft.server.network.ServerPlayerEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(Entity.class) -public class EntityMixin implements ItemTriggerProvider { - @Inject(method = "onLanding", at = @At("HEAD")) - private void triggerItemSpell(CallbackInfo ci) { - var self = (Entity)(Object)this; - - if (self.isTouchingWater() || self.fallDistance <= 2.5) - return; - - if (self instanceof ServerPlayerEntity player) { - trickster$triggerBoots(player, new NumberFragment(self.fallDistance)); - } - } -} diff --git a/src/main/java/dev/enjarai/trickster/mixin/event/ItemStackMixin.java b/src/main/java/dev/enjarai/trickster/mixin/event/ItemStackMixin.java deleted file mode 100644 index b373e72b..00000000 --- a/src/main/java/dev/enjarai/trickster/mixin/event/ItemStackMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package dev.enjarai.trickster.mixin.event; - -import dev.enjarai.trickster.spell.ItemTriggerProvider; -import dev.enjarai.trickster.spell.fragment.EntityFragment; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.server.network.ServerPlayerEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(ItemStack.class) -public class ItemStackMixin implements ItemTriggerProvider { - @Inject(method = "postHit", at = @At("RETURN")) - private void triggerItemSpell(LivingEntity target, PlayerEntity player, CallbackInfoReturnable cir) { - if (player instanceof ServerPlayerEntity serverPlayer) { - trickster$triggerMainHand(serverPlayer, EntityFragment.from(target)); - } - } -} diff --git a/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerEntityMixin.java b/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerEntityMixin.java new file mode 100644 index 00000000..82456ca3 --- /dev/null +++ b/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerEntityMixin.java @@ -0,0 +1,32 @@ +package dev.enjarai.trickster.mixin.event; + +import com.mojang.authlib.GameProfile; +import dev.enjarai.trickster.spell.ItemTriggerHelper; +import dev.enjarai.trickster.spell.fragment.EntityFragment; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ServerPlayerEntity.class) +public abstract class ServerPlayerEntityMixin extends PlayerEntity { + public ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile gameProfile) { + super(world, pos, yaw, gameProfile); + } + + @Inject( + method = "attack", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/entity/player/PlayerEntity;attack(Lnet/minecraft/entity/Entity;)V" + ) + ) + private void triggerItemSpell(Entity target, CallbackInfo ci) { + ItemTriggerHelper.triggerMainHand((ServerPlayerEntity)(Object)this, EntityFragment.from(target)); + } +} diff --git a/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerInteractionManagerMixin.java b/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerInteractionManagerMixin.java index 75ecf3e5..7ac40c44 100644 --- a/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerInteractionManagerMixin.java +++ b/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerInteractionManagerMixin.java @@ -1,7 +1,5 @@ package dev.enjarai.trickster.mixin.event; -import dev.enjarai.trickster.spell.ItemTriggerProvider; -import dev.enjarai.trickster.spell.fragment.VectorFragment; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerInteractionManager; import net.minecraft.server.world.ServerWorld; @@ -14,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ServerPlayerInteractionManager.class) -public abstract class ServerPlayerInteractionManagerMixin implements ItemTriggerProvider { +public abstract class ServerPlayerInteractionManagerMixin { @Shadow protected ServerWorld world; @Shadow @Final protected ServerPlayerEntity player; @@ -37,9 +35,4 @@ private void whyTheFuckDoesntMojangDoThis(BlockPos pos, int sequence, String rea } } } - - @Inject(method = "finishMining", at = @At("RETURN")) - private void triggerItemSpell(BlockPos pos, int sequence, String reason, CallbackInfo ci) { - trickster$triggerMainHand(player, VectorFragment.of(pos)); - } } \ No newline at end of file diff --git a/src/main/java/dev/enjarai/trickster/spell/ItemTriggerHelper.java b/src/main/java/dev/enjarai/trickster/spell/ItemTriggerHelper.java new file mode 100644 index 00000000..8c86387b --- /dev/null +++ b/src/main/java/dev/enjarai/trickster/spell/ItemTriggerHelper.java @@ -0,0 +1,45 @@ +package dev.enjarai.trickster.spell; + +import dev.enjarai.trickster.cca.ModEntityCumponents; +import dev.enjarai.trickster.item.component.ModComponents; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ToolItem; +import net.minecraft.server.network.ServerPlayerEntity; + +import java.util.List; +import java.util.Optional; + +public class ItemTriggerHelper { + public static void triggerMainHand(ServerPlayerEntity player, Fragment... arguments) { + var stack = player.getMainHandStack(); + + if (stack.getItem() instanceof ToolItem) { + trigger(player, stack, List.of(arguments)); + } + } + + public static void triggerBoots(ServerPlayerEntity player, Fragment... arguments) { + triggerArmor(player, 0, arguments); + } + + public static void triggerArmor(ServerPlayerEntity player, int index, Fragment... arguments) { + int i = 0; + + for (var item : player.getAllArmorItems()) { + if (index == i) { + trigger(player, item, List.of(arguments)); + return; + } + + i++; + } + } + + public static void trigger(ServerPlayerEntity player, ItemStack stack, List arguments) { + var spellComponent = stack.get(ModComponents.SPELL); + + if (spellComponent != null) { + ModEntityCumponents.CASTER.get(player).queueSpellAndCast(spellComponent.spell(), arguments, Optional.empty()); + } + } +} diff --git a/src/main/java/dev/enjarai/trickster/spell/ItemTriggerProvider.java b/src/main/java/dev/enjarai/trickster/spell/ItemTriggerProvider.java deleted file mode 100644 index 6b08c9f8..00000000 --- a/src/main/java/dev/enjarai/trickster/spell/ItemTriggerProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -package dev.enjarai.trickster.spell; - -import dev.enjarai.trickster.cca.ModEntityCumponents; -import dev.enjarai.trickster.item.component.ModComponents; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ToolItem; -import net.minecraft.server.network.ServerPlayerEntity; - -import java.util.List; - -public interface ItemTriggerProvider { - default void trickster$triggerMainHand(ServerPlayerEntity player, Fragment... arguments) { - var stack = player.getMainHandStack(); - - if (stack.getItem() instanceof ToolItem) { - trickster$trigger(player, stack, List.of(arguments)); - } - } - - default void trickster$triggerBoots(ServerPlayerEntity player, Fragment... arguments) { - trickster$triggerArmour(player, 0, arguments); - } - - default void trickster$triggerArmour(ServerPlayerEntity player, int index, Fragment... arguments) { - int i = 0; - - for (var item : player.getAllArmorItems()) { - if (index == i) { - trickster$trigger(player, item, List.of(arguments)); - return; - } - - i++; - } - } - - default void trickster$trigger(ServerPlayerEntity player, ItemStack stack, List arguments) { - var spellComponent = stack.get(ModComponents.SPELL); - - if (spellComponent != null) { - ModEntityCumponents.CASTER.get(player).queueSpell(spellComponent.spell(), arguments); - } - } -} diff --git a/src/main/java/dev/enjarai/trickster/spell/execution/SpellExecutionManager.java b/src/main/java/dev/enjarai/trickster/spell/execution/SpellExecutionManager.java index 4f83308e..2abf2764 100644 --- a/src/main/java/dev/enjarai/trickster/spell/execution/SpellExecutionManager.java +++ b/src/main/java/dev/enjarai/trickster/spell/execution/SpellExecutionManager.java @@ -46,8 +46,8 @@ public boolean queue(SpellPart spell, List arguments) { return queue(new DefaultSpellExecutor(spell, arguments)); } - public SpellQueueResult queueAndCast(SpellPart spell, List arguments, ManaPool poolOverride) { - var executor = new DefaultSpellExecutor(spell, new ExecutionState(arguments, poolOverride)); + public SpellQueueResult queueAndCast(SpellPart spell, List arguments, Optional poolOverride) { + var executor = new DefaultSpellExecutor(spell, poolOverride.flatMap(pool -> Optional.of(new ExecutionState(arguments, pool))).orElse(new ExecutionState(arguments))); boolean queued = queue(executor); if (queued) { diff --git a/src/main/resources/trickster.mixins.json b/src/main/resources/trickster.mixins.json index d9963a89..aec8bf94 100644 --- a/src/main/resources/trickster.mixins.json +++ b/src/main/resources/trickster.mixins.json @@ -7,15 +7,14 @@ "AbstractBlockStateMixin", "AnvilScreenHandlerMixin", "EntityMixin", + "ItemMixin", "LivingEntityMixin", "WorldChunkMixin", "chunk_pinning.MinecraftServerMixin", "chunk_pinning.ServerChunkLoadingManagerMixin", "chunk_pinning.ServerWorldMixin", - "event.EntityMixin", - "event.ItemStackMixin", - "event.ServerPlayerInteractionManagerMixin", - "ItemMixin" + "event.ServerPlayerEntityMixin", + "event.ServerPlayerInteractionManagerMixin" ], "injectors": { "defaultRequire": 1 From ef1489942ea790616cc18c262a83a4858bba2d5d Mon Sep 17 00:00:00 2001 From: Aurora Dawn <131844170+StellarWitch7@users.noreply.github.com> Date: Sat, 24 Aug 2024 17:21:17 -0400 Subject: [PATCH 6/8] You shan't fool the book --- .../spell/trick/basic/WriteSpellTrick.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/enjarai/trickster/spell/trick/basic/WriteSpellTrick.java b/src/main/java/dev/enjarai/trickster/spell/trick/basic/WriteSpellTrick.java index 57e4d69a..fae71f34 100644 --- a/src/main/java/dev/enjarai/trickster/spell/trick/basic/WriteSpellTrick.java +++ b/src/main/java/dev/enjarai/trickster/spell/trick/basic/WriteSpellTrick.java @@ -6,6 +6,7 @@ import dev.enjarai.trickster.spell.Fragment; import dev.enjarai.trickster.spell.Pattern; import dev.enjarai.trickster.spell.SpellContext; +import dev.enjarai.trickster.spell.SpellPart; import dev.enjarai.trickster.spell.fragment.BooleanFragment; import dev.enjarai.trickster.spell.fragment.FragmentType; import dev.enjarai.trickster.spell.trick.Trick; @@ -44,9 +45,16 @@ public Fragment activate(SpellContext ctx, List fragments, boolean clo spell.ifPresentOrElse(s -> { var stack2 = stack; - if (stack2.isOf(Items.BOOK)) { + if (stack2.isOf(Items.BOOK) + && !s.isEmpty()) { serverPlayer.equipStack(EquipmentSlot.OFFHAND, stack2.withItem(Items.ENCHANTED_BOOK)); stack2 = serverPlayer.getOffHandStack(); + } else if (stack2.isOf(Items.ENCHANTED_BOOK) + && s.isEmpty() + && (stack.get(DataComponentTypes.STORED_ENCHANTMENTS) instanceof ItemEnchantmentsComponent enchants) + && enchants.isEmpty()) { + serverPlayer.equipStack(EquipmentSlot.OFFHAND, stack2.withItem(Items.BOOK)); + stack2 = serverPlayer.getOffHandStack(); } if (!SpellComponent.setSpellPart(stack2, s, supposeInput(fragments, FragmentType.STRING, 1).flatMap(str -> Optional.of(str.value())), closed)) { @@ -55,7 +63,9 @@ public Fragment activate(SpellContext ctx, List fragments, boolean clo }, () -> { var stack2 = stack; - if (stack2.isOf(Items.ENCHANTED_BOOK) && (stack.get(DataComponentTypes.STORED_ENCHANTMENTS) instanceof ItemEnchantmentsComponent enchants) && enchants.isEmpty()) { + if (stack2.isOf(Items.ENCHANTED_BOOK) + && (stack.get(DataComponentTypes.STORED_ENCHANTMENTS) instanceof ItemEnchantmentsComponent enchants) + && enchants.isEmpty()) { serverPlayer.equipStack(EquipmentSlot.OFFHAND, stack2.withItem(Items.BOOK)); stack2 = serverPlayer.getOffHandStack(); } From 8cc3a9460d5cbec1a1e4a4f106ebcd682ba18bef Mon Sep 17 00:00:00 2001 From: Aurora Dawn <131844170+StellarWitch7@users.noreply.github.com> Date: Sat, 24 Aug 2024 18:46:09 -0400 Subject: [PATCH 7/8] I don't know what I'm doing --- .../java/dev/enjarai/trickster/Trickster.java | 4 ++- .../tome_of_tomfoolery/trigger_items.md | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/trigger_items.md diff --git a/src/main/java/dev/enjarai/trickster/Trickster.java b/src/main/java/dev/enjarai/trickster/Trickster.java index a3b98f21..d3dd3c7d 100644 --- a/src/main/java/dev/enjarai/trickster/Trickster.java +++ b/src/main/java/dev/enjarai/trickster/Trickster.java @@ -61,8 +61,10 @@ public void onInitialize() { PlayerBlockBreakEvents.BEFORE.register((world, player, pos, state, blockEntity) -> { if (player instanceof ServerPlayerEntity serverPlayer) ItemTriggerHelper.triggerMainHand(serverPlayer, VectorFragment.of(pos)); + else return true; - return true; + var newState = world.getBlockState(pos); + return newState.getBlock() == state.getBlock() || newState.getHardness(world, pos) > 0; }); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { diff --git a/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/trigger_items.md b/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/trigger_items.md new file mode 100644 index 00000000..69208be3 --- /dev/null +++ b/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/trigger_items.md @@ -0,0 +1,25 @@ +```json +{ + "title": "Trigger Items", + "icon": "minecraft:diamond_sword" +} +``` + +While the [Wand](^trickster:basics/wand) is the most common, and most versatile, way of quickly casting spells, it is not the only one available. +Described here are several alternative options that are worth considering. + +;;;;; + +<|page-title@lavender:book_components|title=Warrior's Rage|>On tools and melee weapons, +the Warrior's Rage executes the inscribed spell when bringing harm to an entity. The targeted entity received as the first argument. + +;;;;; + +<|page-title@lavender:book_components|title=Prospector's Glee|>Prior to destroying a block, +the Prospector's Glee begins the spell inscribed on the held tool. The position of the breaking block is received as the first argument. + +;;;;; + +<|page-title@lavender:book_components|title=Performer's Grace|>Moments before touching down on a block, +the Performer's Grace triggers a spell inscribed in footwear. The distance that the wearer fell is passed as the first argument. +When held back by water, there is no Grace to the Performer. \ No newline at end of file From 352ca5ce82f466303c65e17dcadf7bb827ab6d88 Mon Sep 17 00:00:00 2001 From: Aurora Dawn <131844170+StellarWitch7@users.noreply.github.com> Date: Sun, 25 Aug 2024 12:42:57 -0400 Subject: [PATCH 8/8] It must be done --- src/main/java/dev/enjarai/trickster/Trickster.java | 2 +- src/main/java/dev/enjarai/trickster/item/ModItems.java | 4 +--- .../trickster/mixin/event/ServerPlayerEntityMixin.java | 2 +- .../dev/enjarai/trickster/spell/ItemTriggerHelper.java | 7 +++++-- .../lavender/entries/tome_of_tomfoolery/trigger_items.md | 4 ++-- .../data/trickster/tags/item/weapon_spell_triggers.json | 5 +++++ 6 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 src/main/resources/data/trickster/tags/item/weapon_spell_triggers.json diff --git a/src/main/java/dev/enjarai/trickster/Trickster.java b/src/main/java/dev/enjarai/trickster/Trickster.java index d3dd3c7d..39c9d0bd 100644 --- a/src/main/java/dev/enjarai/trickster/Trickster.java +++ b/src/main/java/dev/enjarai/trickster/Trickster.java @@ -60,7 +60,7 @@ public void onInitialize() { PlayerBlockBreakEvents.BEFORE.register((world, player, pos, state, blockEntity) -> { if (player instanceof ServerPlayerEntity serverPlayer) - ItemTriggerHelper.triggerMainHand(serverPlayer, VectorFragment.of(pos)); + ItemTriggerHelper.triggerMainHand(serverPlayer, false, VectorFragment.of(pos)); else return true; var newState = world.getBlockState(pos); diff --git a/src/main/java/dev/enjarai/trickster/item/ModItems.java b/src/main/java/dev/enjarai/trickster/item/ModItems.java index 59c2039c..10253138 100644 --- a/src/main/java/dev/enjarai/trickster/item/ModItems.java +++ b/src/main/java/dev/enjarai/trickster/item/ModItems.java @@ -7,8 +7,6 @@ import io.wispforest.lavender.book.LavenderBookItem; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; import net.minecraft.block.Block; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.ContainerComponent; import net.minecraft.component.type.FoodComponent; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; @@ -18,7 +16,6 @@ import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.tag.TagKey; import net.minecraft.text.Text; -import net.minecraft.util.collection.DefaultedList; import java.util.List; import java.util.Optional; @@ -64,6 +61,7 @@ public class ModItems { // public static final TagKey IMMUTABLE_SPELL_HOLDERS = TagKey.of(RegistryKeys.ITEM, Trickster.id("immutable_spell_holders")); public static final TagKey SPELL_COST = TagKey.of(RegistryKeys.ITEM, Trickster.id("spell_cost")); public static final TagKey NO_SPELL_GLINT = TagKey.of(RegistryKeys.ITEM, Trickster.id("no_spell_glint")); + public static final TagKey WEAPON_SPELL_TRIGGERS = TagKey.of(RegistryKeys.ITEM, Trickster.id("weapon_spell_triggers")); public static final TagKey CONJURABLE_FLOWERS = TagKey.of(RegistryKeys.BLOCK, Trickster.id("conjurable_flowers")); public static final ItemGroup ITEM_GROUP = FabricItemGroup.builder() diff --git a/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerEntityMixin.java b/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerEntityMixin.java index 82456ca3..0c5c780e 100644 --- a/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerEntityMixin.java +++ b/src/main/java/dev/enjarai/trickster/mixin/event/ServerPlayerEntityMixin.java @@ -27,6 +27,6 @@ public ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile ) ) private void triggerItemSpell(Entity target, CallbackInfo ci) { - ItemTriggerHelper.triggerMainHand((ServerPlayerEntity)(Object)this, EntityFragment.from(target)); + ItemTriggerHelper.triggerMainHand((ServerPlayerEntity)(Object)this, true, EntityFragment.from(target)); } } diff --git a/src/main/java/dev/enjarai/trickster/spell/ItemTriggerHelper.java b/src/main/java/dev/enjarai/trickster/spell/ItemTriggerHelper.java index 8c86387b..4a7411bf 100644 --- a/src/main/java/dev/enjarai/trickster/spell/ItemTriggerHelper.java +++ b/src/main/java/dev/enjarai/trickster/spell/ItemTriggerHelper.java @@ -1,19 +1,22 @@ package dev.enjarai.trickster.spell; import dev.enjarai.trickster.cca.ModEntityCumponents; +import dev.enjarai.trickster.item.ModItems; import dev.enjarai.trickster.item.component.ModComponents; import net.minecraft.item.ItemStack; import net.minecraft.item.ToolItem; +import net.minecraft.registry.tag.ItemTags; import net.minecraft.server.network.ServerPlayerEntity; import java.util.List; import java.util.Optional; public class ItemTriggerHelper { - public static void triggerMainHand(ServerPlayerEntity player, Fragment... arguments) { + public static void triggerMainHand(ServerPlayerEntity player, boolean isWeaponTrigger, Fragment... arguments) { var stack = player.getMainHandStack(); + var item = stack.getItem(); - if (stack.getItem() instanceof ToolItem) { + if (item instanceof ToolItem || (isWeaponTrigger && stack.isIn(ModItems.WEAPON_SPELL_TRIGGERS))) { trigger(player, stack, List.of(arguments)); } } diff --git a/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/trigger_items.md b/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/trigger_items.md index 69208be3..7244f93a 100644 --- a/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/trigger_items.md +++ b/src/main/resources/assets/trickster/lavender/entries/tome_of_tomfoolery/trigger_items.md @@ -6,12 +6,12 @@ ``` While the [Wand](^trickster:basics/wand) is the most common, and most versatile, way of quickly casting spells, it is not the only one available. -Described here are several alternative options that are worth considering. +Other items may cast their inscribed spell upon certain criteria being met. These items and their criteria are described here. ;;;;; <|page-title@lavender:book_components|title=Warrior's Rage|>On tools and melee weapons, -the Warrior's Rage executes the inscribed spell when bringing harm to an entity. The targeted entity received as the first argument. +the Warrior's Rage executes the inscribed spell when bringing harm to an entity. The targeted entity is received as the first argument. ;;;;; diff --git a/src/main/resources/data/trickster/tags/item/weapon_spell_triggers.json b/src/main/resources/data/trickster/tags/item/weapon_spell_triggers.json new file mode 100644 index 00000000..7a2c450b --- /dev/null +++ b/src/main/resources/data/trickster/tags/item/weapon_spell_triggers.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:trident" + ] +} \ No newline at end of file