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 91d1e7d860a..049e851f266 100644 --- a/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java +++ b/src/main/java/org/spongepowered/common/bridge/world/TrackedWorldBridge.java @@ -28,15 +28,13 @@ 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.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.phys.BlockHitResult; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.world.BlockChangeFlag; import org.spongepowered.common.block.SpongeBlockSnapshot; @@ -44,10 +42,10 @@ import org.spongepowered.common.bridge.world.level.LevelBridge; 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.effect.InteractionAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline; import java.util.Optional; @@ -59,16 +57,14 @@ */ public interface TrackedWorldBridge { - boolean bridge$forceSpawnEntity(Entity entity); - Optional bridge$startBlockChange(BlockPos pos, BlockState state, int rawFlags); /** * Delegates to the {@link ServerLevel} to perform the lookup for a {@link LevelChunk} * such that if the target {@link BlockPos} results in a {@code false} for - * {@link ServerLevel#isBlockLoaded(BlockPos)}, {@link BlockSnapshot#empty()} + * {@link ServerLevel#isLoaded(BlockPos)}, {@link BlockSnapshot#empty()} * will be returned. Likewise, optimizes the creation of the snapshot by performing - * the {@link LevelChunk#getBlockState(BlockPos)} and {@link LevelChunk#getTileEntity(BlockPos, Chunk.CreateEntityType)} + * the {@link LevelChunk#getBlockState(BlockPos)} and {@link LevelChunk#getBlockEntity(BlockPos, LevelChunk.EntityCreationType)} * lookup on the same chunk, avoiding an additional chunk lookup. * *

This should be used when the "known" {@link BlockState} for the target @@ -83,17 +79,13 @@ public interface TrackedWorldBridge { } /** - * Creates a {@link BlockSnapshot} but performs an additional {@link LevelChunk#getTileEntity(BlockPos, Chunk.CreateEntityType)} + * Creates a {@link BlockSnapshot} but performs an additional {@link LevelChunk#getBlockEntity(BlockPos, LevelChunk.EntityCreationType)} * lookup if the providing {@link BlockState#getBlock()} {@code instanceof} is * {@code true} for being an {@link EntityBlock} or * {@link BlockStateBridge#bridge$hasTileEntity()}, and associates * the resulting snapshot of said Tile with the snapshot. This is useful for in-progress * snapshot creation during transaction building for {@link TransactionalCaptureSupplier}. * - *

If the {@link BlockEntity} is already known, and no lookups are needed, use - * {@link #bridge$createSnapshotWithEntity(BlockState, BlockPos, BlockChangeFlag, BlockEntity)} as it avoids - * any further chunk lookups.

- * * @param state The block state * @param pos The target position * @param updateFlag The update flag @@ -101,24 +93,11 @@ public interface TrackedWorldBridge { */ SpongeBlockSnapshot bridge$createSnapshot(BlockState state, BlockPos pos, BlockChangeFlag updateFlag); - /** - * Similar to {@link #bridge$createSnapshot(BlockState, BlockPos, BlockChangeFlag)}, - * but with the added avoidance of a {@link BlockEntity} lookup during the creation of the resulting - * {@link SpongeBlockSnapshot}. - * - * @param state The state - * @param pos The position - * @param updateFlag The update flag - * @param tileEntity The tile entity to serialize, if available - * @return The snapshot, never NONE - */ - SpongeBlockSnapshot bridge$createSnapshotWithEntity(BlockState state, BlockPos pos, BlockChangeFlag updateFlag, @Nullable BlockEntity tileEntity); - - UseItemOnBlockPipeline bridge$startInteractionUseOnChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); + InteractionPipeline<@NonNull InteractionAtArgs> bridge$startInteractionUseOnChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); - UseBlockPipeline bridge$startInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); + InteractionPipeline<@NonNull InteractionAtArgs> bridge$startInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack); - UseItemAtPipeline bridge$startItemInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative); + InteractionPipeline<@NonNull UseItemAtArgs> 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); + InteractionPipeline<@NonNull UseItemArgs> bridge$startItemInteractionUseChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack); } 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 57af8e795a9..59a90650401 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 @@ -27,9 +27,9 @@ import net.minecraft.world.InteractionResult; 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.UseBlockPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; -public final class InteractionItemEffect implements ProcessingSideEffect.Simple { +public final class InteractionItemEffect implements ProcessingSideEffect.Simple, InteractionAtArgs, InteractionResult> { 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, InteractionAtArgs args + InteractionPipeline 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 0400b726f92..c6180c95510 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 @@ -27,9 +27,9 @@ import net.minecraft.world.InteractionResult; 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.InteractionPipeline; -public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect { +public final class InteractionUseItemOnBlockEffect implements ProcessingSideEffect, InteractionResult, InteractionAtArgs, InteractionResult> { 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, InteractionResult oldState, InteractionAtArgs args + InteractionPipeline pipeline, InteractionResult 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/UseItemAtEffect.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java index 2f7dc7ea299..5f1f031232f 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/effect/UseItemAtEffect.java @@ -28,9 +28,9 @@ 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.UseItemAtPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; -public class UseItemAtEffect implements ProcessingSideEffect.Simple { +public class UseItemAtEffect implements ProcessingSideEffect.Simple, UseItemAtArgs, InteractionResult> { private static final class Holder { static final UseItemAtEffect INSTANCE = new UseItemAtEffect(); @@ -45,7 +45,7 @@ public static UseItemAtEffect getInstance() { @Override public EffectResult processSideEffect( - UseItemAtPipeline pipeline, InteractionResult oldState, UseItemAtArgs args + InteractionPipeline pipeline, InteractionResult oldState, UseItemAtArgs args ) { final var stack = args.copiedStack(); final InteractionResult result; 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 9a102746cc4..05062274d74 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 @@ -27,9 +27,9 @@ import net.minecraft.world.InteractionResult; 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; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; -public class UseItemEffect implements ProcessingSideEffect.Simple { +public class UseItemEffect implements ProcessingSideEffect.Simple, UseItemArgs, InteractionResult> { private static final class Holder { static final UseItemEffect INSTANCE = new UseItemEffect(); @@ -44,7 +44,7 @@ public static UseItemEffect getInstance() { @Override public EffectResult processSideEffect( - UseItemPipeline pipeline, InteractionResult oldState, UseItemArgs args + InteractionPipeline pipeline, InteractionResult oldState, UseItemArgs args ) { final var gameMode = args.gameMode(); final InteractionResult result = gameMode.useItem(args.player(), args.world(), args.copiedStack(), args.hand()); 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 index 6bb8c06583c..6b7fe2aa6d0 100644 --- 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 @@ -25,7 +25,6 @@ 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; @@ -48,7 +47,7 @@ public void associateSideEffectEvents(E event, Stream elements) { @Override public void finalizeSideEffects(E post) { // This finalizes the list to be immutable - ((AbstractCompositeEvent) post).postInit(); + ((AbstractCompositeEvent) post).postInit(); } public void pushCause(CauseStackManager.StackFrame frame, E e) { @@ -59,9 +58,12 @@ public void pushCause(CauseStackManager.StackFrame frame, E e) { public boolean markCancelledTransactions( final E event, final ImmutableList> gameTransactions) { + if (!event.isCancelled()) { + return false; + } event.setCancelled(true); gameTransactions.forEach(GameTransaction::markCancelled); - return false; + return true; } } diff --git a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/InteractionPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/InteractionPipeline.java new file mode 100644 index 00000000000..cf25fc06e20 --- /dev/null +++ b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/InteractionPipeline.java @@ -0,0 +1,32 @@ +package org.spongepowered.common.event.tracking.context.transaction.pipeline; + +import net.minecraft.world.InteractionResult; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.common.event.tracking.PhaseContext; +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.ProcessingSideEffect; + +import java.util.Objects; + +public record InteractionPipeline<@NonNull A extends ProcessingSideEffect.Args>( + A args, + InteractionResult defaultResult, + ProcessingSideEffect, InteractionResult, A, InteractionResult> effect, + TransactionalCaptureSupplier transactor +) { + + public InteractionResult processInteraction(final PhaseContext context) { + var result = this.defaultResult; + final ResultingTransactionBySideEffect, InteractionResult, A, InteractionResult> resultingEffect = new ResultingTransactionBySideEffect<>(this.effect); + try (final var ignored = context.getTransactor().pushEffect(resultingEffect)) { + final var effectResult = this.effect.processSideEffect(this, result, this.args); + if (effectResult.hasResult) { + final @Nullable InteractionResult resultingState = effectResult.resultingState; + result = Objects.requireNonNullElse(resultingState, result); + } + } + return result; + } +} 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 deleted file mode 100644 index ac84e89cf0b..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseBlockPipeline.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.level.block.state.BlockState; -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.InteractionAtArgs; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; - -import java.util.List; -import java.util.Objects; - -public class UseBlockPipeline { - - private final ServerLevel worldIn; - private final ServerPlayer player; - private final InteractionHand hand; - private final BlockHitResult blockRaytraceResult; - private final BlockState blockstate; - private final ItemStack copiedStack; - private final List> effects; - private final TransactionalCaptureSupplier transactor; - - - public UseBlockPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - BlockHitResult blockRaytraceResultIn, - BlockState blockstate, - ItemStack copiedStack, - final TransactionalCaptureSupplier transactor) { - - this.worldIn = worldIn; - this.player = playerIn; - this.hand = handIn; - this.blockRaytraceResult = blockRaytraceResultIn; - this.blockstate = blockstate; - this.copiedStack = copiedStack; - this.effects = List.of( - new ResultingTransactionBySideEffect<>(InteractionItemEffect.getInstance()) - ); - this.transactor = transactor; - } - - public InteractionResult processInteraction(PhaseContext context) { - InteractionResult interaction = InteractionResult.PASS; - for (final var effect : this.effects) { - try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - 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, - 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/UseItemAtPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java deleted file mode 100644 index a9606f31c03..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemAtPipeline.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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) { - InteractionResult 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 deleted file mode 100644 index c48d9e1865e..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemOnBlockPipeline.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.level.block.state.BlockState; -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.InteractionAtArgs; -import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionUseItemOnBlockEffect; - -import java.util.List; -import java.util.Objects; - -public final class UseItemOnBlockPipeline { - - private final ServerLevel worldIn; - private final ServerPlayer player; - private final InteractionHand hand; - private final BlockHitResult blockRaytraceResult; - private final BlockState blockstate; - private final ItemStack copiedStack; - private final List> effects; - private final TransactionalCaptureSupplier transactor; - - - public UseItemOnBlockPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - BlockHitResult blockRaytraceResultIn, - BlockState blockstate, - ItemStack copiedStack, - final TransactionalCaptureSupplier transactor) { - - this.worldIn = worldIn; - this.player = playerIn; - this.hand = handIn; - this.blockRaytraceResult = blockRaytraceResultIn; - this.blockstate = blockstate; - this.copiedStack = copiedStack; - this.effects = List.of( - new ResultingTransactionBySideEffect<>(InteractionUseItemOnBlockEffect.getInstance()) - ); - this.transactor = transactor; - } - - public InteractionResult processInteraction(PhaseContext context) { - InteractionResult interaction = InteractionResult.TRY_WITH_EMPTY_HAND; - for (final var effect : this.effects) { - try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) { - 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, - 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/UseItemPipeline.java b/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java deleted file mode 100644 index 67e57baa368..00000000000 --- a/src/main/java/org/spongepowered/common/event/tracking/context/transaction/pipeline/UseItemPipeline.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 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.UseItemArgs; -import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemEffect; - -import java.util.List; -import java.util.Objects; - -public class UseItemPipeline { - - private final ServerLevel worldIn; - private final ServerPlayer player; - private final InteractionHand hand; - private final ItemStack copiedStack; - private final List> effects; - private final TransactionalCaptureSupplier transactor; - - public UseItemPipeline(ServerLevel worldIn, - ServerPlayer playerIn, - InteractionHand handIn, - ItemStack copiedStack, - final TransactionalCaptureSupplier transactor) { - - this.worldIn = worldIn; - this.player = playerIn; - this.hand = handIn; - this.copiedStack = copiedStack; - this.effects = List.of( - new ResultingTransactionBySideEffect<>(UseItemEffect.getInstance()) - ); - this.transactor = transactor; - } - - public InteractionResult processInteraction(PhaseContext context) { - InteractionResult 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.copiedStack, this.player.gameMode); - 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/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 5abcff4bb6e..37ffb643799 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 @@ -37,6 +37,7 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; @@ -97,6 +98,9 @@ import org.spongepowered.common.event.tracking.context.transaction.block.RemoveBlockEntity; import org.spongepowered.common.event.tracking.context.transaction.effect.CheckBlockPostPlacementIsSameEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionItemEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.InteractionUseItemOnBlockEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.NotifyClientEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.NotifyNeighborSideEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.PerformBlockDropsFromDestruction; @@ -105,15 +109,16 @@ import org.spongepowered.common.event.tracking.context.transaction.effect.UpdateConnectingBlocksEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.UpdateLightSideEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.UpdateWorldRendererEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtArgs; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemAtEffect; +import org.spongepowered.common.event.tracking.context.transaction.effect.UseItemEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.WorldBlockChangeCompleteEffect; import org.spongepowered.common.event.tracking.context.transaction.effect.WorldDestroyBlockLevelEffect; import org.spongepowered.common.event.tracking.context.transaction.pipeline.ChunkPipeline; +import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractionPipeline; 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; import org.spongepowered.common.event.tracking.phase.general.GeneralPhase; import org.spongepowered.common.event.tracking.phase.tick.TickPhase; @@ -585,36 +590,38 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable } @Override - public UseItemOnBlockPipeline bridge$startInteractionUseOnChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { + public InteractionPipeline bridge$startInteractionUseOnChange( + net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, + BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack + ) { final var instance = this.tracker$validateServerThread(); if (instance == null) { return null; } - return new UseItemOnBlockPipeline( - (ServerLevel) worldIn, - playerIn, - handIn, - blockRaytraceResultIn, - blockstate, - copiedStack, + final var args = new InteractionAtArgs(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); + return new InteractionPipeline<>( + args, + InteractionResult.TRY_WITH_EMPTY_HAND, + InteractionUseItemOnBlockEffect.getInstance(), instance.getPhaseContext().getTransactor() - ); + ); } @Override - public UseBlockPipeline bridge$startInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack) { + public InteractionPipeline bridge$startInteractionChange( + net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, + BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack + ) { final var instance = this.tracker$validateServerThread(); if (instance == null) { return null; } - return new UseBlockPipeline( - (ServerLevel) worldIn, - playerIn, - handIn, - blockRaytraceResultIn, - blockstate, - copiedStack, + final var args = new InteractionAtArgs(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); + return new InteractionPipeline( + args, + InteractionResult.PASS, + InteractionItemEffect.getInstance(), instance.getPhaseContext().getTransactor() ); } @@ -627,7 +634,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (this.bridge$isFake()) { return null; } - final var instance = PhaseTracker.getInstance(); + final var instance = PhaseTracker.getWorldInstance(this); if (instance.getSidedThread() != PhaseTracker.getServerInstanceExplicitly().getSidedThread() && instance != PhaseTracker.getServerInstanceExplicitly()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } @@ -635,35 +642,31 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable } @Override - public UseItemAtPipeline bridge$startItemInteractionChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative) { + public InteractionPipeline bridge$startItemInteractionChange( + net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, + ItemStack copiedStack, BlockHitResult blockRaytraceResult, boolean creative + ) { final var instance = this.tracker$validateServerThread(); if (instance == null) { return null; } - return new UseItemAtPipeline( - (ServerLevel) worldIn, - playerIn, - handIn, - copiedStack, - blockRaytraceResult, - creative, + final var args = new UseItemAtArgs(worldIn, playerIn,handIn, blockRaytraceResult, copiedStack, creative); + return new InteractionPipeline<>( + args, + InteractionResult.PASS, + UseItemAtEffect.getInstance(), instance.getPhaseContext().getTransactor() ); } @Override - public UseItemPipeline bridge$startItemInteractionUseChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack) { + public InteractionPipeline bridge$startItemInteractionUseChange(net.minecraft.world.level.Level worldIn, ServerPlayer playerIn, InteractionHand handIn, ItemStack copiedStack) { final var instance = this.tracker$validateServerThread(); if (instance == null) { return null; } - return new UseItemPipeline( - (ServerLevel) worldIn, - playerIn, - handIn, - copiedStack, - instance.getPhaseContext().getTransactor() - ); + final var args = new UseItemArgs(worldIn, playerIn, handIn, copiedStack, playerIn.gameMode); + return new InteractionPipeline<>(args, InteractionResult.PASS, UseItemEffect.getInstance(), instance.getPhaseContext().getTransactor()); } /** 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 523170ece67..831a595eb4f 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 @@ -68,7 +68,7 @@ public abstract class ServerPlayerGameModeMixin_Tracker { @Shadow @Final protected ServerPlayer player; - @Shadow protected net.minecraft.server.level.ServerLevel level; + @Shadow protected ServerLevel level; @Shadow private GameType gameModeForPlayer; @Shadow public abstract boolean shadow$isCreative(); @@ -119,6 +119,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl final MenuProvider inamedcontainerprovider = blockstate.getMenuProvider(worldIn, blockpos); if (inamedcontainerprovider != null) { playerIn.openMenu(inamedcontainerprovider); + // Sponge start - throw open container event final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); try (final CauseStackManager.StackFrame blockHit = PhaseTracker.getCauseStackManager().pushCauseFrame()) { @@ -129,7 +130,8 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl return InteractionResult.SUCCESS; } } - return InteractionResult.SUCCESS; + // Sponge end + return InteractionResult.CONSUME; } else { return InteractionResult.PASS; } @@ -148,11 +150,13 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl return itemInteract; } if (itemInteract instanceof InteractionResult.TryEmptyHandInteraction && handIn == InteractionHand.MAIN_HAND) { + // Sponge Start - use interaction pipeline final AbstractContainerMenu lastOpenContainer = playerIn.containerMenu; // Sponge final var interaction = ((TrackedWorldBridge) level).bridge$startInteractionChange(worldIn, playerIn, handIn, blockRaytraceResultIn, blockstate, copiedStack); final var result = interaction.processInteraction(phaseContext); + // Sponge end if (result.consumesAction()) { - // Sponge Start + // Sponge Start - verify opened container is not changed, otherwise throw an event if (lastOpenContainer != playerIn.containerMenu) { final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); @@ -170,18 +174,19 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl CriteriaTriggers.DEFAULT_BLOCK_USE.trigger(playerIn, blockpos); return result; } - } } if (!stackIn.isEmpty() && !playerIn.getCooldowns().isOnCooldown(stackIn)) { - // Sponge start + // Sponge start - verify event derived tristate if (useItem == Tristate.FALSE) { ((ServerPlayerGameModeBridge) this).bridge$setInteractBlockRightClickCancelled(true); return InteractionResult.PASS; } + // Sponge - run interaction through final var interaction = ((TrackedWorldBridge) level).bridge$startItemInteractionChange(worldIn, playerIn, handIn, copiedStack, blockRaytraceResultIn, this.shadow$isCreative()); final var result = interaction.processInteraction(phaseContext); + // Sponge end if (result.consumesAction()) {