Search in sources :

Example 1 with SelectedWindowData

use of mekanism.common.inventory.container.SelectedWindowData in project Mekanism by mekanism.

the class QIOServerCraftingTransferHandler method transferItems.

private void transferItems(Byte2ObjectMap<List<SingularHashedItemSource>> sources) {
    SelectedWindowData windowData = craftingWindow.getWindowData();
    // Extract items that will be put into the crafting window
    Byte2ObjectMap<ItemStack> targetContents = new Byte2ObjectArrayMap<>(sources.size());
    for (Byte2ObjectMap.Entry<List<SingularHashedItemSource>> entry : sources.byte2ObjectEntrySet()) {
        for (SingularHashedItemSource source : entry.getValue()) {
            byte slot = source.getSlot();
            ItemStack stack;
            if (slot == -1) {
                UUID qioSource = source.getQioSource();
                // Neither the source nor the frequency can be null here as we validated that during simulation
                HashedItem storedItem = frequency.getTypeByUUID(qioSource);
                if (storedItem == null) {
                    bail(targetContents, "Received transfer request from: {}, for: {}, could not find stored item with UUID: {}. " + "This likely means that more of it was requested than is stored.", player, recipeID, qioSource);
                    return;
                }
                stack = frequency.removeByType(storedItem, source.getUsed());
                if (stack.isEmpty()) {
                    bail(targetContents, "Received transfer request from: {}, for: {}, but could not extract item: {} with nbt: {} from the QIO.", player, recipeID, storedItem.getStack().getItem(), storedItem.getStack().getTag());
                    return;
                } else if (stack.getCount() < source.getUsed()) {
                    Mekanism.logger.warn("Received transfer request from: {}, for: {}, but was unable to extract the expected amount: {} of item: {} " + "with nbt: {} from the QIO. This should not be possible as it should have been caught during simulation. Attempting " + "to continue anyways with the actual extracted amount of {}.", player, recipeID, source.getUsed(), storedItem.getStack().getItem(), storedItem.getStack().getTag(), stack.getCount());
                }
            } else {
                int actualSlot;
                String slotType;
                if (slot < 9) {
                    // Crafting Window
                    actualSlot = slot;
                    slotType = "crafting window";
                    stack = craftingWindow.getInputSlot(slot).extractItem(source.getUsed(), Action.EXECUTE, AutomationType.MANUAL);
                } else if (slot < 9 + PlayerInventory.getSelectionSize()) {
                    // Hotbar
                    actualSlot = slot - 9;
                    slotType = "hotbar";
                    stack = hotBarSlots.get(actualSlot).remove(source.getUsed());
                } else {
                    // Main inventory
                    actualSlot = slot - 9 - PlayerInventory.getSelectionSize();
                    slotType = "main inventory";
                    stack = mainInventorySlots.get(actualSlot).remove(source.getUsed());
                }
                if (stack.isEmpty()) {
                    bail(targetContents, "Received transfer request from: {}, for: {}, could not extract item from {} slot: {}. " + "This likely means that more of it was requested than is stored.", player, recipeID, slotType, actualSlot);
                    return;
                } else if (stack.getCount() < source.getUsed()) {
                    Mekanism.logger.warn("Received transfer request from: {}, for: {}, but was unable to extract the expected amount: {} from {} slot: {}. " + "This should not be possible as it should have been caught during simulation. Attempting to continue anyways with the " + "actual extracted amount of {}.", player, recipeID, source.getUsed(), slotType, actualSlot, stack.getCount());
                }
            }
            byte targetSlot = entry.getByteKey();
            if (targetContents.containsKey(targetSlot)) {
                ItemStack existing = targetContents.get(targetSlot);
                if (ItemHandlerHelper.canItemStacksStack(existing, stack)) {
                    int needed = existing.getMaxStackSize() - existing.getCount();
                    if (stack.getCount() <= needed) {
                        existing.grow(stack.getCount());
                    } else {
                        existing.grow(needed);
                        // Note: We can safely modify the stack as all our ways of extracting return a new stack
                        stack.shrink(needed);
                        Mekanism.logger.warn("Received transfer request from: {}, for: {}, but contents could not fully fit into target slot: {}. " + "This should not be able to happen, returning excess stack, and attempting to continue.", player, recipeID, targetSlot);
                        returnItem(stack, windowData);
                    }
                } else {
                    Mekanism.logger.warn("Received transfer request from: {}, for: {}, but contents could not stack into target slot: {}. " + "This should not be able to happen, returning extra stack, and attempting to continue.", player, recipeID, targetSlot);
                    returnItem(stack, windowData);
                }
            } else {
                // Note: We can safely modify the stack as all our ways of extracting return a new stack
                targetContents.put(targetSlot, stack);
            }
        }
    }
    // Extract what items are still in the window
    Byte2ObjectMap<ItemStack> remainingCraftingGridContents = new Byte2ObjectArrayMap<>(9);
    for (byte slot = 0; slot < 9; slot++) {
        CraftingWindowInventorySlot inputSlot = craftingWindow.getInputSlot(slot);
        if (!inputSlot.isEmpty()) {
            ItemStack stack = inputSlot.extractItem(inputSlot.getCount(), Action.EXECUTE, AutomationType.MANUAL);
            if (!stack.isEmpty()) {
                remainingCraftingGridContents.put(slot, stack);
            } else {
                bail(targetContents, remainingCraftingGridContents, "Received transfer request from: {}, for: {}, but failed to remove items from crafting " + "input slot: {}. This should not be possible as it should have been caught by an earlier check.", player, recipeID, slot);
                return;
            }
        }
    }
    // Insert items for the crafting window into it
    for (ObjectIterator<Byte2ObjectMap.Entry<ItemStack>> iter = targetContents.byte2ObjectEntrySet().iterator(); iter.hasNext(); ) {
        Byte2ObjectMap.Entry<ItemStack> entry = iter.next();
        byte targetSlot = entry.getByteKey();
        CraftingWindowInventorySlot inputSlot = craftingWindow.getInputSlot(targetSlot);
        ItemStack remainder = inputSlot.insertItem(entry.getValue(), Action.EXECUTE, AutomationType.MANUAL);
        if (remainder.isEmpty()) {
            // If it was fully inserted, remove the entry from what we have left to deal with
            iter.remove();
        } else {
            // otherwise, update the stack for what is remaining and also print a warning as this should have been caught earlier,
            // as we then will handle any remaining contents at the end (though we shouldn't have any)
            // Note: We need to use put, as entry#setValue is not supported in fastutil maps
            targetContents.put(targetSlot, remainder);
            Mekanism.logger.warn("Received transfer request from: {}, for: {}, but was unable to fully insert it into the {} crafting input slot. " + "This should not be possible as it should have been caught during simulation. Attempting to continue anyways.", player, recipeID, targetSlot);
        }
    }
    // Put the items that were in the crafting window in the player's inventory
    for (Byte2ObjectMap.Entry<ItemStack> entry : remainingCraftingGridContents.byte2ObjectEntrySet()) {
        // Insert into player's inventory
        ItemStack stack = returnItemToInventory(entry.getValue(), windowData);
        if (!stack.isEmpty()) {
            // If we couldn't insert it all, try recombining with the slots they were in the crafting window
            // (only if the type matches though)
            CraftingWindowInventorySlot inputSlot = craftingWindow.getInputSlot(entry.getByteKey());
            if (ItemHandlerHelper.canItemStacksStack(inputSlot.getStack(), stack)) {
                stack = inputSlot.insertItem(stack, Action.EXECUTE, AutomationType.MANUAL);
            }
            if (!stack.isEmpty()) {
                // If we couldn't insert it, then try to put the remaining items in the frequency
                if (frequency != null) {
                    stack = frequency.addItem(stack);
                }
                if (!stack.isEmpty()) {
                    // If we couldn't insert it all, either because there was no frequency or it didn't have room for it all
                    // drop it as the player, and print a warning as ideally we should never have been able to get to this
                    // point as our simulation should have marked it as invalid
                    // Note: In theory we should never get to this point due to having accurate simulations ahead of time
                    player.drop(stack, false);
                    Mekanism.logger.warn("Received transfer request from: {}, for: {}, and was unable to fit all contents that were in the crafting window " + "into the player's inventory/QIO system; dropping items by player.", player, recipeID);
                }
            }
        }
    }
    if (!targetContents.isEmpty()) {
        // If we have any contents we wanted to move remaining try to return them, in theory
        // this should never happen but in case it does make sure we don't void any items
        bail(targetContents, "Received transfer request from: {}, for: {}, but ended up with {} items that could not be transferred into " + "the proper crafting grid slot. This should not be possible as it should have been caught during simulation.", player, recipeID, targetContents.size());
    }
}
Also used : HashedItem(mekanism.common.lib.inventory.HashedItem) SingularHashedItemSource(mekanism.common.content.qio.QIOCraftingTransferHelper.SingularHashedItemSource) Byte2ObjectMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectMap) ArrayList(java.util.ArrayList) NonNullList(net.minecraft.util.NonNullList) List(java.util.List) Byte2ObjectArrayMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectArrayMap) ItemStack(net.minecraft.item.ItemStack) UUID(java.util.UUID) SelectedWindowData(mekanism.common.inventory.container.SelectedWindowData) CraftingWindowInventorySlot(mekanism.common.inventory.slot.CraftingWindowInventorySlot)

Example 2 with SelectedWindowData

use of mekanism.common.inventory.container.SelectedWindowData in project Mekanism by mekanism.

the class QIOServerCraftingTransferHandler method bail.

/**
 * Bails out if something went horribly wrong and didn't get caught by simulations, and send the various items back to the inventory.
 */
private void bail(Byte2ObjectMap<ItemStack> targetContents, Byte2ObjectMap<ItemStack> remainingCraftingGridContents, String format, Object... args) {
    Mekanism.logger.warn(format, args);
    SelectedWindowData windowData = craftingWindow.getWindowData();
    for (ItemStack stack : targetContents.values()) {
        // We don't attempt to try and return the contents being moved to the crafting inventory to their original slots
        // as we don't keep track of that data and in theory unless something goes majorly wrong we should never end
        // up bailing anyways
        // TODO: Eventually we may want to try and make it first try to return to the same slots it came from but it doesn't matter that much
        returnItem(stack, windowData);
    }
    // Put the items that were in the crafting window in the player's inventory
    for (Byte2ObjectMap.Entry<ItemStack> entry : remainingCraftingGridContents.byte2ObjectEntrySet()) {
        ItemStack stack = entry.getValue();
        CraftingWindowInventorySlot inputSlot = craftingWindow.getInputSlot(entry.getByteKey());
        if (ItemHandlerHelper.canItemStacksStack(inputSlot.getStack(), stack)) {
            stack = inputSlot.insertItem(stack, Action.EXECUTE, AutomationType.MANUAL);
            if (stack.isEmpty()) {
                continue;
            }
        }
        returnItem(stack, windowData);
    }
}
Also used : Byte2ObjectMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectMap) ItemStack(net.minecraft.item.ItemStack) SelectedWindowData(mekanism.common.inventory.container.SelectedWindowData) CraftingWindowInventorySlot(mekanism.common.inventory.slot.CraftingWindowInventorySlot)

Example 3 with SelectedWindowData

use of mekanism.common.inventory.container.SelectedWindowData in project Mekanism by mekanism.

the class PacketWindowSelect method decode.

public static PacketWindowSelect decode(PacketBuffer buffer) {
    byte extraData = buffer.readByte();
    if (extraData == -1) {
        return new PacketWindowSelect(null);
    }
    WindowType windowType = buffer.readEnum(WindowType.class);
    return new PacketWindowSelect(windowType == WindowType.UNSPECIFIED ? SelectedWindowData.UNSPECIFIED : new SelectedWindowData(windowType, extraData));
}
Also used : WindowType(mekanism.common.inventory.container.SelectedWindowData.WindowType) SelectedWindowData(mekanism.common.inventory.container.SelectedWindowData)

Aggregations

SelectedWindowData (mekanism.common.inventory.container.SelectedWindowData)3 Byte2ObjectMap (it.unimi.dsi.fastutil.bytes.Byte2ObjectMap)2 CraftingWindowInventorySlot (mekanism.common.inventory.slot.CraftingWindowInventorySlot)2 ItemStack (net.minecraft.item.ItemStack)2 Byte2ObjectArrayMap (it.unimi.dsi.fastutil.bytes.Byte2ObjectArrayMap)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 UUID (java.util.UUID)1 SingularHashedItemSource (mekanism.common.content.qio.QIOCraftingTransferHelper.SingularHashedItemSource)1 WindowType (mekanism.common.inventory.container.SelectedWindowData.WindowType)1 HashedItem (mekanism.common.lib.inventory.HashedItem)1 NonNullList (net.minecraft.util.NonNullList)1