Search in sources :

Example 6 with AbstractSlot

use of org.lanternpowered.server.inventory.AbstractSlot in project LanternServer by LanternPowered.

the class VanillaContainerInteractionBehavior method handleNumberKey.

@Override
public void handleNumberKey(ClientContainer clientContainer, ClientSlot clientSlot, int number) {
    if (clientContainer.getPlayer() != this.container.getPlayerInventory().getCarrier().orElse(null) || !(clientSlot instanceof ClientSlot.Slot)) {
        return;
    }
    final ClientSlot hotbarSlot = clientContainer.getClientSlot(clientContainer.getHotbarSlotIndex(number - 1)).orElseThrow(() -> new IllegalStateException("Missing hotbar client slot: " + number));
    if (!(hotbarSlot instanceof ClientSlot.Slot)) {
        return;
    }
    final AbstractSlot slot1 = ((ClientSlot.Slot) clientSlot).getSlot();
    final AbstractSlot hotbarSlot1 = ((ClientSlot.Slot) hotbarSlot).getSlot();
    if (slot1 != hotbarSlot1) {
        final List<SlotTransaction> transactions = new ArrayList<>();
        final Transaction<ItemStackSnapshot> cursorTransaction;
        if (getCursorItem() == null) {
            cursorTransaction = new Transaction<>(ItemStackSnapshot.NONE, ItemStackSnapshot.NONE);
            final ItemStack itemStack = slot1.getRawItemStack();
            final ItemStack hotbarItemStack = hotbarSlot1.getRawItemStack();
            final ItemStackSnapshot itemStackSnapshot = LanternItemStack.toSnapshot(itemStack);
            final ItemStackSnapshot hotbarItemStackSnapshot = LanternItemStack.toSnapshot(hotbarItemStack);
            if (!(itemStackSnapshot != ItemStackSnapshot.NONE && (!hotbarSlot1.isValidItem(itemStack) || itemStackSnapshot.getQuantity() > hotbarSlot1.getMaxStackSize())) && !(hotbarItemStackSnapshot != ItemStackSnapshot.NONE && (!slot1.isValidItem(hotbarItemStack) || hotbarItemStack.getQuantity() > slot1.getMaxStackSize()))) {
                transactions.add(new SlotTransaction(slot1, itemStackSnapshot, hotbarItemStackSnapshot));
                transactions.add(new SlotTransaction(hotbarSlot1, hotbarItemStackSnapshot, itemStackSnapshot));
            }
        } else {
            final ItemStackSnapshot cursorItem = getCursorItem().createSnapshot();
            cursorTransaction = new Transaction<>(cursorItem, cursorItem);
        }
        final CauseStack causeStack = CauseStack.current();
        final ClickInventoryEvent.NumberPress event = SpongeEventFactory.createClickInventoryEventNumberPress(causeStack.getCurrentCause(), cursorTransaction, this.container, this.container.transformSlots(transactions), number - 1);
        finishInventoryEvent(event);
    }
}
Also used : CauseStack(org.lanternpowered.server.event.CauseStack) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) ArrayList(java.util.ArrayList) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) OutputSlot(org.spongepowered.api.item.inventory.slot.OutputSlot) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) AbstractInventorySlot(org.lanternpowered.server.inventory.AbstractInventorySlot) Slot(org.spongepowered.api.item.inventory.Slot) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) LanternItemStackSnapshot(org.lanternpowered.server.inventory.LanternItemStackSnapshot) ItemStack(org.spongepowered.api.item.inventory.ItemStack) LanternItemStack(org.lanternpowered.server.inventory.LanternItemStack)

Example 7 with AbstractSlot

use of org.lanternpowered.server.inventory.AbstractSlot in project LanternServer by LanternPowered.

the class VanillaContainerInteractionBehavior method handleCreativeClick.

@Override
public void handleCreativeClick(ClientContainer clientContainer, @Nullable ClientSlot clientSlot, @Nullable ItemStack itemStack) {
    final LanternPlayer player = clientContainer.getPlayer();
    final CauseStack causeStack = CauseStack.current();
    if (clientSlot == null) {
        if (itemStack != null) {
            causeStack.addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
            LanternEventHelper.handleDroppedItemSpawning(player.getTransform(), itemStack.createSnapshot());
        }
    } else if (clientSlot instanceof ClientSlot.Slot) {
        final AbstractSlot slot = ((ClientSlot.Slot) clientSlot).getSlot();
        final PeekedSetTransactionResult result = slot.peekSet(itemStack);
        // We do not know the remaining stack in the cursor,
        // so just use none as new item
        final Transaction<ItemStackSnapshot> cursorTransaction = new Transaction<>(LanternItemStack.toSnapshot(itemStack), ItemStackSnapshot.NONE);
        final ClickInventoryEvent.Creative event = SpongeEventFactory.createClickInventoryEventCreative(causeStack.getCurrentCause(), cursorTransaction, this.container, this.container.transformSlots(result.getTransactions()));
        finishInventoryEvent(event);
    }
}
Also used : CauseStack(org.lanternpowered.server.event.CauseStack) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Transaction(org.spongepowered.api.data.Transaction) PeekedSetTransactionResult(org.lanternpowered.server.inventory.PeekedSetTransactionResult) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) LanternPlayer(org.lanternpowered.server.entity.living.player.LanternPlayer)

Example 8 with AbstractSlot

use of org.lanternpowered.server.inventory.AbstractSlot in project LanternServer by LanternPowered.

the class VanillaContainerInteractionBehavior method handleDoubleClick.

@Override
public void handleDoubleClick(ClientContainer clientContainer, ClientSlot clientSlot) {
    final LanternPlayer player = clientContainer.getPlayer();
    if (player != this.container.getPlayerInventory().getCarrier().orElse(null) || !(clientSlot instanceof ClientSlot.Slot)) {
        return;
    }
    final AbstractSlot slot = ((ClientSlot.Slot) clientSlot).getSlot();
    final ItemStackSnapshot oldItem = LanternItemStack.toSnapshot(getCursorItem());
    ItemStackSnapshot newItem = oldItem;
    final List<SlotTransaction> transactions = new ArrayList<>();
    if (getCursorItem() != null && !(slot instanceof OutputSlot)) {
        final ItemStack cursorItem = getCursorItem().copy();
        int quantity = cursorItem.getQuantity();
        final int maxQuantity = cursorItem.getMaxStackQuantity();
        if (quantity < maxQuantity) {
            final AbstractInventory inventory;
            if (clientContainer instanceof PlayerClientContainer) {
                inventory = this.container.getPlayerInventory().getView(LanternPlayerInventory.View.ALL_PRIORITY_MAIN);
            } else {
                inventory = AbstractOrderedInventory.viewBuilder().inventory(this.container.getOpenInventory()).inventory(this.container.getPlayerInventory().getView(LanternPlayerInventory.View.PRIORITY_MAIN_AND_HOTBAR)).build();
            }
            // Try first to get enough unfinished stacks
            PeekedPollTransactionResult peekResult = inventory.peekPoll(maxQuantity - quantity, stack -> stack.getQuantity() < stack.getMaxStackQuantity() && ((LanternItemStack) cursorItem).similarTo(stack)).orElse(null);
            if (peekResult != null) {
                quantity += peekResult.getPolledItem().getQuantity();
                transactions.addAll(peekResult.getTransactions());
            }
            // Get the last items for the stack from a full stack
            if (quantity <= maxQuantity) {
                peekResult = this.container.peekPoll(maxQuantity - quantity, stack -> stack.getQuantity() >= stack.getMaxStackQuantity() && ((LanternItemStack) cursorItem).similarTo(stack)).orElse(null);
                if (peekResult != null) {
                    quantity += peekResult.getPolledItem().getQuantity();
                    transactions.addAll(peekResult.getTransactions());
                }
            }
            cursorItem.setQuantity(quantity);
            newItem = cursorItem.createSnapshot();
        }
    }
    final CauseStack causeStack = CauseStack.current();
    final Transaction<ItemStackSnapshot> cursorTransaction = new Transaction<>(oldItem, newItem);
    final ClickInventoryEvent.Double event = SpongeEventFactory.createClickInventoryEventDouble(causeStack.getCurrentCause(), cursorTransaction, this.container, this.container.transformSlots(transactions));
    finishInventoryEvent(event);
}
Also used : EventContextKeys(org.spongepowered.api.event.cause.EventContextKeys) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) LanternPlayerInventory(org.lanternpowered.server.inventory.vanilla.LanternPlayerInventory) LanternItemStackSnapshot(org.lanternpowered.server.inventory.LanternItemStackSnapshot) CraftingResult(org.spongepowered.api.item.recipe.crafting.CraftingResult) ItemStack(org.spongepowered.api.item.inventory.ItemStack) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) Transaction(org.spongepowered.api.data.Transaction) OutputSlot(org.spongepowered.api.item.inventory.slot.OutputSlot) ExtendedCraftingResult(org.lanternpowered.server.item.recipe.crafting.ExtendedCraftingResult) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) MatrixResult(org.lanternpowered.server.item.recipe.crafting.MatrixResult) Sponge(org.spongepowered.api.Sponge) CraftingGridInventory(org.spongepowered.api.item.inventory.crafting.CraftingGridInventory) Tuple(org.spongepowered.api.util.Tuple) Streams(com.google.common.collect.Streams) CraftingOutput(org.spongepowered.api.item.inventory.crafting.CraftingOutput) Collectors(java.util.stream.Collectors) Preconditions.checkState(com.google.common.base.Preconditions.checkState) List(java.util.List) Lantern(org.lanternpowered.server.game.Lantern) Transform(org.spongepowered.api.entity.Transform) GameMode(org.spongepowered.api.entity.living.player.gamemode.GameMode) ChangeInventoryEvent(org.spongepowered.api.event.item.inventory.ChangeInventoryEvent) CraftingInventory(org.spongepowered.api.item.inventory.crafting.CraftingInventory) World(org.spongepowered.api.world.World) Optional(java.util.Optional) AbstractOrderedInventory(org.lanternpowered.server.inventory.AbstractOrderedInventory) Player(org.spongepowered.api.entity.living.player.Player) LanternItemStack(org.lanternpowered.server.inventory.LanternItemStack) ClientContainer(org.lanternpowered.server.inventory.client.ClientContainer) IInventory(org.lanternpowered.server.inventory.IInventory) Keys(org.spongepowered.api.data.key.Keys) PeekedSetTransactionResult(org.lanternpowered.server.inventory.PeekedSetTransactionResult) GameModes(org.spongepowered.api.entity.living.player.gamemode.GameModes) ArrayList(java.util.ArrayList) CauseStack(org.lanternpowered.server.event.CauseStack) PlayerInventoryContainer(org.lanternpowered.server.inventory.PlayerInventoryContainer) LanternContainer(org.lanternpowered.server.inventory.LanternContainer) PlayerClientContainer(org.lanternpowered.server.inventory.client.PlayerClientContainer) LanternWorld(org.lanternpowered.server.world.LanternWorld) CraftingMatrix(org.lanternpowered.server.item.recipe.crafting.CraftingMatrix) Nullable(javax.annotation.Nullable) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) AbstractInventorySlot(org.lanternpowered.server.inventory.AbstractInventorySlot) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) LanternEventHelper(org.lanternpowered.server.event.LanternEventHelper) PeekedPollTransactionResult(org.lanternpowered.server.inventory.PeekedPollTransactionResult) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) Slot(org.spongepowered.api.item.inventory.Slot) Entity(org.spongepowered.api.entity.Entity) PeekedOfferTransactionResult(org.lanternpowered.server.inventory.PeekedOfferTransactionResult) SpawnTypes(org.spongepowered.api.event.cause.entity.spawn.SpawnTypes) LanternPlayer(org.lanternpowered.server.entity.living.player.LanternPlayer) LanternHotbarInventory(org.lanternpowered.server.inventory.vanilla.LanternHotbarInventory) AbstractInventory(org.lanternpowered.server.inventory.AbstractInventory) CauseStack(org.lanternpowered.server.event.CauseStack) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) ArrayList(java.util.ArrayList) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) LanternItemStack(org.lanternpowered.server.inventory.LanternItemStack) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) AbstractInventory(org.lanternpowered.server.inventory.AbstractInventory) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Transaction(org.spongepowered.api.data.Transaction) PlayerClientContainer(org.lanternpowered.server.inventory.client.PlayerClientContainer) PeekedPollTransactionResult(org.lanternpowered.server.inventory.PeekedPollTransactionResult) OutputSlot(org.spongepowered.api.item.inventory.slot.OutputSlot) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) AbstractInventorySlot(org.lanternpowered.server.inventory.AbstractInventorySlot) Slot(org.spongepowered.api.item.inventory.Slot) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) LanternItemStackSnapshot(org.lanternpowered.server.inventory.LanternItemStackSnapshot) OutputSlot(org.spongepowered.api.item.inventory.slot.OutputSlot) ItemStack(org.spongepowered.api.item.inventory.ItemStack) LanternItemStack(org.lanternpowered.server.inventory.LanternItemStack) LanternPlayer(org.lanternpowered.server.entity.living.player.LanternPlayer)

Example 9 with AbstractSlot

use of org.lanternpowered.server.inventory.AbstractSlot in project LanternServer by LanternPowered.

the class VanillaContainerInteractionBehavior method handleDrag.

@Override
public void handleDrag(ClientContainer clientContainer, List<ClientSlot> clientSlots, MouseButton mouseButton) {
    final LanternPlayer player = clientContainer.getPlayer();
    if (player != this.container.getPlayerInventory().getCarrier().orElse(null)) {
        return;
    }
    final List<AbstractSlot> slots = clientSlots.stream().filter(clientSlot -> clientSlot instanceof ClientSlot.Slot).map(clientSlot -> ((ClientSlot.Slot) clientSlot).getSlot()).collect(Collectors.toList());
    if (slots.size() != clientSlots.size()) {
        // TODO: Is this the behavior we want?
        return;
    }
    final ItemStack cursorItem = getCursorItem();
    if (cursorItem == null || cursorItem.isEmpty()) {
        return;
    }
    final CauseStack causeStack = CauseStack.current();
    if (mouseButton == MouseButton.LEFT) {
        final int quantity = cursorItem.getQuantity();
        final int slotCount = slots.size();
        final int itemsPerSlot = quantity / slotCount;
        final int rest = quantity - itemsPerSlot * slotCount;
        final List<SlotTransaction> transactions = new ArrayList<>();
        for (AbstractSlot slot : slots) {
            final ItemStack itemStack = cursorItem.copy();
            itemStack.setQuantity(itemsPerSlot);
            transactions.addAll(slot.peekOffer(itemStack).getTransactions());
        }
        ItemStackSnapshot newCursorItem = ItemStackSnapshot.NONE;
        if (rest > 0) {
            final ItemStack itemStack = cursorItem.copy();
            itemStack.setQuantity(rest);
            newCursorItem = LanternItemStackSnapshot.wrap(itemStack);
        }
        final ItemStackSnapshot oldCursorItem = cursorItem.createSnapshot();
        final Transaction<ItemStackSnapshot> cursorTransaction = new Transaction<>(oldCursorItem, newCursorItem);
        final ClickInventoryEvent.Drag.Primary event = SpongeEventFactory.createClickInventoryEventDragPrimary(causeStack.getCurrentCause(), cursorTransaction, this.container, transactions);
        finishInventoryEvent(event);
    } else if (mouseButton == MouseButton.RIGHT) {
        int quantity = cursorItem.getQuantity();
        final int size = Math.min(slots.size(), quantity);
        final List<SlotTransaction> transactions = new ArrayList<>();
        for (AbstractSlot slot : slots) {
            final ItemStack itemStack = cursorItem.copy();
            itemStack.setQuantity(1);
            transactions.addAll(slot.peekOffer(itemStack).getTransactions());
        }
        quantity -= size;
        ItemStackSnapshot newCursorItem = ItemStackSnapshot.NONE;
        if (quantity > 0) {
            final ItemStack itemStack = cursorItem.copy();
            itemStack.setQuantity(quantity);
            newCursorItem = LanternItemStackSnapshot.wrap(itemStack);
        }
        final ItemStackSnapshot oldCursorItem = getCursorItem().createSnapshot();
        final Transaction<ItemStackSnapshot> cursorTransaction = new Transaction<>(oldCursorItem, newCursorItem);
        final ClickInventoryEvent.Drag.Secondary event = SpongeEventFactory.createClickInventoryEventDragSecondary(causeStack.getCurrentCause(), cursorTransaction, this.container, this.container.transformSlots(transactions));
        finishInventoryEvent(event);
    } else {
    // TODO: Middle mouse drag mode
    }
}
Also used : EventContextKeys(org.spongepowered.api.event.cause.EventContextKeys) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) LanternPlayerInventory(org.lanternpowered.server.inventory.vanilla.LanternPlayerInventory) LanternItemStackSnapshot(org.lanternpowered.server.inventory.LanternItemStackSnapshot) CraftingResult(org.spongepowered.api.item.recipe.crafting.CraftingResult) ItemStack(org.spongepowered.api.item.inventory.ItemStack) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) Transaction(org.spongepowered.api.data.Transaction) OutputSlot(org.spongepowered.api.item.inventory.slot.OutputSlot) ExtendedCraftingResult(org.lanternpowered.server.item.recipe.crafting.ExtendedCraftingResult) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) MatrixResult(org.lanternpowered.server.item.recipe.crafting.MatrixResult) Sponge(org.spongepowered.api.Sponge) CraftingGridInventory(org.spongepowered.api.item.inventory.crafting.CraftingGridInventory) Tuple(org.spongepowered.api.util.Tuple) Streams(com.google.common.collect.Streams) CraftingOutput(org.spongepowered.api.item.inventory.crafting.CraftingOutput) Collectors(java.util.stream.Collectors) Preconditions.checkState(com.google.common.base.Preconditions.checkState) List(java.util.List) Lantern(org.lanternpowered.server.game.Lantern) Transform(org.spongepowered.api.entity.Transform) GameMode(org.spongepowered.api.entity.living.player.gamemode.GameMode) ChangeInventoryEvent(org.spongepowered.api.event.item.inventory.ChangeInventoryEvent) CraftingInventory(org.spongepowered.api.item.inventory.crafting.CraftingInventory) World(org.spongepowered.api.world.World) Optional(java.util.Optional) AbstractOrderedInventory(org.lanternpowered.server.inventory.AbstractOrderedInventory) Player(org.spongepowered.api.entity.living.player.Player) LanternItemStack(org.lanternpowered.server.inventory.LanternItemStack) ClientContainer(org.lanternpowered.server.inventory.client.ClientContainer) IInventory(org.lanternpowered.server.inventory.IInventory) Keys(org.spongepowered.api.data.key.Keys) PeekedSetTransactionResult(org.lanternpowered.server.inventory.PeekedSetTransactionResult) GameModes(org.spongepowered.api.entity.living.player.gamemode.GameModes) ArrayList(java.util.ArrayList) CauseStack(org.lanternpowered.server.event.CauseStack) PlayerInventoryContainer(org.lanternpowered.server.inventory.PlayerInventoryContainer) LanternContainer(org.lanternpowered.server.inventory.LanternContainer) PlayerClientContainer(org.lanternpowered.server.inventory.client.PlayerClientContainer) LanternWorld(org.lanternpowered.server.world.LanternWorld) CraftingMatrix(org.lanternpowered.server.item.recipe.crafting.CraftingMatrix) Nullable(javax.annotation.Nullable) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) AbstractInventorySlot(org.lanternpowered.server.inventory.AbstractInventorySlot) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) LanternEventHelper(org.lanternpowered.server.event.LanternEventHelper) PeekedPollTransactionResult(org.lanternpowered.server.inventory.PeekedPollTransactionResult) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) Slot(org.spongepowered.api.item.inventory.Slot) Entity(org.spongepowered.api.entity.Entity) PeekedOfferTransactionResult(org.lanternpowered.server.inventory.PeekedOfferTransactionResult) SpawnTypes(org.spongepowered.api.event.cause.entity.spawn.SpawnTypes) LanternPlayer(org.lanternpowered.server.entity.living.player.LanternPlayer) LanternHotbarInventory(org.lanternpowered.server.inventory.vanilla.LanternHotbarInventory) AbstractInventory(org.lanternpowered.server.inventory.AbstractInventory) CauseStack(org.lanternpowered.server.event.CauseStack) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) ArrayList(java.util.ArrayList) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Transaction(org.spongepowered.api.data.Transaction) OutputSlot(org.spongepowered.api.item.inventory.slot.OutputSlot) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) ClientSlot(org.lanternpowered.server.inventory.client.ClientSlot) AbstractInventorySlot(org.lanternpowered.server.inventory.AbstractInventorySlot) Slot(org.spongepowered.api.item.inventory.Slot) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) LanternItemStackSnapshot(org.lanternpowered.server.inventory.LanternItemStackSnapshot) List(java.util.List) ArrayList(java.util.ArrayList) ItemStack(org.spongepowered.api.item.inventory.ItemStack) LanternItemStack(org.lanternpowered.server.inventory.LanternItemStack) LanternPlayer(org.lanternpowered.server.entity.living.player.LanternPlayer)

Example 10 with AbstractSlot

use of org.lanternpowered.server.inventory.AbstractSlot in project LanternServer by LanternPowered.

the class PlayerInteractionHandler method handleBlockPlacing.

public void handleBlockPlacing(MessagePlayInPlayerBlockPlacement message) {
    final HandType handType = message.getHandType();
    // the main hand message.
    if (handType == HandTypes.OFF_HAND) {
        return;
    }
    // Try the action of the hotbar item first
    final AbstractSlot hotbarSlot = this.player.getInventory().getHotbar().getSelectedSlot();
    final AbstractSlot offHandSlot = this.player.getInventory().getOffhand();
    // The offset can round up to 1, causing
    // an incorrect clicked block location
    final Vector3d pos2 = message.getClickOffset();
    final double dx = Math.min(pos2.getX(), 0.999);
    final double dy = Math.min(pos2.getY(), 0.999);
    final double dz = Math.min(pos2.getZ(), 0.999);
    final Location<World> clickedLocation = new Location<>(this.player.getWorld(), message.getPosition().toDouble().add(dx, dy, dz));
    final Direction face = message.getFace();
    final CauseStack causeStack = CauseStack.current();
    try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
        frame.pushCause(this.player);
        // Add context
        frame.addContext(ContextKeys.INTERACTION_FACE, face);
        frame.addContext(ContextKeys.INTERACTION_LOCATION, clickedLocation);
        frame.addContext(ContextKeys.BLOCK_LOCATION, new Location<>(clickedLocation.getExtent(), message.getPosition()));
        frame.addContext(ContextKeys.PLAYER, this.player);
        final BehaviorContextImpl context = new BehaviorContextImpl(causeStack);
        final BehaviorContext.Snapshot snapshot = context.pushSnapshot();
        if (!this.player.get(Keys.IS_SNEAKING).orElse(false)) {
            final BlockState blockState = this.player.getWorld().getBlock(message.getPosition());
            final LanternBlockType blockType = (LanternBlockType) blockState.getType();
            frame.addContext(ContextKeys.BLOCK_TYPE, blockState.getType());
            frame.addContext(ContextKeys.USED_BLOCK_STATE, blockState);
            BehaviorContext.Snapshot snapshot1 = context.pushSnapshot();
            // Try first with the main hand
            hotbarSlot.peek().ifPresent(stack -> frame.addContext(ContextKeys.USED_ITEM_STACK, stack));
            frame.addContext(ContextKeys.USED_SLOT, hotbarSlot);
            frame.addContext(ContextKeys.INTERACTION_HAND, HandTypes.MAIN_HAND);
            BehaviorResult result = context.process(blockType.getPipeline().pipeline(InteractWithBlockBehavior.class), (ctx, behavior) -> behavior.tryInteract(blockType.getPipeline(), ctx));
            if (!result.isSuccess()) {
                context.popSnapshot(snapshot1);
                snapshot1 = context.pushSnapshot();
                // Try again with the off hand
                offHandSlot.peek().ifPresent(stack -> frame.addContext(ContextKeys.USED_ITEM_STACK, stack));
                frame.addContext(ContextKeys.USED_SLOT, offHandSlot);
                frame.addContext(ContextKeys.INTERACTION_HAND, HandTypes.OFF_HAND);
                result = context.process(blockType.getPipeline().pipeline(InteractWithBlockBehavior.class), (ctx, behavior) -> behavior.tryInteract(blockType.getPipeline(), ctx));
            }
            if (result.isSuccess()) {
                snapshot1 = context.pushSnapshot();
                // We can still continue, doing other operations
                if (result == BehaviorResult.CONTINUE) {
                    handleMainHandItemInteraction(context, snapshot1);
                }
                context.accept();
                return;
            }
            context.popSnapshot(snapshot1);
            snapshot1 = context.pushSnapshot();
            if (result.isSuccess()) {
                snapshot1 = context.pushSnapshot();
                // We can still continue, doing other operations
                if (result == BehaviorResult.CONTINUE) {
                    handleOffHandItemInteraction(context, snapshot1);
                }
                context.accept();
                return;
            }
            context.popSnapshot(snapshot1);
        }
        handleItemInteraction(context, snapshot);
    }
}
Also used : MessagePlayOutEntityAnimation(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayOutEntityAnimation) LanternKeys(org.lanternpowered.server.data.key.LanternKeys) Keys(org.spongepowered.api.data.key.Keys) EventContextKeys(org.spongepowered.api.event.cause.EventContextKeys) LanternBlockType(org.lanternpowered.server.block.LanternBlockType) MessagePlayInPlayerSwingArm(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInPlayerSwingArm) BehaviorContextImpl(org.lanternpowered.server.behavior.BehaviorContextImpl) Vector3d(com.flowpowered.math.vector.Vector3d) MessagePlayInOutFinishUsingItem(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInOutFinishUsingItem) MessagePlayInPlayerDigging(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInPlayerDigging) HandType(org.spongepowered.api.data.type.HandType) MinimumUseDurationProperty(org.lanternpowered.server.item.property.MinimumUseDurationProperty) GameModes(org.spongepowered.api.entity.living.player.gamemode.GameModes) BreakBlockBehavior(org.lanternpowered.server.block.behavior.types.BreakBlockBehavior) ItemStack(org.spongepowered.api.item.inventory.ItemStack) BehaviorContext(org.lanternpowered.server.behavior.BehaviorContext) CauseStack(org.lanternpowered.server.event.CauseStack) InteractWithItemBehavior(org.lanternpowered.server.item.behavior.types.InteractWithItemBehavior) MessagePlayOutBlockBreakAnimation(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayOutBlockBreakAnimation) BehaviorResult(org.lanternpowered.server.behavior.BehaviorResult) LanternWorld(org.lanternpowered.server.world.LanternWorld) InteractWithBlockBehavior(org.lanternpowered.server.block.behavior.types.InteractWithBlockBehavior) Nullable(javax.annotation.Nullable) ContextKeys(org.lanternpowered.server.behavior.ContextKeys) FinishUsingItemBehavior(org.lanternpowered.server.item.behavior.types.FinishUsingItemBehavior) Location(org.spongepowered.api.world.Location) MaximumUseDurationProperty(org.lanternpowered.server.item.property.MaximumUseDurationProperty) LanternItemType(org.lanternpowered.server.item.LanternItemType) MessagePlayInPlayerUseItem(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInPlayerUseItem) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) BlockTypes(org.spongepowered.api.block.BlockTypes) SwingHandEntityEvent(org.lanternpowered.server.entity.event.SwingHandEntityEvent) Set(java.util.Set) LanternGame(org.lanternpowered.server.game.LanternGame) BlockState(org.spongepowered.api.block.BlockState) Objects(java.util.Objects) Direction(org.spongepowered.api.util.Direction) DualWieldProperty(org.lanternpowered.server.item.property.DualWieldProperty) Lantern(org.lanternpowered.server.game.Lantern) Vector3i(com.flowpowered.math.vector.Vector3i) World(org.spongepowered.api.world.World) BlockType(org.spongepowered.api.block.BlockType) HandTypes(org.spongepowered.api.data.type.HandTypes) Optional(java.util.Optional) MessagePlayInPlayerBlockPlacement(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInPlayerBlockPlacement) CauseStack(org.lanternpowered.server.event.CauseStack) AbstractSlot(org.lanternpowered.server.inventory.AbstractSlot) HandType(org.spongepowered.api.data.type.HandType) LanternWorld(org.lanternpowered.server.world.LanternWorld) World(org.spongepowered.api.world.World) Direction(org.spongepowered.api.util.Direction) LanternBlockType(org.lanternpowered.server.block.LanternBlockType) BehaviorContextImpl(org.lanternpowered.server.behavior.BehaviorContextImpl) BlockState(org.spongepowered.api.block.BlockState) Vector3d(com.flowpowered.math.vector.Vector3d) BehaviorResult(org.lanternpowered.server.behavior.BehaviorResult) BehaviorContext(org.lanternpowered.server.behavior.BehaviorContext) Location(org.spongepowered.api.world.Location) InteractWithBlockBehavior(org.lanternpowered.server.block.behavior.types.InteractWithBlockBehavior)

Aggregations

AbstractSlot (org.lanternpowered.server.inventory.AbstractSlot)21 ItemStack (org.spongepowered.api.item.inventory.ItemStack)15 CauseStack (org.lanternpowered.server.event.CauseStack)12 ArrayList (java.util.ArrayList)10 LanternPlayer (org.lanternpowered.server.entity.living.player.LanternPlayer)10 LanternItemStack (org.lanternpowered.server.inventory.LanternItemStack)9 SlotTransaction (org.spongepowered.api.item.inventory.transaction.SlotTransaction)9 Optional (java.util.Optional)8 Nullable (javax.annotation.Nullable)8 Lantern (org.lanternpowered.server.game.Lantern)8 LanternWorld (org.lanternpowered.server.world.LanternWorld)8 Keys (org.spongepowered.api.data.key.Keys)8 EventContextKeys (org.spongepowered.api.event.cause.EventContextKeys)8 ItemStackSnapshot (org.spongepowered.api.item.inventory.ItemStackSnapshot)8 World (org.spongepowered.api.world.World)8 LanternItemStackSnapshot (org.lanternpowered.server.inventory.LanternItemStackSnapshot)7 PlayerInventoryContainer (org.lanternpowered.server.inventory.PlayerInventoryContainer)7 ClientSlot (org.lanternpowered.server.inventory.client.ClientSlot)7 LanternPlayerInventory (org.lanternpowered.server.inventory.vanilla.LanternPlayerInventory)7 ChangeInventoryEvent (org.spongepowered.api.event.item.inventory.ChangeInventoryEvent)7