Search in sources :

Example 11 with CraftingInventory

use of net.minecraft.inventory.CraftingInventory in project Mekanism by mekanism.

the class MekanismShapedRecipe method assemble.

@Override
public ItemStack assemble(CraftingInventory inv) {
    if (getResultItem().isEmpty()) {
        return ItemStack.EMPTY;
    }
    ItemStack toReturn = getResultItem().copy();
    List<ItemStack> nbtInputs = new ArrayList<>();
    for (int i = 0; i < inv.getContainerSize(); i++) {
        ItemStack stack = inv.getItem(i);
        if (!stack.isEmpty() && stack.hasTag()) {
            nbtInputs.add(stack);
        }
    }
    if (nbtInputs.isEmpty()) {
        // If none of our items have NBT we can skip checking what data can be transferred
        return toReturn;
    }
    Set<RecipeUpgradeType> supportedTypes = RecipeUpgradeData.getSupportedTypes(toReturn);
    if (supportedTypes.isEmpty()) {
        // If we have no supported types "fail" gracefully by just not transferring any data
        return toReturn;
    }
    Map<RecipeUpgradeType, List<RecipeUpgradeData<?>>> upgradeInfo = new EnumMap<>(RecipeUpgradeType.class);
    // Only bother checking input items that have NBT as ones that do not, don't have any data they may need to transfer
    for (ItemStack stack : nbtInputs) {
        Set<RecipeUpgradeType> stackSupportedTypes = RecipeUpgradeData.getSupportedTypes(stack);
        for (RecipeUpgradeType supportedType : stackSupportedTypes) {
            if (supportedTypes.contains(supportedType)) {
                RecipeUpgradeData<?> data = RecipeUpgradeData.getUpgradeData(supportedType, stack);
                if (data != null) {
                    // If something went wrong, and we didn't actually get any data don't add it
                    upgradeInfo.computeIfAbsent(supportedType, type -> new ArrayList<>()).add(data);
                }
            }
        }
    }
    for (Entry<RecipeUpgradeType, List<RecipeUpgradeData<?>>> entry : upgradeInfo.entrySet()) {
        List<RecipeUpgradeData<?>> upgradeData = entry.getValue();
        if (!upgradeData.isEmpty()) {
            // Skip any empty data, even though we should never have any
            RecipeUpgradeData<?> data = RecipeUpgradeData.mergeUpgradeData(upgradeData);
            if (data == null || !data.applyToStack(toReturn)) {
                // Fail, incompatible data
                return ItemStack.EMPTY;
            }
        }
    }
    return toReturn;
}
Also used : IRecipeSerializer(net.minecraft.item.crafting.IRecipeSerializer) MethodsReturnNonnullByDefault(mcp.MethodsReturnNonnullByDefault) WrappedShapedRecipe(mekanism.common.recipe.WrappedShapedRecipe) EnumMap(java.util.EnumMap) MekanismRecipeSerializers(mekanism.common.registries.MekanismRecipeSerializers) Set(java.util.Set) ParametersAreNonnullByDefault(javax.annotation.ParametersAreNonnullByDefault) ArrayList(java.util.ArrayList) ItemStack(net.minecraft.item.ItemStack) List(java.util.List) Map(java.util.Map) Entry(java.util.Map.Entry) CraftingInventory(net.minecraft.inventory.CraftingInventory) ShapedRecipe(net.minecraft.item.crafting.ShapedRecipe) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) ItemStack(net.minecraft.item.ItemStack) EnumMap(java.util.EnumMap)

Example 12 with CraftingInventory

use of net.minecraft.inventory.CraftingInventory in project Mekanism by mekanism.

the class QIOCraftingTransferHandler method transferRecipe.

@Nullable
@Override
public IRecipeTransferError transferRecipe(CONTAINER container, Object rawRecipe, IRecipeLayout recipeLayout, PlayerEntity player, boolean maxTransfer, boolean doTransfer) {
    if (!(rawRecipe instanceof ICraftingRecipe)) {
        // a crafting recipe, and if it isn't the server won't know how to transfer it anyway
        return handlerHelper.createInternalError();
    }
    byte selectedCraftingGrid = container.getSelectedCraftingGrid();
    if (selectedCraftingGrid == -1) {
        // as there are no crafting grids being shown
        return handlerHelper.createInternalError();
    }
    ICraftingRecipe recipe = (ICraftingRecipe) rawRecipe;
    QIOCraftingWindow craftingWindow = container.getCraftingWindow(selectedCraftingGrid);
    // Note: This variable is only used for when doTransfer is false
    byte nonEmptyCraftingSlots = 0;
    if (!doTransfer) {
        CraftingInventory dummy = MekanismUtils.getDummyCraftingInv();
        for (int slot = 0; slot < 9; slot++) {
            CraftingWindowInventorySlot inputSlot = craftingWindow.getInputSlot(slot);
            if (!inputSlot.isEmpty()) {
                // Copy it in case any recipe does weird things and tries to mutate the stack
                dummy.setItem(slot, StackUtils.size(inputSlot.getStack(), 1));
                // Count how many crafting slots are not empty
                nonEmptyCraftingSlots++;
            }
        }
        if (recipe.matches(dummy, player.level)) {
            // or we may be transferring different items if different ones are shown in JEI
            return null;
        }
    }
    // TODO: It may be nice to eventually implement some sort of caching for this, it isn't drastically needed because JEI is smart
    // and only calls it once per recipe to decide if it should display the button rather than say calling it every render tick in
    // case something changed and the render state should be different. We probably could add some sort of listeners to
    // inventory, QIO, and crafting window that if one changes it invalidates the cache of what ingredients are stored, though then
    // we wouldn't be able to directly modify the map as we find inputs, and also we still would have to do a lot of this comparison
    // logic, unless we can also somehow cache the recipe layout and how it interacts with the other information
    int inputCount = 0;
    Byte2ObjectMap<Set<HashedItem>> hashedIngredients = new Byte2ObjectArrayMap<>();
    for (Map.Entry<Integer, ? extends IGuiIngredient<ItemStack>> entry : recipeLayout.getItemStacks().getGuiIngredients().entrySet()) {
        IGuiIngredient<ItemStack> ingredient = entry.getValue();
        if (ingredient.isInput()) {
            List<ItemStack> validIngredients = ingredient.getAllIngredients();
            if (!validIngredients.isEmpty()) {
                // If there are valid ingredients, increment the count
                inputCount++;
                // and convert them to HashedItems
                // Note: we use a linked hash set to preserve the order of the ingredients as done in JEI
                LinkedHashSet<HashedItem> representations = new LinkedHashSet<>();
                // Note: We shouldn't need to convert the item that is part of the recipe to a "reduced" stack form based
                // on what the server would send, as the item should already be like that from when the server sent the
                // client the recipe. If this turns out to be incorrect due to how some mod does recipes, then we may need
                // to change this
                ItemStack displayed = ingredient.getDisplayedIngredient();
                // so we may as well remove some unneeded copies
                if (displayed != null) {
                    // Start by adding the displayed ingredient if there is one to prioritize it
                    representations.add(HashedItem.raw(displayed));
                }
                // we will just end up merging with the displayed ingredient when we get to it as a valid ingredient
                for (ItemStack validIngredient : validIngredients) {
                    representations.add(HashedItem.raw(validIngredient));
                }
                // Note: We decrement the index by one because JEI uses the first index for the output
                int actualIndex = entry.getKey() - 1;
                if (actualIndex > Byte.MAX_VALUE || actualIndex < Byte.MIN_VALUE) {
                    // Note: This should not happen, but validate it doesn't just to ensure if it does, we gracefully error
                    Mekanism.logger.warn("Error evaluating recipe transfer handler for recipe: {}, had unexpected index: {}", recipe.getId(), actualIndex);
                    return handlerHelper.createInternalError();
                }
                hashedIngredients.put((byte) actualIndex, representations);
            }
        }
    }
    if (inputCount > 9) {
        // I don't believe this ever will happen with a normal crafting recipe but just in case it does, error
        // if we have more than nine inputs, we check it as an extra validation step, but we don't hold off on
        // converting input ingredients to HashedItems, until we have validated this, as there should never be
        // a case where this actually happens except potentially with some really obscure modded recipe
        Mekanism.logger.warn("Error evaluating recipe transfer handler for recipe: {}, had more than 9 inputs: {}", recipe.getId(), inputCount);
        return handlerHelper.createInternalError();
    }
    // Get all our available items in the QIO frequency, we flatten the cache to stack together items that
    // as far as the client is concerned are the same instead of keeping them UUID separated, and add all
    // the items in the currently selected crafting window and the player's inventory to our available items
    QIOCraftingTransferHelper qioTransferHelper = container.getTransferHelper(player, craftingWindow);
    if (qioTransferHelper.isInvalid()) {
        Mekanism.logger.warn("Error initializing QIO transfer handler for crafting window: {}", selectedCraftingGrid);
        return handlerHelper.createInternalError();
    }
    // Note: We do this in a reversed manner (HashedItem -> slots, vs slot -> HashedItem) so that we can more easily
    // calculate the split for how we handle maxTransfer by quickly being able to see how many of each type we have
    Map<HashedItem, ByteList> matchedItems = new HashMap<>(inputCount);
    ByteSet missingSlots = new ByteArraySet(inputCount);
    for (Byte2ObjectMap.Entry<Set<HashedItem>> entry : hashedIngredients.byte2ObjectEntrySet()) {
        // TODO: Eventually we probably will want to add in some handling for if an item is valid for more than one slot and one combination
        // has it being valid and one combination it is not valid. For example if we have a single piece of stone and it is valid in either
        // slot 1 or 2 but slot 2 only allows for stone, and slot 1 can accept granite instead and we have granite available. When coming
        // up with a solution to this, we also will need to handle the slower comparison method, and make sure that if maxTransfer is true
        // then we pick the one that has the most elements we can assign to all slots evenly so that we can craft as many things as possible.
        // We currently don't bother with any handling related to this as JEI's own transfer handler it registers for things like the crafting
        // table don't currently handle this, though it is something that would be nice to handle and is something I believe vanilla's recipe
        // book transfer handler is able to do (RecipeItemHelper/ServerRecipePlayer)
        boolean matchFound = false;
        for (HashedItem validInput : entry.getValue()) {
            HashedItemSource source = qioTransferHelper.getSource(validInput);
            if (source != null && source.hasMoreRemaining()) {
                // We found a match for this slot, reduce how much of the item we have as an input
                source.matchFound();
                // mark that we found a match
                matchFound = true;
                // and which HashedItem the slot's index corresponds to
                matchedItems.computeIfAbsent(validInput, item -> new ByteArrayList()).add(entry.getByteKey());
                // and stop checking the other possible inputs
                break;
            }
        }
        if (!matchFound) {
            // If we didn't find a match for the slot, add it as a slot we may be missing
            missingSlots.add(entry.getByteKey());
        }
    }
    if (!missingSlots.isEmpty()) {
        // After doing the quicker exact match lookup checks, go through any potentially missing slots
        // and do the slower more "accurate" check of if the stacks match. This allows us to use JEI's
        // system for letting mods declare what things match when it comes down to NBT
        Map<HashedItem, String> cachedIngredientUUIDs = new HashMap<>();
        for (Map.Entry<HashedItem, HashedItemSource> entry : qioTransferHelper.reverseLookup.entrySet()) {
            HashedItemSource source = entry.getValue();
            if (source.hasMoreRemaining()) {
                // Only look at the source if we still have more items available in it
                HashedItem storedHashedItem = entry.getKey();
                ItemStack storedItem = storedHashedItem.getStack();
                Item storedItemType = storedItem.getItem();
                String storedItemUUID = null;
                for (ByteIterator missingIterator = missingSlots.iterator(); missingIterator.hasNext(); ) {
                    byte index = missingIterator.nextByte();
                    for (HashedItem validIngredient : hashedIngredients.get(index)) {
                        // Compare the raw item types
                        if (storedItemType == validIngredient.getStack().getItem()) {
                            // If they match, compute the identifiers for both stacks as needed
                            if (storedItemUUID == null) {
                                // If we haven't retrieved a UUID for the stored stack yet because none of our previous ingredients
                                // matched the basic item type, retrieve it
                                storedItemUUID = stackHelper.getUniqueIdentifierForStack(storedItem, UidContext.Recipe);
                            }
                            // Next compute the UUID for the ingredient we are missing if we haven't already calculated it
                            // either in a previous iteration or for a different slot
                            String ingredientUUID = cachedIngredientUUIDs.computeIfAbsent(validIngredient, ingredient -> stackHelper.getUniqueIdentifierForStack(ingredient.getStack(), UidContext.Recipe));
                            if (storedItemUUID.equals(ingredientUUID)) {
                                // If the items are equivalent, reduce how much of the item we have as an input
                                source.matchFound();
                                // unmark that the slot is missing a match
                                missingIterator.remove();
                                // and mark which HashedItem the slot's index corresponds to
                                matchedItems.computeIfAbsent(storedHashedItem, item -> new ByteArrayList()).add(index);
                                // and stop checking the other possible inputs
                                break;
                            }
                        }
                    }
                    if (!source.hasMoreRemaining()) {
                        // If we have "used up" all the input we have available then continue onto the next stored stack
                        break;
                    }
                }
                if (missingSlots.isEmpty()) {
                    // If we have accounted for all the slots, stop checking for matches
                    break;
                }
            }
        }
        if (!missingSlots.isEmpty()) {
            // Note: We have to shift this back up by one as we shifted the indices earlier to make them easier to work with
            return handlerHelper.createUserErrorForSlots(MekanismLang.JEI_MISSING_ITEMS.translate(), missingSlots.stream().map(i -> i + 1).collect(Collectors.toList()));
        }
    }
    if (doTransfer || (nonEmptyCraftingSlots > 0 && nonEmptyCraftingSlots >= qioTransferHelper.getEmptyInventorySlots())) {
        // Note: If all our crafting inventory slots are not empty, and we don't "obviously" have enough room due to empty slots,
        // then we need to calculate how much we can actually transfer and where it is coming from so that we are able to calculate
        // if we actually have enough room to shuffle the items around, even though otherwise we would only need to do these
        // calculations for when we are transferring items
        int toTransfer;
        if (maxTransfer) {
            // Calculate how much we can actually transfer if we want to transfer as many full sets as possible
            long maxToTransfer = Long.MAX_VALUE;
            for (Map.Entry<HashedItem, ByteList> entry : matchedItems.entrySet()) {
                HashedItem hashedItem = entry.getKey();
                HashedItemSource source = qioTransferHelper.getSource(hashedItem);
                if (source == null) {
                    // If something went wrong, and we don't actually have the item we think we do, error
                    return invalidSource(hashedItem);
                }
                int maxStack = hashedItem.getStack().getMaxStackSize();
                // If we have something that only stacks to one, such as a bucket. Don't limit the max stack size
                // of other items to one
                long max = maxStack == 1 ? maxToTransfer : Math.min(maxToTransfer, maxStack);
                // Note: This will always be at least one as the int list should not be able to become
                // larger than the number of items we have available
                maxToTransfer = Math.min(max, source.getAvailable() / entry.getValue().size());
            }
            toTransfer = MathUtils.clampToInt(maxToTransfer);
        } else {
            toTransfer = 1;
        }
        QIOFrequency frequency = container.getFrequency();
        Byte2ObjectMap<List<SingularHashedItemSource>> sources = new Byte2ObjectArrayMap<>(inputCount);
        Map<HashedItemSource, List<List<SingularHashedItemSource>>> shuffleLookup = frequency == null ? Collections.emptyMap() : new HashMap<>(inputCount);
        for (Map.Entry<HashedItem, ByteList> entry : matchedItems.entrySet()) {
            HashedItem hashedItem = entry.getKey();
            HashedItemSource source = qioTransferHelper.getSource(hashedItem);
            if (source == null) {
                // If something went wrong, and we don't actually have the item we think we do, error
                return invalidSource(hashedItem);
            }
            // Cap the amount to transfer at the max tack size. This way we allow for transferring buckets
            // and other stuff with it. This only actually matters if the max stack size is one, due to
            // the logic done above when calculating how much to transfer, but we do this regardless here
            // as there is no reason not to and then if we decide to widen it up we only have to change one spot
            int transferAmount = Math.min(toTransfer, hashedItem.getStack().getMaxStackSize());
            for (byte slot : entry.getValue()) {
                // Try to use the item and figure out where it is coming from
                List<SingularHashedItemSource> actualSources = source.use(transferAmount);
                if (actualSources.isEmpty()) {
                    // If something went wrong, and we don't actually have enough of the item for some reason, error
                    return invalidSource(hashedItem);
                }
                sources.put(slot, actualSources);
                if (frequency != null) {
                    // The shuffle lookup only comes into play if we have a frequency so might end up having to check if there is room in it
                    int elements = entry.getValue().size();
                    if (elements == 1) {
                        shuffleLookup.put(source, Collections.singletonList(actualSources));
                    } else {
                        shuffleLookup.computeIfAbsent(source, s -> new ArrayList<>(elements)).add(actualSources);
                    }
                }
            }
        }
        if (!hasRoomToShuffle(qioTransferHelper, frequency, craftingWindow, container.getHotBarSlots(), container.getMainInventorySlots(), shuffleLookup)) {
            return handlerHelper.createUserErrorWithTooltip(MekanismLang.JEI_INVENTORY_FULL.translate());
        }
        if (doTransfer) {
            // Note: We skip doing a validation check on if the recipe matches or not, as there is a chance that for some recipes
            // things may not fully be accurate on the client side with the stacks that JEI lets us know match the recipe, as
            // they may require extra NBT that is server side only.
            // TODO: If the sources are all from the crafting window and are already in the correct spots, there is no need to send this packet
            Mekanism.packetHandler.sendToServer(new PacketQIOFillCraftingWindow(recipe.getId(), maxTransfer, sources));
        }
    }
    return null;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PacketQIOFillCraftingWindow(mekanism.common.network.to_server.PacketQIOFillCraftingWindow) Object2BooleanMap(it.unimi.dsi.fastutil.objects.Object2BooleanMap) Object2IntArrayMap(it.unimi.dsi.fastutil.objects.Object2IntArrayMap) HashedItemSource(mekanism.common.content.qio.QIOCraftingTransferHelper.HashedItemSource) SingularHashedItemSource(mekanism.common.content.qio.QIOCraftingTransferHelper.SingularHashedItemSource) IStackHelper(mezz.jei.api.helpers.IStackHelper) Item(net.minecraft.item.Item) ByteSet(it.unimi.dsi.fastutil.bytes.ByteSet) Object2BooleanArrayMap(it.unimi.dsi.fastutil.objects.Object2BooleanArrayMap) UidContext(mezz.jei.api.ingredients.subtypes.UidContext) BaseSimulatedInventory(mekanism.common.content.qio.QIOCraftingTransferHelper.BaseSimulatedInventory) ICraftingRecipe(net.minecraft.item.crafting.ICraftingRecipe) ByteIterator(it.unimi.dsi.fastutil.bytes.ByteIterator) Map(java.util.Map) CraftingInventory(net.minecraft.inventory.CraftingInventory) ByteArraySet(it.unimi.dsi.fastutil.bytes.ByteArraySet) IRecipeLayout(mezz.jei.api.gui.IRecipeLayout) IRecipeTransferError(mezz.jei.api.recipe.transfer.IRecipeTransferError) HashedItem(mekanism.common.lib.inventory.HashedItem) PlayerEntity(net.minecraft.entity.player.PlayerEntity) QIOItemViewerContainer(mekanism.common.inventory.container.QIOItemViewerContainer) StackUtils(mekanism.common.util.StackUtils) Set(java.util.Set) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) MekanismUtils(mekanism.common.util.MekanismUtils) List(java.util.List) Byte2ObjectArrayMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectArrayMap) MekanismLang(mekanism.common.MekanismLang) IRecipeTransferHandler(mezz.jei.api.recipe.transfer.IRecipeTransferHandler) MainInventorySlot(mekanism.common.inventory.container.slot.MainInventorySlot) HotBarSlot(mekanism.common.inventory.container.slot.HotBarSlot) HashMap(java.util.HashMap) QIOCraftingWindow(mekanism.common.content.qio.QIOCraftingWindow) ArrayList(java.util.ArrayList) ItemStack(net.minecraft.item.ItemStack) ByteList(it.unimi.dsi.fastutil.bytes.ByteList) QIOFrequency(mekanism.common.content.qio.QIOFrequency) IRecipeTransferHandlerHelper(mezz.jei.api.recipe.transfer.IRecipeTransferHandlerHelper) Byte2ObjectMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectMap) Nonnull(javax.annotation.Nonnull) LinkedHashSet(java.util.LinkedHashSet) Nullable(javax.annotation.Nullable) Mekanism(mekanism.common.Mekanism) QIOCraftingTransferHelper(mekanism.common.content.qio.QIOCraftingTransferHelper) MathUtils(mekanism.api.math.MathUtils) CraftingWindowInventorySlot(mekanism.common.inventory.slot.CraftingWindowInventorySlot) IGuiIngredient(mezz.jei.api.gui.ingredient.IGuiIngredient) Object2IntMap(it.unimi.dsi.fastutil.objects.Object2IntMap) IInventorySlot(mekanism.api.inventory.IInventorySlot) ByteArrayList(it.unimi.dsi.fastutil.bytes.ByteArrayList) Collections(java.util.Collections) HashedItem(mekanism.common.lib.inventory.HashedItem) ByteSet(it.unimi.dsi.fastutil.bytes.ByteSet) ByteArraySet(it.unimi.dsi.fastutil.bytes.ByteArraySet) Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) HashedItemSource(mekanism.common.content.qio.QIOCraftingTransferHelper.HashedItemSource) SingularHashedItemSource(mekanism.common.content.qio.QIOCraftingTransferHelper.SingularHashedItemSource) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ByteArrayList(it.unimi.dsi.fastutil.bytes.ByteArrayList) Item(net.minecraft.item.Item) HashedItem(mekanism.common.lib.inventory.HashedItem) PacketQIOFillCraftingWindow(mekanism.common.network.to_server.PacketQIOFillCraftingWindow) ICraftingRecipe(net.minecraft.item.crafting.ICraftingRecipe) ByteArrayList(it.unimi.dsi.fastutil.bytes.ByteArrayList) List(java.util.List) ArrayList(java.util.ArrayList) ByteList(it.unimi.dsi.fastutil.bytes.ByteList) ByteArrayList(it.unimi.dsi.fastutil.bytes.ByteArrayList) Byte2ObjectArrayMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectArrayMap) CraftingWindowInventorySlot(mekanism.common.inventory.slot.CraftingWindowInventorySlot) CraftingInventory(net.minecraft.inventory.CraftingInventory) ByteList(it.unimi.dsi.fastutil.bytes.ByteList) QIOCraftingWindow(mekanism.common.content.qio.QIOCraftingWindow) SingularHashedItemSource(mekanism.common.content.qio.QIOCraftingTransferHelper.SingularHashedItemSource) Byte2ObjectMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectMap) ByteArraySet(it.unimi.dsi.fastutil.bytes.ByteArraySet) ByteIterator(it.unimi.dsi.fastutil.bytes.ByteIterator) QIOCraftingTransferHelper(mekanism.common.content.qio.QIOCraftingTransferHelper) ItemStack(net.minecraft.item.ItemStack) Object2BooleanMap(it.unimi.dsi.fastutil.objects.Object2BooleanMap) Object2IntArrayMap(it.unimi.dsi.fastutil.objects.Object2IntArrayMap) Object2BooleanArrayMap(it.unimi.dsi.fastutil.objects.Object2BooleanArrayMap) Map(java.util.Map) Byte2ObjectArrayMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectArrayMap) HashMap(java.util.HashMap) Byte2ObjectMap(it.unimi.dsi.fastutil.bytes.Byte2ObjectMap) Object2IntMap(it.unimi.dsi.fastutil.objects.Object2IntMap) ByteSet(it.unimi.dsi.fastutil.bytes.ByteSet) QIOFrequency(mekanism.common.content.qio.QIOFrequency) Nullable(javax.annotation.Nullable)

Example 13 with CraftingInventory

use of net.minecraft.inventory.CraftingInventory in project SophisticatedBackpacks by P3pp3rF1y.

the class BackpackUpgradeRecipe method assemble.

@Override
public ItemStack assemble(CraftingInventory inv) {
    ItemStack upgradedBackpack = super.assemble(inv);
    getBackpack(inv).flatMap(backpack -> Optional.ofNullable(backpack.getTag())).ifPresent(tag -> upgradedBackpack.setTag(tag.copy()));
    upgradedBackpack.getCapability(CapabilityBackpackWrapper.getCapabilityInstance()).ifPresent(wrapper -> {
        BackpackItem backpackItem = ((BackpackItem) upgradedBackpack.getItem());
        wrapper.setSlotNumbers(backpackItem.getNumberOfSlots(), backpackItem.getNumberOfUpgradeSlots());
    });
    return upgradedBackpack;
}
Also used : ItemStack(net.minecraft.item.ItemStack) IRecipeSerializer(net.minecraft.item.crafting.IRecipeSerializer) CapabilityBackpackWrapper(net.p3pp3rf1y.sophisticatedbackpacks.api.CapabilityBackpackWrapper) CraftingInventory(net.minecraft.inventory.CraftingInventory) Optional(java.util.Optional) ShapedRecipe(net.minecraft.item.crafting.ShapedRecipe) BackpackItem(net.p3pp3rf1y.sophisticatedbackpacks.backpack.BackpackItem) ItemStack(net.minecraft.item.ItemStack) BackpackItem(net.p3pp3rf1y.sophisticatedbackpacks.backpack.BackpackItem)

Example 14 with CraftingInventory

use of net.minecraft.inventory.CraftingInventory in project minecolonies by ldtteam.

the class GenericRecipe method calculateSecondaryOutputs.

@NotNull
private static List<ItemStack> calculateSecondaryOutputs(@NotNull final IRecipe<?> recipe) {
    if (recipe instanceof ICraftingRecipe) {
        final List<Ingredient> inputs = recipe.getIngredients();
        final CraftingInventory inv = new CraftingInventory(new Container(ContainerType.CRAFTING, 0) {

            @Override
            public boolean stillValid(@NotNull final PlayerEntity playerIn) {
                return false;
            }
        }, 3, 3);
        for (int slot = 0; slot < inputs.size(); ++slot) {
            final ItemStack[] stacks = inputs.get(slot).getItems();
            if (stacks.length > 0) {
                inv.setItem(slot, stacks[0]);
            }
        }
        if (((ICraftingRecipe) recipe).matches(inv, null)) {
            return ((ICraftingRecipe) recipe).getRemainingItems(inv).stream().filter(ItemStackUtils::isNotEmpty).filter(// this is filtered out of the inputs too
            stack -> stack.getItem() != buildTool.get()).collect(Collectors.toList());
        }
    }
    return Collections.emptyList();
}
Also used : CraftingInventory(net.minecraft.inventory.CraftingInventory) IRecipe(net.minecraft.item.crafting.IRecipe) Ingredient(net.minecraft.item.crafting.Ingredient) java.util(java.util) PlayerEntity(net.minecraft.entity.player.PlayerEntity) ItemStackUtils(com.minecolonies.api.util.ItemStackUtils) Container(net.minecraft.inventory.container.Container) IColonyManager(com.minecolonies.api.colony.IColonyManager) IToken(com.minecolonies.api.colony.requestsystem.token.IToken) FurnaceRecipe(net.minecraft.item.crafting.FurnaceRecipe) Collectors(java.util.stream.Collectors) Blocks(net.minecraft.block.Blocks) ContainerType(net.minecraft.inventory.container.ContainerType) ITextComponent(net.minecraft.util.text.ITextComponent) ItemStack(net.minecraft.item.ItemStack) ICraftingRecipe(net.minecraft.item.crafting.ICraftingRecipe) Nullable(org.jetbrains.annotations.Nullable) Stream(java.util.stream.Stream) Block(net.minecraft.block.Block) CraftingInventory(net.minecraft.inventory.CraftingInventory) ResourceLocation(net.minecraft.util.ResourceLocation) ModItems.buildTool(com.ldtteam.structurize.items.ModItems.buildTool) NotNull(org.jetbrains.annotations.NotNull) OptionalPredicate(com.minecolonies.api.util.OptionalPredicate) Container(net.minecraft.inventory.container.Container) ICraftingRecipe(net.minecraft.item.crafting.ICraftingRecipe) Ingredient(net.minecraft.item.crafting.Ingredient) ItemStackUtils(com.minecolonies.api.util.ItemStackUtils) ItemStack(net.minecraft.item.ItemStack) PlayerEntity(net.minecraft.entity.player.PlayerEntity) NotNull(org.jetbrains.annotations.NotNull)

Example 15 with CraftingInventory

use of net.minecraft.inventory.CraftingInventory in project minecolonies by ldtteam.

the class CraftingGuiHandler method updateServer.

@Override
protected void updateServer(@NotNull final WindowCrafting gui) {
    final Map<Integer, ItemStack> matrix = new HashMap<>();
    final CraftingInventory inventory = gui.getMenu().getInv();
    if (gui.isCompleteCrafting()) {
        for (int i = 0; i < 9; ++i) {
            matrix.put(i, inventory.getItem(i));
        }
    } else {
        matrix.put(0, inventory.getItem(0));
        matrix.put(1, inventory.getItem(1));
        matrix.put(3, inventory.getItem(2));
        matrix.put(4, inventory.getItem(3));
    }
    final TransferRecipeCraftingTeachingMessage message = new TransferRecipeCraftingTeachingMessage(matrix, gui.isCompleteCrafting());
    Network.getNetwork().sendToServer(message);
}
Also used : CraftingInventory(net.minecraft.inventory.CraftingInventory) TransferRecipeCraftingTeachingMessage(com.minecolonies.coremod.network.messages.server.TransferRecipeCraftingTeachingMessage) ItemStack(net.minecraft.item.ItemStack)

Aggregations

CraftingInventory (net.minecraft.inventory.CraftingInventory)17 ItemStack (net.minecraft.item.ItemStack)12 ArrayList (java.util.ArrayList)6 List (java.util.List)6 PlayerEntity (net.minecraft.entity.player.PlayerEntity)5 TransferRecipeCraftingTeachingMessage (com.minecolonies.coremod.network.messages.server.TransferRecipeCraftingTeachingMessage)4 HashMap (java.util.HashMap)4 ICraftingRecipe (net.minecraft.item.crafting.ICraftingRecipe)4 Map (java.util.Map)3 Set (java.util.Set)3 Collectors (java.util.stream.Collectors)3 IInventory (net.minecraft.inventory.IInventory)3 IRecipeType (net.minecraft.item.crafting.IRecipeType)3 ITextComponent (net.minecraft.util.text.ITextComponent)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 ModItems.buildTool (com.ldtteam.structurize.items.ModItems.buildTool)2 IColonyManager (com.minecolonies.api.colony.IColonyManager)2 IToken (com.minecolonies.api.colony.requestsystem.token.IToken)2 IGenericRecipe (com.minecolonies.api.crafting.IGenericRecipe)2 ItemStackUtils (com.minecolonies.api.util.ItemStackUtils)2