Search in sources :

Example 1 with SlotTransaction

use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.

the class MixinSlotCrafting method afterTake.

/**
 * Create CraftItemEvent.Post result is also handled by
 * {@link MixinContainer#redirectTransferStackInSlot} or
 * {@link MixinContainer#redirectOnTakeThrow}
 */
@Inject(method = "onTake", cancellable = true, at = @At("RETURN"))
private void afterTake(EntityPlayer thePlayer, ItemStack stack, CallbackInfoReturnable<ItemStack> cir) {
    if (((IMixinWorld) thePlayer.world).isFake()) {
        return;
    }
    ((IMixinContainer) thePlayer.openContainer).detectAndSendChanges(true);
    ((IMixinContainer) thePlayer.openContainer).setCaptureInventory(false);
    Container container = thePlayer.openContainer;
    Inventory craftInv = ((Inventory) container).query(QueryOperationTypes.INVENTORY_TYPE.of(CraftingInventory.class));
    if (!(craftInv instanceof CraftingInventory)) {
        SpongeImpl.getLogger().warn("Detected crafting without a InventoryCrafting!? Crafting Event will not fire.");
        return;
    }
    // retain only last slot-transactions on output slot
    SlotTransaction first = null;
    List<SlotTransaction> capturedTransactions = ((IMixinContainer) container).getCapturedTransactions();
    for (Iterator<SlotTransaction> iterator = capturedTransactions.iterator(); iterator.hasNext(); ) {
        SlotTransaction trans = iterator.next();
        Optional<SlotIndex> slotIndex = trans.getSlot().getInventoryProperty(SlotIndex.class);
        if (slotIndex.isPresent() && slotIndex.get().getValue() == 0) {
            iterator.remove();
            if (first == null) {
                first = trans;
            }
        }
    }
    ItemStackSnapshot craftedItem;
    // if we got a transaction on the crafting-slot use this
    if (first != null) {
        capturedTransactions.add(first);
        craftedItem = first.getOriginal().copy();
    } else {
        if (stack.isEmpty()) {
            // if stack is empty this was probably shift-crafting so we use the captured itemstack instead
            craftedItem = ItemStackUtil.snapshotOf(this.craftedStack);
        } else {
            craftedItem = ItemStackUtil.snapshotOf(stack);
        }
    }
    CraftingInventory craftingInventory = (CraftingInventory) craftInv;
    CraftItemEvent.Craft event = SpongeCommonEventFactory.callCraftEventPost(thePlayer, craftingInventory, craftedItem, this.lastRecipe, container, capturedTransactions);
    ((IMixinContainer) container).setLastCraft(event);
    ((IMixinContainer) container).setFirePreview(true);
    this.craftedStack = null;
    SlotTransaction last = new SlotTransaction(craftingInventory.getResult(), ItemStackSnapshot.NONE, ItemStackUtil.snapshotOf(this.getStack()));
    List<SlotTransaction> previewTransactions = ((IMixinContainer) container).getPreviewTransactions();
    CraftingRecipe newRecipe = Sponge.getRegistry().getCraftingRecipeRegistry().findMatchingRecipe(craftingInventory.getCraftingGrid(), ((World) player.world)).orElse(null);
    SpongeCommonEventFactory.callCraftEventPre(thePlayer, craftingInventory, last, newRecipe, container, previewTransactions);
    previewTransactions.clear();
}
Also used : CraftingInventory(org.spongepowered.api.item.inventory.crafting.CraftingInventory) CraftingRecipe(org.spongepowered.api.item.recipe.crafting.CraftingRecipe) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) IMixinContainer(org.spongepowered.common.interfaces.IMixinContainer) IMixinContainer(org.spongepowered.common.interfaces.IMixinContainer) Container(net.minecraft.inventory.Container) IMixinWorld(org.spongepowered.common.interfaces.world.IMixinWorld) SlotIndex(org.spongepowered.api.item.inventory.property.SlotIndex) CraftItemEvent(org.spongepowered.api.event.item.inventory.CraftItemEvent) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) Inventory(org.spongepowered.api.item.inventory.Inventory) CraftingInventory(org.spongepowered.api.item.inventory.crafting.CraftingInventory) IInventory(net.minecraft.inventory.IInventory) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 2 with SlotTransaction

use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.

the class EnchantItemPacketState method unwind.

@Override
public void unwind(InventoryPacketContext context) {
    // TODO - Pre changes of merging PacketFunction into the phase states, enchantments did NOT have any processing....
    final EntityPlayerMP player = context.getPacketPlayer();
    // The server will disable the player's crafting after receiving a
    // client packet
    // that did not pass validation (server click item != packet click item)
    // The server then sends a SPacketConfirmTransaction and waits for a
    // CPacketConfirmTransaction to re-enable crafting confirming that the
    // client
    // acknowledged the denied transaction.
    // To detect when this happens, we turn off capturing so we can avoid
    // firing
    // invalid events.
    // See MixinNetHandlerPlayServer processClickWindow redirect for rest of
    // fix.
    // --bloodmc
    final IMixinContainer mixinContainer = ContainerUtil.toMixin(player.openContainer);
    if (!mixinContainer.capturingInventory()) {
        mixinContainer.getCapturedTransactions().clear();
        return;
    }
    // TODO clear this shit out of the context
    final CPacketEnchantItem packetIn = context.getPacket();
    final ItemStackSnapshot lastCursor = context.getCursor();
    final ItemStackSnapshot newCursor = ItemStackUtil.snapshotOf(player.inventory.getItemStack());
    final Transaction<ItemStackSnapshot> transaction = new Transaction<>(lastCursor, newCursor);
    final net.minecraft.inventory.Container openContainer = player.openContainer;
    final List<SlotTransaction> slotTransactions = mixinContainer.getCapturedTransactions();
    final int usedButton = packetIn.getButton();
    final List<Entity> capturedItems = new ArrayList<>();
    for (EntityItem entityItem : context.getCapturedItems()) {
        capturedItems.add(EntityUtil.fromNative(entityItem));
    }
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(player);
        Sponge.getCauseStackManager().pushCause(openContainer);
        final ClickInventoryEvent inventoryEvent;
        inventoryEvent = this.createInventoryEvent(player, ContainerUtil.fromNative(openContainer), transaction, Lists.newArrayList(slotTransactions), capturedItems, usedButton);
        // If this happens and we captured no entities, avoid firing events
        if (mixinContainer.getCapturedTransactions().isEmpty() && capturedItems.isEmpty()) {
            mixinContainer.setCaptureInventory(false);
            return;
        }
        if (inventoryEvent != null) {
            // Don't fire inventory drop events when there are no entities
            if (inventoryEvent instanceof AffectEntityEvent && ((AffectEntityEvent) inventoryEvent).getEntities().isEmpty()) {
                slotTransactions.clear();
                mixinContainer.setCaptureInventory(false);
                return;
            }
            // packet has everything we want.
            if (!(inventoryEvent instanceof ClickInventoryEvent.Drag)) {
                PacketPhaseUtil.validateCapturedTransactions(packetIn.getWindowId(), openContainer, inventoryEvent.getTransactions());
            }
            SpongeImpl.postEvent(inventoryEvent);
            if (inventoryEvent.isCancelled() || PacketPhaseUtil.allTransactionsInvalid(inventoryEvent.getTransactions())) {
                if (inventoryEvent instanceof ClickInventoryEvent.Drop) {
                    capturedItems.clear();
                }
                // Restore cursor
                PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getOriginal());
                // Restore target slots
                PacketPhaseUtil.handleSlotRestore(player, openContainer, inventoryEvent.getTransactions(), true);
            } else {
                PacketPhaseUtil.handleSlotRestore(player, openContainer, inventoryEvent.getTransactions(), false);
                // Handle cursor
                if (!inventoryEvent.getCursorTransaction().isValid()) {
                    PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getOriginal());
                } else if (inventoryEvent.getCursorTransaction().getCustom().isPresent()) {
                    PacketPhaseUtil.handleCustomCursor(player, inventoryEvent.getCursorTransaction().getFinal());
                } else if (inventoryEvent instanceof ClickInventoryEvent.Drag) {
                    int increment;
                    increment = slotTransactions.stream().filter((t) -> !t.isValid()).mapToInt((t) -> t.getFinal().getQuantity()).sum();
                    final ItemStack cursor = inventoryEvent.getCursorTransaction().getFinal().createStack();
                    cursor.setQuantity(cursor.getQuantity() + increment);
                    PacketPhaseUtil.handleCustomCursor(player, cursor.createSnapshot());
                } else if (inventoryEvent instanceof ClickInventoryEvent.Double && !(inventoryEvent instanceof ClickInventoryEvent.Shift)) {
                    int decrement;
                    decrement = slotTransactions.stream().filter((t) -> !t.isValid()).mapToInt((t) -> t.getOriginal().getQuantity()).sum();
                    final ItemStack cursor = inventoryEvent.getCursorTransaction().getFinal().createStack();
                    cursor.setQuantity(cursor.getQuantity() - decrement);
                    PacketPhaseUtil.handleCustomCursor(player, cursor.createSnapshot());
                }
                if (inventoryEvent instanceof SpawnEntityEvent) {
                    processSpawnedEntities(player, (SpawnEntityEvent) inventoryEvent);
                } else if (!context.getCapturedEntitySupplier().isEmpty()) {
                    SpawnEntityEvent spawnEntityEvent = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), context.getCapturedEntities());
                    SpongeImpl.postEvent(spawnEntityEvent);
                    if (!spawnEntityEvent.isCancelled()) {
                        processSpawnedEntities(player, spawnEntityEvent);
                    }
                }
            }
        }
    }
    slotTransactions.clear();
    mixinContainer.setCaptureInventory(false);
}
Also used : CPacketEnchantItem(net.minecraft.network.play.client.CPacketEnchantItem) EntityItem(net.minecraft.entity.item.EntityItem) SpongeImpl(org.spongepowered.common.SpongeImpl) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) CPacketEnchantItem(net.minecraft.network.play.client.CPacketEnchantItem) Sponge(org.spongepowered.api.Sponge) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) Entity(org.spongepowered.api.entity.Entity) ItemStackUtil(org.spongepowered.common.item.inventory.util.ItemStackUtil) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) EntityUtil(org.spongepowered.common.entity.EntityUtil) ArrayList(java.util.ArrayList) ContainerUtil(org.spongepowered.common.item.inventory.util.ContainerUtil) ItemStack(org.spongepowered.api.item.inventory.ItemStack) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) List(java.util.List) Lists(com.google.common.collect.Lists) AffectEntityEvent(org.spongepowered.api.event.entity.AffectEntityEvent) IMixinContainer(org.spongepowered.common.interfaces.IMixinContainer) CauseStackManager(org.spongepowered.api.event.CauseStackManager) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) Transaction(org.spongepowered.api.data.Transaction) Entity(org.spongepowered.api.entity.Entity) ArrayList(java.util.ArrayList) CauseStackManager(org.spongepowered.api.event.CauseStackManager) EntityItem(net.minecraft.entity.item.EntityItem) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) IMixinContainer(org.spongepowered.common.interfaces.IMixinContainer) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Transaction(org.spongepowered.api.data.Transaction) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) AffectEntityEvent(org.spongepowered.api.event.entity.AffectEntityEvent) ItemStack(org.spongepowered.api.item.inventory.ItemStack)

Example 3 with SlotTransaction

use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method callPlayerChangeInventoryPickupPreEvent.

public static boolean callPlayerChangeInventoryPickupPreEvent(EntityPlayer player, EntityItem itemToPickup, int pickupDelay, UUID creator) {
    ItemStack stack = itemToPickup.getItem();
    Sponge.getCauseStackManager().pushCause(player);
    ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack);
    ChangeInventoryEvent.Pickup.Pre event = SpongeEventFactory.createChangeInventoryEventPickupPre(Sponge.getCauseStackManager().getCurrentCause(), Optional.empty(), Collections.singletonList(snapshot), snapshot, ((Item) itemToPickup), ((Inventory) player.inventory));
    SpongeImpl.postEvent(event);
    Sponge.getCauseStackManager().popCause();
    if (event.isCancelled()) {
        return false;
    }
    if (event.getCustom().isPresent()) {
        List<ItemStackSnapshot> list = event.getCustom().get();
        if (list.isEmpty()) {
            itemToPickup.getItem().setCount(0);
            return false;
        }
        boolean fullTransfer = true;
        IMixinInventoryPlayer capture = (IMixinInventoryPlayer) player.inventory;
        capture.setCapture(true);
        for (ItemStackSnapshot item : list) {
            org.spongepowered.api.item.inventory.ItemStack itemStack = item.createStack();
            player.inventory.addItemStackToInventory(ItemStackUtil.toNative(itemStack));
            if (!itemStack.isEmpty()) {
                fullTransfer = false;
                break;
            }
        }
        capture.setCapture(false);
        if (!fullTransfer) {
            for (SlotTransaction trans : capture.getCapturedTransactions()) {
                trans.getSlot().set(trans.getOriginal().createStack());
            }
            return false;
        }
        if (!callPlayerChangeInventoryPickupEvent(player, capture)) {
            return false;
        }
        itemToPickup.getItem().setCount(0);
    }
    return true;
}
Also used : SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) IMixinInventoryPlayer(org.spongepowered.common.interfaces.entity.player.IMixinInventoryPlayer) EntityItem(net.minecraft.entity.item.EntityItem) Item(org.spongepowered.api.entity.Item) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) ItemStack(net.minecraft.item.ItemStack) IMixinInventory(org.spongepowered.common.interfaces.IMixinInventory) OrderedInventory(org.spongepowered.api.item.inventory.type.OrderedInventory) CraftingInventory(org.spongepowered.api.item.inventory.crafting.CraftingInventory) CarriedInventory(org.spongepowered.api.item.inventory.type.CarriedInventory) Inventory(org.spongepowered.api.item.inventory.Inventory) CustomInventory(org.spongepowered.common.item.inventory.custom.CustomInventory) IInventory(net.minecraft.inventory.IInventory)

Example 4 with SlotTransaction

use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method generateTransactions.

private static List<SlotTransaction> generateTransactions(@Nullable Inventory inv, IInventory inventory, ItemStack[] previous) {
    if (inv == null) {
        return Collections.emptyList();
    }
    List<SlotTransaction> trans = new ArrayList<>();
    Iterator<Inventory> it = inv.slots().iterator();
    for (int i = 0; i < inventory.getSizeInventory(); i++) {
        org.spongepowered.api.item.inventory.Slot slot = (org.spongepowered.api.item.inventory.Slot) it.next();
        ItemStack newStack = inventory.getStackInSlot(i);
        ItemStack prevStack = previous[i];
        if (!ItemStack.areItemStacksEqual(newStack, prevStack)) {
            trans.add(new SlotTransaction(slot, ItemStackUtil.snapshotOf(prevStack), ItemStackUtil.snapshotOf(newStack)));
        }
    }
    return trans;
}
Also used : ArrayList(java.util.ArrayList) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) SPacketSetSlot(net.minecraft.network.play.server.SPacketSetSlot) Slot(net.minecraft.inventory.Slot) ItemStack(net.minecraft.item.ItemStack) IMixinInventory(org.spongepowered.common.interfaces.IMixinInventory) OrderedInventory(org.spongepowered.api.item.inventory.type.OrderedInventory) CraftingInventory(org.spongepowered.api.item.inventory.crafting.CraftingInventory) CarriedInventory(org.spongepowered.api.item.inventory.type.CarriedInventory) Inventory(org.spongepowered.api.item.inventory.Inventory) CustomInventory(org.spongepowered.common.item.inventory.custom.CustomInventory) IInventory(net.minecraft.inventory.IInventory)

Example 5 with SlotTransaction

use of org.spongepowered.api.item.inventory.transaction.SlotTransaction in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method captureTransaction.

/**
 * Captures a transaction
 *
 * @param captureIn the {@link IMixinInventory} to capture the transaction in
 * @param inv the Inventory
 * @param index the affected SlotIndex
 * @param originalStack the original Stack
 */
public static void captureTransaction(IMixinInventory captureIn, Inventory inv, int index, ItemStack originalStack) {
    // TODO make sure we never got null
    if (captureIn == null || inv == null) {
        return;
    }
    Inventory ordered = inv.query(QueryOperationTypes.INVENTORY_TYPE.of(OrderedInventory.class));
    if (ordered instanceof OrderedInventory) {
        Optional<org.spongepowered.api.item.inventory.Slot> slot = ((OrderedInventory) ordered).getSlot(SlotIndex.of(index));
        if (slot.isPresent()) {
            SlotTransaction trans = new SlotTransaction(slot.get(), ItemStackUtil.snapshotOf(originalStack), ItemStackUtil.snapshotOf(slot.get().peek().orElse(org.spongepowered.api.item.inventory.ItemStack.empty())));
            captureIn.getCapturedTransactions().add(trans);
        }
    }
}
Also used : SPacketSetSlot(net.minecraft.network.play.server.SPacketSetSlot) Slot(net.minecraft.inventory.Slot) OrderedInventory(org.spongepowered.api.item.inventory.type.OrderedInventory) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) IMixinInventory(org.spongepowered.common.interfaces.IMixinInventory) OrderedInventory(org.spongepowered.api.item.inventory.type.OrderedInventory) CraftingInventory(org.spongepowered.api.item.inventory.crafting.CraftingInventory) CarriedInventory(org.spongepowered.api.item.inventory.type.CarriedInventory) Inventory(org.spongepowered.api.item.inventory.Inventory) CustomInventory(org.spongepowered.common.item.inventory.custom.CustomInventory) IInventory(net.minecraft.inventory.IInventory)

Aggregations

SlotTransaction (org.spongepowered.api.item.inventory.transaction.SlotTransaction)50 ItemStackSnapshot (org.spongepowered.api.item.inventory.ItemStackSnapshot)30 ArrayList (java.util.ArrayList)20 ItemStack (org.spongepowered.api.item.inventory.ItemStack)16 Inventory (org.spongepowered.api.item.inventory.Inventory)14 CraftingInventory (org.spongepowered.api.item.inventory.crafting.CraftingInventory)14 Entity (org.spongepowered.api.entity.Entity)13 Transaction (org.spongepowered.api.data.Transaction)11 ChangeInventoryEvent (org.spongepowered.api.event.item.inventory.ChangeInventoryEvent)11 ClickInventoryEvent (org.spongepowered.api.event.item.inventory.ClickInventoryEvent)11 Slot (org.spongepowered.api.item.inventory.Slot)11 Slot (net.minecraft.inventory.Slot)9 SPacketSetSlot (net.minecraft.network.play.server.SPacketSetSlot)9 AbstractSlot (org.lanternpowered.server.inventory.AbstractSlot)9 SpawnEntityEvent (org.spongepowered.api.event.entity.SpawnEntityEvent)9 IMixinContainer (org.spongepowered.common.interfaces.IMixinContainer)9 Nullable (javax.annotation.Nullable)8 ItemStack (net.minecraft.item.ItemStack)8 CauseStack (org.lanternpowered.server.event.CauseStack)8 List (java.util.List)7