From 96990e0bd281f3a7d520dfab6a3de75cb4c1a6b7 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 6 May 2024 01:06:26 -0700 Subject: [PATCH] feat: Add other interactions as pipeline transactions --- .editorconfig | 2 + .../bridge/world/TrackedWorldBridge.java | 5 +- .../event/SpongeCommonEventFactory.java | 4 +- .../transaction/EventByTransaction.java | 2 +- .../context/transaction/GameTransaction.java | 13 ++ .../context/transaction/TransactionSink.java | 26 +++- .../TransactionalCaptureSupplier.java | 7 +- ...actionArgs.java => InteractionAtArgs.java} | 2 +- .../effect/InteractionItemEffect.java | 4 +- .../InteractionUseItemOnBlockEffect.java | 4 +- .../effect/ProcessingSideEffect.java | 6 +- .../transaction/effect/UseItemArgs.java | 5 +- .../transaction/effect/UseItemAtArgs.java | 41 +++++++ ...efreshEffect.java => UseItemAtEffect.java} | 29 +++-- .../transaction/effect/UseItemEffect.java | 18 +-- .../transaction/effect/UseItemOnArgs.java | 39 ++++++ .../inventory/CompositeTransaction.java | 68 +++++++++++ .../inventory/InteractItemTransaction.java | 53 ++++----- .../InteractItemWithBlockTransaction.java | 112 ++++++++++++++++++ .../pipeline/UseBlockPipeline.java | 6 +- .../pipeline/UseItemAtPipeline.java | 100 ++++++++++++++++ .../pipeline/UseItemOnBlockPipeline.java | 6 +- .../transaction/pipeline/UseItemPipeline.java | 18 +-- .../transaction/type/TransactionTypes.java | 4 +- .../loader/SpongeCommonRegistryLoader.java | 2 +- .../core/world/entity/ai/goal/GoalMixin.java | 3 + ...GamePacketListenerImplMixin_Inventory.java | 10 +- .../level/ServerLevelMixin_Tracker.java | 69 +++++++---- .../ServerPlayerGameModeMixin_Tracker.java | 13 +- .../test/projectile/ProjectileTest.java | 2 +- .../test/volumestream/VolumeStreamTest.java | 2 +- 31 files changed, 550 insertions(+), 125 deletions(-) rename src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/{InteractionArgs.java => InteractionAtArgs.java} (98%) create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtArgs.java rename src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/{PlayerContainerRefreshEffect.java => UseItemAtEffect.java} (68%) create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemOnArgs.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemWithBlockTransaction.java create mode 100644 src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java diff --git a/.editorconfig b/.editorconfig index ea24aef8a80..14179785cef 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,6 +12,8 @@ insert_final_newline = false max_line_length = 120 tab_width = 4 +[{*.json,*.jsonc,*.png.mcmeta,mcmod.info,pack.mcmeta}] +indent_size = 2 [*.yaml] indent_size = 2 \ No newline at end of file diff --git a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java index c5c48c5c380..91d1e7d860a 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java @@ -45,6 +45,7 @@ import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; @@ -117,5 +118,7 @@ public interface TrackedWorldBridge { UseBlockPipeline bridge$startInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); - UseItemPipeline bridge$startItemInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative); + UseItemAtPipeline bridge$startItemInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative); + + UseItemPipeline bridge$startItemInteractionUseChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack); } diff --git a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java index 5a769dface4..6a5eff8d157 100644 --- a/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/SpongeCommonEventFactory.java @@ -297,10 +297,10 @@ public static InteractItemEvent.Primary callInteractItemEventPrimary(final net.m } } - public static InteractItemEvent.Secondary callInteractItemEventSecondary(final net.minecraft.world.entity.player.Player player, final ItemStack stack, final InteractionHand hand) { + public static InteractItemEvent.Secondary.Pre callInteractItemEventSecondary(final net.minecraft.world.entity.player.Player player, final ItemStack stack, final InteractionHand hand) { try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { SpongeCommonEventFactory.applyCommonInteractContext(player, stack, hand, null, null, frame); - final InteractItemEvent.Secondary event = SpongeEventFactory.createInteractItemEventSecondary(frame.currentCause(), ItemStackUtil.snapshotOf(stack)); + final var event = SpongeEventFactory.createInteractItemEventSecondaryPre(frame.currentCause(), ItemStackUtil.snapshotOf(stack)); SpongeCommon.post(event); return event; } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EventByTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EventByTransaction.java index eed31f53d27..a2dc78e740c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EventByTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/EventByTransaction.java @@ -32,7 +32,7 @@ import org.spongepowered.api.event.Event; @DefaultQualifier(NonNull.class) -record EventByTransaction( +public record EventByTransaction( T event, ImmutableList> transactions, @Nullable GameTransaction<@NonNull ?> parent, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java index 391443f3f19..9f524c74b75 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/GameTransaction.java @@ -46,6 +46,7 @@ import java.util.Optional; import java.util.StringJoiner; import java.util.function.BiConsumer; +import java.util.stream.Stream; @DefaultQualifier(NonNull.class) public abstract class GameTransaction implements TransactionFlow, StatefulTransaction { @@ -189,6 +190,18 @@ protected void captureState() { } + public void associateSideEffectEvents(E e, Stream elements) { + + } + + public void pushCause(CauseStackManager.StackFrame frame, E e) { + frame.pushCause(e); + } + + public void finalizeSideEffects(E e) { + + } + private static class ChildIterator implements Iterator> { private final Iterator> effectIterator; private @Nullable GameTransaction<@NonNull ?> cachedNext; diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java index 73655b3996b..303ebf915a6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionSink.java @@ -27,7 +27,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -46,6 +45,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.block.BlockSnapshot; +import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.cause.entity.SpawnType; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.api.item.inventory.ItemStackSnapshot; @@ -74,6 +74,7 @@ import org.spongepowered.common.event.tracking.context.transaction.block.ScheduleUpdateTransaction; import org.spongepowered.common.event.tracking.context.transaction.effect.BlockAddedEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.EntityPerformingDropsEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.InventoryEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.PrepareBlockDrops; import org.spongepowered.common.event.tracking.context.transaction.effect.ProcessingSideEffect; @@ -86,6 +87,7 @@ import org.spongepowered.common.event.tracking.context.transaction.inventory.DropFromPlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.ExplicitInventoryOmittedTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.InteractItemTransaction; +import org.spongepowered.common.event.tracking.context.transaction.inventory.InteractItemWithBlockTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.InventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.OpenMenuTransaction; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlaceRecipeTransaction; @@ -421,10 +423,26 @@ default EffectTransactor logInventoryTransaction(final AbstractContainerMenu con } default void logSecondaryInteractionTransaction( - final ServerPlayer playerIn, final ItemStack stackIn, final Vector3d hitVec, - final BlockSnapshot snapshot, final Direction direction, final InteractionHand handIn) { - final InteractItemTransaction transaction = new InteractItemTransaction(playerIn, stackIn, hitVec, snapshot, direction, handIn); + final ServerPlayer playerIn, final Vector3d hitVec, + final BlockSnapshot snapshot, final Direction direction, InteractBlockEvent.Secondary.Pre event) { + final InteractItemWithBlockTransaction transaction = new InteractItemWithBlockTransaction(playerIn, + hitVec, + snapshot, + direction, + event.originalUseBlockResult(), + event.useBlockResult(), + event.originalUseItemResult(), + event.useItemResult() + ); this.logTransaction(transaction); } + default EffectTransactor logSecondaryInteractItemTransaction( + final ServerPlayer playerIn, final ItemStack stackIn + ) { + final InteractItemTransaction transaction = new InteractItemTransaction(playerIn, stackIn); + this.logTransaction(transaction); + return this.pushEffect(new ResultingTransactionBySideEffect<>(InteractionItemEffect.getInstance())); + } + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java index 36edd7e27c6..d5bb7c3cb0b 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/TransactionalCaptureSupplier.java @@ -311,13 +311,16 @@ private static void generateEventForTransaction( if (transaction.sideEffects == null || transaction.sideEffects.isEmpty()) { continue; } - generatedEvent.ifPresent(frame::pushCause); + generatedEvent.ifPresent(e -> transaction.pushCause(frame, e)); for (final ResultingTransactionBySideEffect sideEffect : transaction.sideEffects) { if (sideEffect.head == null) { continue; } - builder.addAll(TransactionalCaptureSupplier.batchTransactions(sideEffect.head, pointer, context, transactionPostEventBuilder)); + final var elements = TransactionalCaptureSupplier.batchTransactions(sideEffect.head, pointer, context, transactionPostEventBuilder); + generatedEvent.ifPresent(e -> transaction.associateSideEffectEvents(e, elements.stream().map(EventByTransaction::event))); + builder.addAll(elements); } + generatedEvent.ifPresent(transaction::finalizeSideEffects); } } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionAtArgs.java similarity index 98% rename from src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java rename to src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionAtArgs.java index fac849e78d2..5cd9000fdc3 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionArgs.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionAtArgs.java @@ -31,7 +31,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; -public record InteractionArgs( +public record InteractionAtArgs( Level world, ServerPlayer player, InteractionHand hand, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java index 8ccfc3a0b4e..57af8e795a9 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionItemEffect.java @@ -29,7 +29,7 @@ import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; -public final class InteractionItemEffect implements ProcessingSideEffect { +public final class InteractionItemEffect implements ProcessingSideEffect.Simple { private static final class Holder { static final InteractionItemEffect INSTANCE = new InteractionItemEffect(); @@ -41,7 +41,7 @@ public static InteractionItemEffect getInstance() { @Override public EffectResult processSideEffect( - UseBlockPipeline pipeline, InteractionResult oldState, InteractionArgs args + UseBlockPipeline pipeline, InteractionResult oldState, InteractionAtArgs args ) { final var player = args.player(); final var world = args.world(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java index 71d393a62fe..e0bcef3e8e8 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/InteractionUseItemOnBlockEffect.java @@ -29,7 +29,7 @@ import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; -public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { +public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { private static final class Holder { static final InteractionUseItemOnBlockEffect INSTANCE = new InteractionUseItemOnBlockEffect(); @@ -41,7 +41,7 @@ public static InteractionUseItemOnBlockEffect getInstance() { @Override public EffectResult processSideEffect( - UseItemOnBlockPipeline pipeline, ItemInteractionResult oldState, InteractionArgs args + UseItemOnBlockPipeline pipeline, ItemInteractionResult oldState, InteractionAtArgs args ) { final var player = args.player(); final var hand = args.hand(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java index 6c4a7d1ff09..be0e3f21018 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/ProcessingSideEffect.java @@ -29,8 +29,12 @@ @FunctionalInterface public interface ProcessingSideEffect { + interface Simple extends ProcessingSideEffect { + + } + EffectResult processSideEffect(T pipeline, C oldState, A args); - sealed interface Args permits BlockChangeArgs, InteractionArgs, UseItemArgs {} + sealed interface Args permits BlockChangeArgs, InteractionAtArgs, UseItemOnArgs, UseItemAtArgs, UseItemArgs {} } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java index aebd7497bb2..eeb1c6c3f2f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemArgs.java @@ -25,17 +25,16 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.phys.BlockHitResult; public record UseItemArgs( Level world, ServerPlayer player, InteractionHand hand, - BlockHitResult result, ItemStack copiedStack, - boolean creative + ServerPlayerGameMode gameMode ) implements ProcessingSideEffect.Args { } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtArgs.java new file mode 100644 index 00000000000..ab8616303c3 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtArgs.java @@ -0,0 +1,41 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; + +public record UseItemAtArgs( + Level world, + ServerPlayer player, + InteractionHand hand, + BlockHitResult result, + ItemStack copiedStack, + boolean creative +) implements ProcessingSideEffect.Args { +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java similarity index 68% rename from src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java rename to src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java index a0f81ef9ad0..2f7dc7ea299 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/PlayerContainerRefreshEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java @@ -25,28 +25,43 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.context.UseOnContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; -import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; -public final class PlayerContainerRefreshEffect implements ProcessingSideEffect { +public class UseItemAtEffect implements ProcessingSideEffect.Simple { private static final class Holder { - static final PlayerContainerRefreshEffect INSTANCE = new PlayerContainerRefreshEffect(); + static final UseItemAtEffect INSTANCE = new UseItemAtEffect(); } - public static PlayerContainerRefreshEffect getInstance() { - return Holder.INSTANCE; + private UseItemAtEffect() { + } + + public static UseItemAtEffect getInstance() { + return UseItemAtEffect.Holder.INSTANCE; } @Override public EffectResult processSideEffect( - UseItemOnBlockPipeline pipeline, InteractionResult oldState, InteractionArgs args + UseItemAtPipeline pipeline, InteractionResult oldState, UseItemAtArgs args ) { + final var stack = args.copiedStack(); + final InteractionResult result; + final var context = new UseOnContext(args.player(), args.hand(), args.result()); + if (args.creative()) { + int count = stack.getCount(); + result = stack.useOn(context); + stack.setCount(count); + } else { + result = stack.useOn(context); + } pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { args.player().containerMenu.broadcastChanges(); } - return EffectResult.nullPass(); + return new EffectResult<>(result, true); } + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java index 130e414c734..9a102746cc4 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemEffect.java @@ -25,17 +25,19 @@ package org.spongepowered.common.event.tracking.context.transaction.effect; import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.context.UseOnContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; -public class UseItemEffect implements ProcessingSideEffect { +public class UseItemEffect implements ProcessingSideEffect.Simple { private static final class Holder { static final UseItemEffect INSTANCE = new UseItemEffect(); } + private UseItemEffect() { + } + public static UseItemEffect getInstance() { return UseItemEffect.Holder.INSTANCE; } @@ -44,16 +46,8 @@ public static UseItemEffect getInstance() { public EffectResult processSideEffect( UseItemPipeline pipeline, InteractionResult oldState, UseItemArgs args ) { - final var stack = args.copiedStack(); - final InteractionResult result; - final var context = new UseOnContext(args.player(), args.hand(), args.result()); - if (args.creative()) { - int $$14 = stack.getCount(); - result = stack.useOn(context); - stack.setCount($$14); - } else { - result = stack.useOn(context); - } + final var gameMode = args.gameMode(); + final InteractionResult result = gameMode.useItem(args.player(), args.world(), args.copiedStack(), args.hand()); pipeline.transactor().logPlayerInventoryChange(args.player(), PlayerInventoryTransaction.EventCreator.STANDARD); try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(pipeline.transactor())) { args.player().containerMenu.broadcastChanges(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemOnArgs.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemOnArgs.java new file mode 100644 index 00000000000..72029fd5deb --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemOnArgs.java @@ -0,0 +1,39 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.effect; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import org.spongepowered.api.item.inventory.ItemStackSnapshot; + +public record UseItemOnArgs( + UseOnContext context, + ItemStack itemStack, + ItemStackSnapshot itemStackSnapshot, + ServerPlayer player, + boolean isCreative +) implements ProcessingSideEffect.Args { +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java new file mode 100644 index 00000000000..ab730bdad7c --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/CompositeTransaction.java @@ -0,0 +1,68 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.inventory; + +import com.google.common.collect.ImmutableList; +import org.spongepowered.api.event.Cancellable; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.CompositeEvent; +import org.spongepowered.api.event.Event; +import org.spongepowered.api.event.impl.AbstractCompositeEvent; +import org.spongepowered.common.event.tracking.context.transaction.GameTransaction; +import org.spongepowered.common.event.tracking.context.transaction.type.TransactionType; + +import java.util.stream.Stream; + +public abstract class CompositeTransaction extends GameTransaction { + protected CompositeTransaction(TransactionType transactionType) { + super(transactionType); + } + + @Override + public void associateSideEffectEvents(E event, Stream elements) { + elements.forEach(event.children()::add); + } + + @Override + public void finalizeSideEffects(E post) { + // This finalizes the list to be immutable + ((AbstractCompositeEvent) post).postInit(); + } + + public void pushCause(CauseStackManager.StackFrame frame, E e) { + frame.pushCause(e.baseEvent()); + } + + @Override + public boolean markCancelledTransactions( + final E event, + final ImmutableList> gameTransactions) { + event.children().stream().filter(e -> e instanceof Cancellable) + .map(e -> (Cancellable) e) + .forEach(e -> e.setCancelled(event.isCancelled())); + return false; + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java index 3302e01d076..c2a8fc0399c 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemTransaction.java @@ -26,50 +26,46 @@ import com.google.common.collect.ImmutableList; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.event.Cause; import org.spongepowered.api.event.CauseStackManager; -import org.spongepowered.api.event.block.InteractBlockEvent; +import org.spongepowered.api.event.Event; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.item.inventory.InteractItemEvent; import org.spongepowered.api.item.inventory.ItemStackSnapshot; -import org.spongepowered.api.util.Direction; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.context.transaction.GameTransaction; import org.spongepowered.common.event.tracking.context.transaction.type.TransactionTypes; import org.spongepowered.common.item.util.ItemStackUtil; import org.spongepowered.common.util.PrettyPrinter; -import org.spongepowered.math.vector.Vector3d; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.function.BiConsumer; -public class InteractItemTransaction extends GameTransaction { +public class InteractItemTransaction extends CompositeTransaction { - - private final Vector3d hitVec; - private final BlockSnapshot snapshot; - private final Direction direction; - private final InteractionHand hand; + private final ServerPlayer player; private final ItemStackSnapshot stack; - public InteractItemTransaction(ServerPlayer playerIn, ItemStack stackIn, Vector3d hitVec, BlockSnapshot snapshot, Direction direction, InteractionHand handIn) { - super(TransactionTypes.INTERACT_BLOCK_SECONDARY.get()); + public InteractItemTransaction( + final ServerPlayer playerIn, final ItemStack stackIn) { + super(TransactionTypes.INTERACT_ITEM_SECONDARY.get()); + this.player = playerIn; this.stack = ItemStackUtil.snapshotOf(stackIn); - this.hitVec = hitVec; - this.snapshot = snapshot; - this.direction = direction; - this.hand = handIn; - } + } @Override public Optional, CauseStackManager.StackFrame>> getFrameMutator( @Nullable GameTransaction<@NonNull ?> parent ) { - return Optional.empty(); + return Optional.of((context, frame) -> { + frame.pushCause(this.player); + }); } @Override @@ -78,24 +74,23 @@ public void addToPrinter(PrettyPrinter printer) { } @Override - public Optional generateEvent( + public Optional generateEvent( final PhaseContext<@NonNull ?> context, final @Nullable GameTransaction<@NonNull ?> parent, - final ImmutableList> gameTransactions, + final ImmutableList> gameTransactions, final Cause currentCause ) { - return Optional.empty(); + final var root = SpongeEventFactory.createInteractItemEventSecondary(currentCause, this.stack); + final List list = new ArrayList<>(); + final var composite = SpongeEventFactory.createInteractItemEventSecondaryPost(currentCause, root, list); + return Optional.of(composite); } - @Override - public void restore(PhaseContext<@NonNull ?> context, InteractBlockEvent.Secondary.Composite event) { - } @Override - public boolean markCancelledTransactions( - final InteractBlockEvent.Secondary.Composite event, - final ImmutableList> gameTransactions) { - return false; + public void restore(PhaseContext<@NonNull ?> context, InteractItemEvent.Secondary.Post event) { + } + } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemWithBlockTransaction.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemWithBlockTransaction.java new file mode 100644 index 00000000000..d49727d6adb --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/inventory/InteractItemWithBlockTransaction.java @@ -0,0 +1,112 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.inventory; + +import com.google.common.collect.ImmutableList; +import net.minecraft.server.level.ServerPlayer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.block.BlockSnapshot; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.CauseStackManager; +import org.spongepowered.api.event.Event; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.block.InteractBlockEvent; +import org.spongepowered.api.util.Direction; +import org.spongepowered.api.util.Tristate; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.GameTransaction; +import org.spongepowered.common.event.tracking.context.transaction.type.TransactionTypes; +import org.spongepowered.common.util.PrettyPrinter; +import org.spongepowered.math.vector.Vector3d; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.BiConsumer; + +public class InteractItemWithBlockTransaction extends CompositeTransaction { + + private final Vector3d hitVec; + private final BlockSnapshot snapshot; + private final Direction direction; + private final ServerPlayer player; + private final Tristate originalBlockResult, blockResult, originalItemResult, itemResult; + + public InteractItemWithBlockTransaction( + final ServerPlayer playerIn, final Vector3d hitVec, final BlockSnapshot snapshot, + final Direction direction, + final Tristate originalBlockResult, final Tristate useBlockResult, + final Tristate originalUseItemResult, final Tristate useItemResult) { + super(TransactionTypes.INTERACT_BLOCK_SECONDARY.get()); + this.player = playerIn; + this.hitVec = hitVec; + this.snapshot = snapshot; + this.direction = direction; + this.originalBlockResult = originalBlockResult; + this.blockResult = useBlockResult; + this.originalItemResult = originalUseItemResult; + this.itemResult = useItemResult; + } + + + @Override + public Optional, CauseStackManager.StackFrame>> getFrameMutator( + @Nullable GameTransaction<@NonNull ?> parent + ) { + return Optional.of((context, frame) -> { + frame.pushCause(this.player); + }); + } + + @Override + public void addToPrinter(PrettyPrinter printer) { + + } + + @Override + public Optional generateEvent( + final PhaseContext<@NonNull ?> context, + final @Nullable GameTransaction<@NonNull ?> parent, + final ImmutableList> gameTransactions, + final Cause currentCause + ) { + final var root = SpongeEventFactory.createInteractBlockEventSecondary(currentCause, + this.originalBlockResult, this.blockResult, + this.originalItemResult, this.itemResult, + this.snapshot, this.hitVec, + this.direction + ); + final List list = new ArrayList<>(); + final InteractBlockEvent.Secondary.Post composite = SpongeEventFactory.createInteractBlockEventSecondaryPost(currentCause, root, list); + return Optional.of(composite); + } + + @Override + public void restore(PhaseContext<@NonNull ?> context, InteractBlockEvent.Secondary.Post event) { + + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java index 4203d6474ad..f543af72bd6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java @@ -37,7 +37,7 @@ import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; import java.util.List; @@ -51,7 +51,7 @@ public class UseBlockPipeline { private final BlockHitResult blockRaytraceResult; private final BlockState blockstate; private final ItemStack copiedStack; - private final List> effects; + private final List> effects; private final TransactionalCaptureSupplier transactor; @@ -79,7 +79,7 @@ public InteractionResult processInteraction(PhaseContext context) { var interaction = InteractionResult.PASS; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final InteractionArgs args = new InteractionArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); + final InteractionAtArgs args = new InteractionAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); final EffectResult result = effect.effect.processSideEffect( this, interaction, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java new file mode 100644 index 00000000000..2f2c5f16b17 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java @@ -0,0 +1,100 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.event.tracking.context.transaction.pipeline; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.BlockHitResult; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.event.tracking.PhaseContext; +import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; +import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; +import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; +import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtEffect; + +import java.util.List; +import java.util.Objects; + +public class UseItemAtPipeline { + + private final ServerLevel worldIn; + private final ServerPlayer player; + private final InteractionHand hand; + private final ItemStack copiedStack; + private final BlockHitResult blockRaytraceResult; + private final boolean creative; + private final List> effects; + private final TransactionalCaptureSupplier transactor; + + + public UseItemAtPipeline(ServerLevel worldIn, + ServerPlayer playerIn, + InteractionHand handIn, + ItemStack copiedStack, + BlockHitResult blockRaytraceResult, + boolean creative, + final TransactionalCaptureSupplier transactor) { + + this.worldIn = worldIn; + this.player = playerIn; + this.hand = handIn; + this.copiedStack = copiedStack; + this.blockRaytraceResult = blockRaytraceResult; + this.creative = creative; + this.effects = List.of( + new ResultingTransactionBySideEffect<>(UseItemAtEffect.getInstance()) + ); + this.transactor = transactor; + } + + public InteractionResult processInteraction(PhaseContext context) { + var interaction = InteractionResult.PASS; + for (final var effect : this.effects) { + try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { + final var args = new UseItemAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.copiedStack, this.creative); + final EffectResult result = effect.effect.processSideEffect( + this, + interaction, + args + ); + if (result.hasResult) { + final @Nullable InteractionResult resultingState = result.resultingState; + interaction = Objects.requireNonNullElse(resultingState, interaction); + } + } + } + return interaction; + } + + public TransactionalCaptureSupplier transactor() { + return this.transactor; + } + +} diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java index 82ba980892b..c24001d5719 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java @@ -37,7 +37,7 @@ import org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionUseItemOnBlockEffect; import java.util.List; @@ -51,7 +51,7 @@ public final class UseItemOnBlockPipeline { private final BlockHitResult blockRaytraceResult; private final BlockState blockstate; private final ItemStack copiedStack; - private final List> effects; + private final List> effects; private final TransactionalCaptureSupplier transactor; @@ -79,7 +79,7 @@ public ItemInteractionResult processInteraction(PhaseContext context) { var interaction = ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final InteractionArgs args = new InteractionArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); + final InteractionAtArgs args = new InteractionAtArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.blockstate, this.copiedStack); final EffectResult result = effect.effect.processSideEffect( this, interaction, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java index ce4fbd53238..f2f315e91a7 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java @@ -29,7 +29,6 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.BlockHitResult; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; @@ -48,26 +47,19 @@ public class UseItemPipeline { private final ServerPlayer player; private final InteractionHand hand; private final ItemStack copiedStack; - private final BlockHitResult blockRaytraceResult; - private final boolean creative; private final List> effects; private final TransactionalCaptureSupplier transactor; - public UseItemPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - ItemStack copiedStack, - BlockHitResult blockRaytraceResult, - boolean creative, - final TransactionalCaptureSupplier transactor) { + ServerPlayer playerIn, + InteractionHand handIn, + ItemStack copiedStack, + final TransactionalCaptureSupplier transactor) { this.worldIn = worldIn; this.player = playerIn; this.hand = handIn; this.copiedStack = copiedStack; - this.blockRaytraceResult = blockRaytraceResult; - this.creative = creative; this.effects = List.of( new ResultingTransactionBySideEffect<>(UseItemEffect.getInstance()) ); @@ -78,7 +70,7 @@ public InteractionResult processInteraction(PhaseContext context) { var interaction = InteractionResult.PASS; for (final var effect : this.effects) { try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - final var args = new UseItemArgs(this.worldIn, this.player, this.hand, this.blockRaytraceResult, this.copiedStack, this.creative); + final var args = new UseItemArgs(this.worldIn, this.player, this.hand,this.copiedStack, this.player.gameMode); final EffectResult result = effect.effect.processSideEffect( this, interaction, diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java index 188b314c4a3..fcab599e3d6 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/type/TransactionTypes.java @@ -36,6 +36,7 @@ import org.spongepowered.api.event.entity.SpawnEntityEvent; import org.spongepowered.api.event.item.inventory.AffectSlotEvent; import org.spongepowered.api.event.item.inventory.ChangeInventoryEvent; +import org.spongepowered.api.event.item.inventory.InteractItemEvent; import org.spongepowered.api.event.item.inventory.container.ClickContainerEvent; import org.spongepowered.api.event.item.inventory.container.InteractContainerEvent; import org.spongepowered.api.registry.DefaultedRegistryReference; @@ -68,7 +69,8 @@ public final class TransactionTypes { public static final DefaultedRegistryReference> SLOT_CHANGE = TransactionTypes.key(ResourceKey.sponge("slot_change")); - public static final DefaultedRegistryReference> INTERACT_BLOCK_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); + public static final DefaultedRegistryReference> INTERACT_BLOCK_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); + public static final DefaultedRegistryReference> INTERACT_ITEM_SECONDARY = TransactionTypes.key(ResourceKey.sponge("interact_block_secondary")); // SORTFIELDS:OFF diff --git a/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java b/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java index eb6b5a2ff83..7d7570ff6b5 100644 --- a/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java +++ b/src/main/java/org/spongepowered/common/registry/loader/SpongeCommonRegistryLoader.java @@ -48,7 +48,7 @@ public class SpongeCommonRegistryLoader { l.add(TransactionTypes.NEIGHBOR_NOTIFICATION, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); l.add(TransactionTypes.SCHEDULE_BLOCK_UPDATE, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); l.add(TransactionTypes.SLOT_CHANGE, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); - l.add(TransactionTypes.SPAWN_ENTITY, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); + l.add(TransactionTypes.INTERACT_BLOCK_SECONDARY, k -> new NoOpTransactionType<>(false, k.value().toUpperCase(Locale.ROOT))); }); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/GoalMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/GoalMixin.java index ab09ccf8e03..48052fae4f1 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/GoalMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/ai/goal/GoalMixin.java @@ -29,6 +29,7 @@ import org.spongepowered.api.entity.ai.goal.GoalExecutor; import org.spongepowered.api.entity.ai.goal.GoalType; 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.callback.CallbackInfo; @@ -42,6 +43,8 @@ @Mixin(Goal.class) public abstract class GoalMixin implements GoalBridge { + @Shadow protected abstract int shadow$adjustedTickDelay(int $$0); + private Supplier impl$type; private GoalExecutor impl$owner; diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java index 6866a22f93b..fa0e5eab5b3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java @@ -49,12 +49,12 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.common.bridge.world.TrackedWorldBridge; import org.spongepowered.common.bridge.world.inventory.container.MenuBridge; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; import org.spongepowered.common.event.tracking.context.transaction.EffectTransactor; import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier; -import org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction; import org.spongepowered.common.inventory.custom.SpongeInventoryMenu; import org.spongepowered.common.item.util.ItemStackUtil; @@ -122,12 +122,10 @@ public class ServerGamePacketListenerImplMixin_Inventory { final Level param1, final ItemStack param2, final InteractionHand param3) { final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); - try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(this.player, PlayerInventoryTransaction.EventCreator.STANDARD)) { - final InteractionResult result = serverPlayerGameMode.useItem(param0, param1, param2, param3); - this.player.inventoryMenu.broadcastChanges(); // capture - return result; + try (final EffectTransactor ignored = transactor.logSecondaryInteractItemTransaction(param0, param2)) { + final var pipeline = ((TrackedWorldBridge) param1).bridge$startItemInteractionUseChange(param1, param0, param3, param2); + return pipeline.processInteraction(context); } - // TrackingUtil.processBlockCaptures called by UseItemPacketState } @Redirect(method = "handleContainerClose", diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index 31844e0afc9..ece610b5871 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -109,6 +109,7 @@ import org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor; import org.spongepowered.common.event.tracking.context.transaction.pipeline.TileEntityPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemAtPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemOnBlockPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.UseItemPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; @@ -131,15 +132,15 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem @Redirect( - // This normally would target this.entityTickList.forEach((var2x) -> - // but we don't have lambda syntax support yet. - method = "lambda$tick$2", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/server/level/ServerLevel;guardEntityTick(Ljava/util/function/Consumer;Lnet/minecraft/world/entity/Entity;)V") + // This normally would target this.entityTickList.forEach((var2x) -> + // but we don't have lambda syntax support yet. + method = "lambda$tick$2", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/server/level/ServerLevel;guardEntityTick(Ljava/util/function/Consumer;Lnet/minecraft/world/entity/Entity;)V") ) private void tracker$wrapNormalEntityTick(final ServerLevel level, final Consumer entityUpdateConsumer, - final Entity entity + final Entity entity ) { final PhaseContext<@NonNull ?> currentState = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); TrackingUtil.tickEntity(entityUpdateConsumer, entity); @@ -158,9 +159,9 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem * or we wrap in this method here. * * @param blockState The block state being ticked - * @param worldIn The world (this world) - * @param posIn The position of the block - * @param randomIn The world random + * @param worldIn The world (this world) + * @param posIn The position of the block + * @param randomIn The world random * @author gabizou - January 11th, 2020 - Minecraft 1.14.3 */ @Redirect(method = "tickBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V", @@ -453,11 +454,11 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem final ChunkPipeline chunkPipeline = mixinChunk.bridge$createChunkPipeline(pos, newState, currentState, spongeFlag, limit); final WorldPipeline.Builder worldPipelineBuilder = WorldPipeline.builder(chunkPipeline); worldPipelineBuilder.addEffect((pipeline, oldState, args) -> { - if (oldState == null) { - return EffectResult.nullReturn(); - } - return EffectResult.nullPass(); - }) + if (oldState == null) { + return EffectResult.nullReturn(); + } + return EffectResult.nullPass(); + }) .addEffect(UpdateLightSideEffect.getInstance()) .addEffect(CheckBlockPostPlacementIsSameEffect.getInstance()) .addEffect(UpdateWorldRendererEffect.getInstance()) @@ -547,7 +548,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable @Override public SpongeBlockSnapshot bridge$createSnapshot(final net.minecraft.world.level.block.state.BlockState state, final BlockPos pos, - final BlockChangeFlag updateFlag + final BlockChangeFlag updateFlag ) { final SpongeBlockSnapshot.BuilderImpl builder = SpongeBlockSnapshot.BuilderImpl.pooled(); builder.reset(); @@ -595,7 +596,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } - final var pipeline = new UseItemOnBlockPipeline( + return new UseItemOnBlockPipeline( (ServerLevel) worldIn, playerIn, handIn, @@ -604,9 +605,9 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable copiedStack, instance.getPhaseContext().getTransactor() ); - return pipeline; } + @Override public UseBlockPipeline bridge$startInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer @@ -620,7 +621,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } - final var pipeline = new UseBlockPipeline( + return new UseBlockPipeline( (ServerLevel) worldIn, playerIn, handIn, @@ -629,10 +630,9 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable copiedStack, instance.getPhaseContext().getTransactor() ); - return pipeline; } @Override - public UseItemPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { + public UseItemAtPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer return null; } @@ -644,7 +644,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } - return new UseItemPipeline( + return new UseItemAtPipeline( (ServerLevel) worldIn, playerIn, handIn, @@ -655,6 +655,27 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable ); } + public UseItemPipeline bridge$startItemInteractionUseChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack) { + if (this.shadow$isDebug()) { // isClientSide is always false since this is WorldServer + return null; + } + if (this.bridge$isFake()) { + return null; + } + + final var instance = PhaseTracker.getInstance(); + if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); + } + return new UseItemPipeline( + (ServerLevel) worldIn, + playerIn, + handIn, + copiedStack, + instance.getPhaseContext().getTransactor() + ); + } + /** * Technically an overwrite, but because this is simply an override, we can * effectively do as we need to, which is determine if we are performing @@ -699,7 +720,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable) .addEffect(RemoveTileEntityFromChunkEffect.getInstance()) .build(); - pipeline.processEffects(current, new PipelineCursor(tileentity.getBlockState(), immutable, tileentity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); + pipeline.processEffects(current, new PipelineCursor(tileentity.getBlockState(), immutable, tileentity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); return; } super.shadow$removeBlockEntity(immutable); @@ -731,7 +752,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable) .addEffect(SetAndRegisterBlockEntityToLevelChunk.getInstance()) .build(); - pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); + pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT)); return; } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index b06c7ac4d21..15b021aee54 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -41,7 +41,6 @@ import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.event.CauseStackManager; import org.spongepowered.api.event.EventContextKeys; -import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.item.inventory.InteractItemEvent; import org.spongepowered.api.util.Tristate; import org.spongepowered.api.world.server.ServerLocation; @@ -80,7 +79,7 @@ public abstract class ServerPlayerGameModeMixin_Tracker { public void impl$callInteractItemSecondary(final ServerPlayer player, final Level level, final ItemStack stack, final InteractionHand hand, final CallbackInfoReturnable cir ) { - final InteractItemEvent.Secondary event = SpongeCommonEventFactory.callInteractItemEventSecondary(player, stack, hand); + final InteractItemEvent.Secondary.Pre event = SpongeCommonEventFactory.callInteractItemEventSecondary(player, stack, hand); if (event.isCancelled()) { player.inventoryMenu.sendAllDataToRemote(); cir.setReturnValue(InteractionResult.FAIL); @@ -98,12 +97,16 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl // Sponge start final BlockSnapshot snapshot = ((ServerWorld) (worldIn)).createSnapshot(VecHelper.toVector3i(blockpos)); final Vector3d hitVec = Vector3d.from(blockRaytraceResultIn.getBlockPos().getX(), blockRaytraceResultIn.getBlockPos().getY(), blockRaytraceResultIn.getBlockPos().getZ()); - final org.spongepowered.api.util.Direction direction = DirectionFacingProvider.INSTANCE.getKey(blockRaytraceResultIn.getDirection()).get(); + final var direction = DirectionFacingProvider.INSTANCE.getKey(blockRaytraceResultIn.getDirection()).get(); final PhaseContext phaseContext = PhaseTracker.getInstance().getPhaseContext(); - phaseContext.getTransactor().logSecondaryInteractionTransaction(playerIn, stackIn, hitVec, snapshot, direction, handIn); - final InteractBlockEvent.Secondary.Pre event = SpongeCommonEventFactory.callInteractBlockEventSecondary(playerIn, stackIn, hitVec, snapshot, direction, handIn); + final var event = SpongeCommonEventFactory.callInteractBlockEventSecondary(playerIn, stackIn, hitVec, snapshot, direction, handIn); final Tristate useItem = event.useItemResult(); final Tristate useBlock = event.useBlockResult(); + phaseContext.getTransactor().logSecondaryInteractionTransaction(playerIn, + hitVec, + snapshot, + direction, + event); ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(event.isCancelled()); if (event.isCancelled()) { player.inventoryMenu.sendAllDataToRemote(); diff --git a/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java b/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java index 9d9743c1ce3..1f70e0e6626 100644 --- a/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/projectile/ProjectileTest.java @@ -208,7 +208,7 @@ public ProjectileTestListener() { } @Listener - private void onClickBlock(final InteractBlockEvent.Secondary event, @First final ServerPlayer player) { + private void onClickBlock(final InteractBlockEvent.Secondary.Pre event, @First final ServerPlayer player) { final Vector3d interactionPoint = event.interactionPoint(); final ServerWorld world = player.world(); final EntityType nextType = this.projectileTypes.poll(); diff --git a/testplugins/src/main/java/org/spongepowered/test/volumestream/VolumeStreamTest.java b/testplugins/src/main/java/org/spongepowered/test/volumestream/VolumeStreamTest.java index 1de067274ed..67e0a85ccb0 100644 --- a/testplugins/src/main/java/org/spongepowered/test/volumestream/VolumeStreamTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/volumestream/VolumeStreamTest.java @@ -407,7 +407,7 @@ private void onInteract(final InteractBlockEvent.Primary event, @Root final Play } @Listener - public void onInteract(final InteractBlockEvent.Secondary event, @Root final Player player) { + public void onInteract(final InteractBlockEvent.Secondary.Pre event, @Root final Player player) { event.context().get(EventContextKeys.USED_ITEM).ifPresent(snapshot -> { final BlockSnapshot block = event.block(); if (snapshot.type().equals(ItemTypes.WOODEN_AXE.get()) && block != BlockSnapshot.empty()) {