Skip to content

Commit

Permalink
!feat: Refactor Interactions to use Transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
gabizou committed Apr 21, 2024
1 parent 7348084 commit f3249bc
Show file tree
Hide file tree
Showing 50 changed files with 770 additions and 3,949 deletions.
3,669 changes: 0 additions & 3,669 deletions gradle/verification-metadata.xml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@

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.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.spongepowered.api.block.BlockSnapshot;
import org.spongepowered.api.world.BlockChangeFlag;
Expand All @@ -41,6 +46,7 @@
import org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge;
import org.spongepowered.common.event.tracking.PhaseContext;
import org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier;
import org.spongepowered.common.event.tracking.context.transaction.pipeline.InteractItemPipeline;
import org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline;

import java.util.Optional;
Expand Down Expand Up @@ -111,4 +117,5 @@ public interface TrackedWorldBridge {
*/
SpongeBlockSnapshot bridge$createSnapshotWithEntity(BlockState state, BlockPos pos, BlockChangeFlag updateFlag, @Nullable BlockEntity tileEntity);

InteractItemPipeline bridge$startInteractionChange(Level worldIn, ServerPlayer playerIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, BlockState blockstate, ItemStack copiedStack);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@
import java.util.Deque;

public class EffectTransactor implements AutoCloseable {
final @Nullable ResultingTransactionBySideEffect previousEffect;
final @Nullable ResultingTransactionBySideEffect<?, ?, ?, ?> previousEffect;
public final @Nullable GameTransaction<@NonNull ?> parent;
private final TransactionalCaptureSupplier supplier;
private final ResultingTransactionBySideEffect effect;
private final ResultingTransactionBySideEffect<?, ?, ?, ?> effect;

EffectTransactor(final ResultingTransactionBySideEffect effect, final @Nullable GameTransaction<@NonNull ?> parent,
final @Nullable ResultingTransactionBySideEffect previousEffect, final TransactionalCaptureSupplier transactor) {
EffectTransactor(final ResultingTransactionBySideEffect<?, ?, ?, ?> effect, final @Nullable GameTransaction<@NonNull ?> parent,
final @Nullable ResultingTransactionBySideEffect<?, ?, ?, ?> previousEffect, final TransactionalCaptureSupplier transactor) {
/*
| ChangeBlock(1) <- head will be RemoveTileEntity(1), tail is still RemoveTileentity(1)
| |- RemoveTileEntity <- Head will be ChangeBlock(2) tail is still ChangeBlock(2)
Expand All @@ -55,7 +55,7 @@ public void close() {
&& this.parent.sideEffects != null
&& this.parent.getEffects().peekLast() == this.effect
) {
final Deque<ResultingTransactionBySideEffect> effects = this.parent.getEffects();
final Deque<ResultingTransactionBySideEffect<?, ?, ?, ?>> effects = this.parent.getEffects();
effects.removeLast();
if (effects.isEmpty()) {
this.parent.sideEffects = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public abstract class GameTransaction<E extends Event & Cancellable> implements
protected boolean cancelled = false;

// Children Definitions
@Nullable LinkedList<ResultingTransactionBySideEffect> sideEffects;
@Nullable LinkedList<ResultingTransactionBySideEffect<?, ?, ?, ?>> sideEffects;

// LinkedList node definitions
@Nullable GameTransaction<@NonNull ?> previous;
Expand All @@ -75,14 +75,14 @@ public final TransactionType<? extends E> getTransactionType() {
return this.transactionType;
}

final Deque<ResultingTransactionBySideEffect> getEffects() {
final Deque<ResultingTransactionBySideEffect<?, ?, ?, ?>> getEffects() {
if (this.sideEffects == null) {
this.sideEffects = new LinkedList<>();
}
return this.sideEffects;
}

public final void addLast(final ResultingTransactionBySideEffect effect) {
public final void addLast(final ResultingTransactionBySideEffect<?, ?, ?, ?> effect) {
if (this.sideEffects == null) {
this.sideEffects = new LinkedList<>();
}
Expand All @@ -97,7 +97,7 @@ public final boolean hasAnyPrimaryChildrenTransactions() {
if (this.sideEffects == null) {
return false;
}
for (final ResultingTransactionBySideEffect sideEffect : this.sideEffects) {
for (final ResultingTransactionBySideEffect<?, ?, ?, ?> sideEffect : this.sideEffects) {
@Nullable GameTransaction<@NonNull ?> transaction = sideEffect.head;
while (transaction != null) {
if (transaction.transactionType.isPrimary() || transaction.hasChildTransactions()) {
Expand Down Expand Up @@ -131,10 +131,17 @@ public abstract Optional<E> generateEvent(
public final void markCancelled() {
this.cancelled = true;
this.childIterator().forEachRemaining(GameTransaction::markCancelled);
if (this.next != null && this.next.hasUnknownChainRequiringCancellation()) {
this.next.markCancelled();
}
}

public abstract boolean markCancelledTransactions(E event, ImmutableList<? extends GameTransaction<E>> transactions);

protected boolean hasUnknownChainRequiringCancellation() {
return false;
}

public void postProcessEvent(final PhaseContext<@NonNull ?> context, final E event) {

}
Expand Down Expand Up @@ -183,16 +190,16 @@ protected void captureState() {
}

private static class ChildIterator implements Iterator<GameTransaction<@NonNull ?>> {
private final Iterator<ResultingTransactionBySideEffect> effectIterator;
private final Iterator<ResultingTransactionBySideEffect<?, ?, ?, ?>> effectIterator;
private @Nullable GameTransaction<@NonNull ?> cachedNext;
private @MonotonicNonNull GameTransaction<@NonNull ?> pointer;
private boolean hasNoRemainingElements = false;

ChildIterator(final Iterator<ResultingTransactionBySideEffect> iterator) {
ChildIterator(final Iterator<ResultingTransactionBySideEffect<?, ?, ?, ?>> iterator) {
// We're going to search the iterator's effects until we find the first at least
this.effectIterator = iterator;
while (this.effectIterator.hasNext()) {
final ResultingTransactionBySideEffect next = this.effectIterator.next();
final ResultingTransactionBySideEffect<?, ?, ?, ?> next = this.effectIterator.next();
if (next.head != null) {
this.cachedNext = next.head;
this.pointer = next.head;
Expand All @@ -219,7 +226,7 @@ public boolean hasNext() {
// start search for the next, sadly because effects don't make a clean chain,
// there can be many effects with no transactions recorded
while (this.effectIterator.hasNext()) {
final ResultingTransactionBySideEffect next = this.effectIterator.next();
final ResultingTransactionBySideEffect<?, ?, ?, ?> next = this.effectIterator.next();
if (next.head != null) {
this.cachedNext = next.head;
return true;
Expand Down Expand Up @@ -250,16 +257,16 @@ public boolean hasNext() {


private static class ReverseChildIterator implements Iterator<GameTransaction<@NonNull ?>> {
private final Iterator<ResultingTransactionBySideEffect> effectIterator;
private final Iterator<ResultingTransactionBySideEffect<?, ?, ?, ?>> effectIterator;
private @Nullable GameTransaction<@NonNull ?> cachedPrevious;
private @MonotonicNonNull GameTransaction<@NonNull ?> pointer;
private boolean hasNoRemainingElements = false;

ReverseChildIterator(final Iterator<ResultingTransactionBySideEffect> iterator) {
ReverseChildIterator(final Iterator<ResultingTransactionBySideEffect<?, ?, ?, ?>> iterator) {
// We're going to search the iterator's effects until we find the first at least
this.effectIterator = iterator;
while (this.effectIterator.hasNext()) {
final ResultingTransactionBySideEffect next = this.effectIterator.next();
final ResultingTransactionBySideEffect<?, ?, ?, ?> next = this.effectIterator.next();
if (next.tail != null) {
this.pointer = next.tail;
this.cachedPrevious = next.tail;
Expand Down Expand Up @@ -287,7 +294,7 @@ public boolean hasNext() {
// start search for the next, sadly because effects don't make a clean chain,
// there can be many effects with no transactions recorded
while (this.effectIterator.hasNext()) {
final ResultingTransactionBySideEffect next = this.effectIterator.next();
final ResultingTransactionBySideEffect<?, ?, ?, ?> next = this.effectIterator.next();
if (next.tail != null) {
this.cachedPrevious = next.tail;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
import java.util.Iterator;
import java.util.Optional;

public class ResultingTransactionBySideEffect {
public final ProcessingSideEffect effect;
public class ResultingTransactionBySideEffect<T, C, A extends ProcessingSideEffect.Args, @Nullable R> {
public final ProcessingSideEffect<T, C, A, @Nullable R> effect;
@Nullable GameTransaction<@NonNull ?> head;
@Nullable GameTransaction<@NonNull ?> tail;

public ResultingTransactionBySideEffect(final ProcessingSideEffect effect) {
public ResultingTransactionBySideEffect(final ProcessingSideEffect<T, C, A, @Nullable R> effect) {
this.effect = effect;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
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;
Expand All @@ -45,12 +46,14 @@
import net.minecraft.world.ticks.ScheduledTick;
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.entity.SpawnType;
import org.spongepowered.api.item.inventory.Inventory;
import org.spongepowered.api.item.inventory.ItemStackSnapshot;
import org.spongepowered.api.item.inventory.Slot;
import org.spongepowered.api.item.inventory.crafting.CraftingInventory;
import org.spongepowered.api.item.inventory.transaction.SlotTransaction;
import org.spongepowered.api.util.Direction;
import org.spongepowered.api.world.BlockChangeFlag;
import org.spongepowered.api.world.BlockChangeFlags;
import org.spongepowered.common.SpongeCommon;
Expand All @@ -72,6 +75,7 @@
import org.spongepowered.common.event.tracking.context.transaction.effect.EntityPerformingDropsEffect;
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;
import org.spongepowered.common.event.tracking.context.transaction.inventory.ClickCreativeMenuTransaction;
import org.spongepowered.common.event.tracking.context.transaction.inventory.ClickMenuTransaction;
import org.spongepowered.common.event.tracking.context.transaction.inventory.CloseMenuTransaction;
Expand All @@ -80,6 +84,7 @@
import org.spongepowered.common.event.tracking.context.transaction.inventory.CraftingTransaction;
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.InventoryTransaction;
import org.spongepowered.common.event.tracking.context.transaction.inventory.OpenMenuTransaction;
import org.spongepowered.common.event.tracking.context.transaction.inventory.PlaceRecipeTransaction;
Expand All @@ -97,6 +102,7 @@
import org.spongepowered.common.world.BlockChange;
import org.spongepowered.common.world.SpongeBlockChangeFlag;
import org.spongepowered.common.world.volume.VolumeStreamUtils;
import org.spongepowered.math.vector.Vector3d;

import java.lang.ref.WeakReference;
import java.util.Objects;
Expand All @@ -121,7 +127,7 @@ interface TransactionSink {
@Deprecated
void logTransaction(StatefulTransaction transaction);

EffectTransactor pushEffect(final ResultingTransactionBySideEffect effect);
<T, C, A extends ProcessingSideEffect.Args, @Nullable R> EffectTransactor pushEffect(final ResultingTransactionBySideEffect<T, C, A, R> effect);

default ChangeBlock logBlockChange(final SpongeBlockSnapshot originalBlockSnapshot, final BlockState newState,
final BlockChangeFlag flags
Expand Down Expand Up @@ -174,7 +180,7 @@ default EffectTransactor logBlockDrops(
original.blockChange = BlockChange.MODIFY;
final PrepareBlockDropsTransaction transaction = new PrepareBlockDropsTransaction(pos, state, original);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(PrepareBlockDrops.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(PrepareBlockDrops.getInstance()));
}

@SuppressWarnings("ConstantConditions")
Expand Down Expand Up @@ -258,7 +264,7 @@ default boolean logTileRemoval(final @Nullable BlockEntity tileentity, final Sup
final EntityPerformingDropsTransaction transaction = new EntityPerformingDropsTransaction(entity);
this.logTransaction(transaction);
if (transaction.recorded()) {
return this.pushEffect(new ResultingTransactionBySideEffect(EntityPerformingDropsEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(EntityPerformingDropsEffect.getInstance()));
}
return null;
}
Expand Down Expand Up @@ -334,44 +340,44 @@ default EffectTransactor logClickContainer(
final ClickMenuTransaction transaction = new ClickMenuTransaction(
player, menu, slotNum, buttonNum, clickType, slot, ItemStackUtil.snapshotOf(player.containerMenu.getCarried()));
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}

default EffectTransactor logPlayerInventoryChangeWithEffect(final Player player, final PlayerInventoryTransaction.EventCreator eventCreator) {
final PlayerInventoryTransaction transaction = new PlayerInventoryTransaction(player, eventCreator);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}

default EffectTransactor logCreativeClickContainer(final int slotNum, final ItemStackSnapshot creativeStack, final Player player) {
final ClickCreativeMenuTransaction transaction = new ClickCreativeMenuTransaction(player, slotNum, creativeStack);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}


default EffectTransactor logDropFromPlayerInventory(final ServerPlayer player, final boolean dropAll) {
final DropFromPlayerInventoryTransaction transaction = new DropFromPlayerInventoryTransaction(player, dropAll);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}

default EffectTransactor logOpenInventory(final Player player) {
final OpenMenuTransaction transaction = new OpenMenuTransaction(player);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}

default EffectTransactor logCloseInventory(final Player player, final boolean clientSource) {
final CloseMenuTransaction transaction = new CloseMenuTransaction(player, clientSource);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}

default EffectTransactor logPlaceRecipe(final boolean shift, final RecipeHolder<Recipe<?>> recipe, final ServerPlayer player, final CraftingInventory craftInv) {
final PlaceRecipeTransaction transaction = new PlaceRecipeTransaction(player, shift, recipe, craftInv);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}

default void logSelectTrade(final ServerPlayer player, final int item) {
Expand Down Expand Up @@ -403,12 +409,20 @@ default void logCrafting(final Player player, @Nullable final ItemStack craftedS
default EffectTransactor logIgnoredInventory(AbstractContainerMenu containerMenu) {
final ExplicitInventoryOmittedTransaction transaction = new ExplicitInventoryOmittedTransaction(containerMenu);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}

default EffectTransactor logInventoryTransaction(final AbstractContainerMenu containerMenu) {
final InventoryTransaction transaction = new InventoryTransaction((Inventory) containerMenu);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()));
return this.pushEffect(new ResultingTransactionBySideEffect<>(InventoryEffect.getInstance()));
}

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);
this.logTransaction(transaction);
}

}
Loading

0 comments on commit f3249bc

Please sign in to comment.