Jump to content

[Solved]Crafting recipe with ItemStack inputs


Jay Avery

Recommended Posts

I want to make crafting recipes that require some of the input ItemStacks to have a stack size of greater than 1. I've worked out how to check the stack sizes when checking if the craft matrix matches the recipe, but I have no idea what to do with

getRemainingItems

. Looking at the forge vanilla code, I can't figure out what the

ForgeHooks.getContainerItem

method does, or how to adjust it so that the remaining items have the required stack size subtracted. I'm sure I've seen someone write about making crafting recipes with non-one stack sizes before but I can't find anything now. Can anyone advise and/or link me to somewhere it's been done?

 

My custom recipe class is here. It correctly detects whether the input ItemStacks are large enough (the output slot only shows the output when they are), but when I click on the output the crafting grid slots don't seem to change correctly.

 

package com.jj.jjmod.crafting;

import java.util.Arrays;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ShapedRecipes;
import net.minecraft.world.World;

public class ShapedRecipe extends ShapedRecipes {

    public ShapedRecipe(int width, int height, ItemStack[] inputs,
            ItemStack output) {

        super(width, height, inputs, output);

    }

    @Override
    public boolean matches(InventoryCrafting inv, World worldIn) {

        for (int i = 0; i <= inv.getWidth() - this.recipeWidth; i++) {

            for (int j = 0; j <= inv.getHeight() - this.recipeHeight; j++) {

                if (this.checkMatch(inv, i, j, true) ||
                        this.checkMatch(inv, i, j, false)) {

                    return true;
                }
            }
        }

        return false;
    }

    private boolean checkMatch(InventoryCrafting inv, int a, int b,
            boolean flag) {

        for (int i = 0; i < inv.getWidth(); ++i) {

            for (int j = 0; j < inv.getHeight(); ++j) {

                int k = i - a;
                int l = j - b;
                ItemStack required = null;

                if (k >= 0 && l >= 0 && k < this.recipeWidth &&
                        l < this.recipeHeight) {

                    if (flag) {

                        required = this.recipeItems[this.recipeWidth -
                                k - 1 + l * this.recipeWidth];

                    } else {

                        required = this.recipeItems[k + l * this.recipeWidth];
                    }
                }

                ItemStack inInv = inv.getStackInRowAndColumn(i, j);

                if (inInv != null || required != null) {

                    if (inInv == null && required != null ||
                            inInv != null && required == null) {

                        return false;
                    }

                    if (required.getItem() != inInv.getItem()) {

                        return false;
                    }

                    if (required.getMetadata() != 32767 &&
                            required.getMetadata() != inInv.getMetadata()) {

                        return false;
                    }

                    if (required.stackSize > inInv.stackSize) {
                        
                        return false;
                    }
                }
            }
        }

        return true;
    }
}

 

 

Edit: I think I've solved this, although I don't know if it's the best way I could have done it (I suspect it's very much not). I made a new method in my custom recipe class that returns an array of ints representing how many items from each input stack should be used up. (The code is more or less the same as the way it checks for a matching recipe in the first place, because it has to find the recipe's position in the grid and then check each slot individually). Then I call that in my custom crafting slot's

onPickupFromSlot

(the same place where

getRemainingItems

is called) and use it to decrease the crafting grid stack sizes.

 

Here is the code of my new method:

 

    public int[] getAmountsUsed(InventoryCrafting inv) {
        
        int a = -1;
        int b = -1;
        boolean flag = true;
        
        outer:
        for (int i = 0; i <= inv.getWidth() - this.recipeWidth; i++) {

            for (int j = 0; j <= inv.getHeight() - this.recipeHeight; j++) {

                if (this.checkMatch(inv, i, j, true)) {

                    a = i;
                    b = j;
                    flag = true;
                    break outer;
                }
                
                if (this.checkMatch(inv, i, j, false)) {
                    
                    a = i;
                    b = j;
                    flag = false;
                    break outer;
                }
            }
        }
        
        int[] amounts = new int[inv.getSizeInventory()];
        
        for (int i = 0; i < inv.getWidth(); ++i) {

            for (int j = 0; j < inv.getHeight(); ++j) {

                int k = i - a;
                int l = j - b;
                int amount = (j * inv.getWidth()) + i;
                amounts[amount] = 0;

                if (k >= 0 && l >= 0 && k < this.recipeWidth &&
                        l < this.recipeHeight) {

                    if (flag) {

                        amounts[amount] = this.recipeItems[this.recipeWidth -
                                k - 1 + l * this.recipeWidth].stackSize;

                    } else {

                        amounts[amount] = this.recipeItems[k + l *
                                this.recipeWidth].stackSize;
                    }
                }
            }
        }

        return amounts;
    }

 

 

Like I said I have no idea if this is a good way to do it. It seems to work, but although it seems really messy I can't think of a better way at the moment. If anyone has any ideas please let me know.

Link to comment
Share on other sites

On how to implement

getRemainingItems

to use up more than one of the input ItemStack.

 

It seems to be intended only for things like buckets where one item replaces another. But the reduction in stack size of the input items is actually done in

SlotCrafting#onPickupFromSlot

. So I need some way to get the information about which input stacks are reduced by which amounts (including the potential for the recipe to be in different positions in the crafting grid), and send that back to the crafting slot (which I have extended with my own class so I can do what I want there) to update it when the output is removed.

 

Maybe a new method in my recipe that's like

getRemainingItems

but returns an array of ints to subtract from the input stack sizes? The trouble is,

getRemainingItems

just checks the items individually so the positioning of the recipe is irrelevant. But I'd ideally like to be able to have a recipe requiring any amount of different-sized stacks of the same or different items, which would mean somehow checking the input grid to find the exact position of the recipe, getting the stack size reductions, and then converting that to the size and shape of the crafting grid before returning it to be used by the slot. Seems a bit excessive but I can't think of a simpler way at the moment. :S

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.