Jump to content

[1.8]Help with Custom Crafting Table and Recipes


Nodnarb3

Recommended Posts

I've got almost everything working correctly as a custom crafting table with its own recipes working,

except when the item crafted is picked up from the output slot, the itemstacks in the crafting matrix are never decremented.

This wasn't an issue in 1.7.2, but now it appears to be quite the problem.

 

Container Code:

 

public class ContainerKnappingStone extends Container
{
public InventoryCrafting craftMatrix;
public IInventory craftResult;
private World world;
private BlockPos pos;

private int verticalSlots = 5;
private int horizontalSlots = 5;

public ContainerKnappingStone(InventoryPlayer inventory, World world, BlockPos pos)
{
	craftMatrix = new InventoryCrafting(this, horizontalSlots, verticalSlots);
	craftResult = new InventoryCraftResult();
	this.world = world;
	this.pos = pos;

	//Output Slot
	this.addSlotToContainer(new SlotCrafting(inventory.player, craftMatrix, craftResult, 0, 140, 54));

	//Crafting Grid
	for(int y = 0; y < verticalSlots; y++)
	{
		for(int x = 0; x < horizontalSlots; x++)
		{
			this.addSlotToContainer(new Slot(craftMatrix, x + y * horizontalSlots, 8 + x * 18, 17 + y * 18));
		}
	}

	//Inventory
	for(int y = 0; y < 3; y++)
	{
		for(int x = 0; x < 9; x++)
		{
			this.addSlotToContainer(new Slot(inventory, x + y * 9 + 9, 8 + x * 18, 120 + y * 18));
		}
	}

	//Hotbar
	for(int x = 0; x < 9; x++)
	{
		this.addSlotToContainer(new Slot(inventory, x, 8 + x * 18, 178));
	}

	onCraftMatrixChanged(craftMatrix);
}

@Override
public void onCraftMatrixChanged(IInventory iinventory)
{
	craftResult.setInventorySlotContents(0, KnappingStoneCraftingManager.getInstance().findMatchingRecipe(craftMatrix, world));
}

@Override
public void onContainerClosed(EntityPlayer player)
{
	super.onContainerClosed(player);
	if(!world.isRemote)
	{
		for(int i = 0; i < verticalSlots * horizontalSlots; i++)
		{
			ItemStack itemstack = craftMatrix.getStackInSlotOnClosing(i);

			if(itemstack != null)
			{
				player.dropPlayerItemWithRandomChoice(itemstack, false);
			}
		}
	}
}

@Override
public boolean canInteractWith(EntityPlayer player)
{
	if(world.getBlockState(pos).getBlock() != SurvivalPlusBlocks.knapping_stone)
	{
		return false;
	}
	else
	{
		return player.getDistanceSq((double)pos.getX() + 0.5d, (double)pos.getY() + 0.5d, (double)pos.getZ() + 0.5d) <= 64.0d;
	}
}

@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
	ItemStack itemstack = null;
	Slot slot = (Slot) inventorySlots.get(index);

	if(slot != null && slot.getHasStack())
	{
		ItemStack itemstack1 = slot.getStack();
		itemstack = itemstack1.copy();

		if(index == 0)
		{
			if(!mergeItemStack(itemstack1, 26, 62, true))
			{
				return null;
			}

			slot.onSlotChange(itemstack1, itemstack);
		}
		else if(index >= 26 && index < 53)
		{
			if (!mergeItemStack(itemstack1, 53, 62, false))
                {
                    return null;
                }
		}
		else if(index >= 53 && index < 62)
		{
			if (!mergeItemStack(itemstack1, 26, 53, false))
                {
                    return null;
                }
		}
		else if(!mergeItemStack(itemstack1, 26, 62, false))
		{
			return null;
		}

		if(itemstack1.stackSize == 0)
		{
			slot.putStack(null);
		}
		else
		{
			slot.onSlotChanged();
		}

		if(itemstack1.stackSize == itemstack.stackSize)
		{
			return null;
		}

		slot.onPickupFromSlot(player, itemstack1);
	}

	return itemstack;
}

}

 

 

CraftingManager:

 

public class KnappingStoneCraftingManager 
{
private static final KnappingStoneCraftingManager instance = new KnappingStoneCraftingManager();

private List recipes = new ArrayList();

private KnappingStoneCraftingManager()
{
	//FIXME: Crafting is BORKED!
	recipes = new ArrayList();

	/*Add recipes here*/
	this.addRecipe(new ItemStack(SurvivalPlusItems.heavy_tool_binding, 2), new Object[] {"R R R", 'R', SurvivalPlusItems.rock_item});
	this.addShapelessRecipe(new ItemStack(SurvivalPlusItems.heavy_tool_binding, 1), new Object[]{SurvivalPlusItems.rock_item});

	Collections.sort(this.recipes, new KnappingStoneRecipeSorter(this));
}

public KnappingStoneShapedRecipes addRecipe(ItemStack result, Object ...  objArray)
{
	String str = "";
	int i = 0; 
	int j = 0;
	int k = 0;

	if(objArray[i] instanceof String[])
	{
		String[] astr = (String[])(String[])objArray[i++];

		for(int l = 0; l < astr.length; ++l)
		{
			String str1 = astr[l];
			++k;
			j = str1.length();
			str += str1;
		}
	}
	else
	{
		while(objArray[i] instanceof String)
		{
			String str2 = (String)objArray[i++];
			++k;
			j = str2.length();
			str += str2;
		}
	}

	HashMap hashmap;

	for(hashmap = new HashMap(); i < objArray.length; i+= 2)
	{
		Character character = (Character)objArray[i];
		ItemStack itemstack1 = null;

		if(objArray[i+1] instanceof Item)
		{
			itemstack1 = new ItemStack((Item)objArray[i + 1]);
		}
		else if(objArray[i+1] instanceof Block)
		{
			itemstack1 = new ItemStack((Block)objArray[i + 1]);
		}
		else if(objArray[i+1] instanceof ItemStack)
		{
			itemstack1 = (ItemStack)objArray[i + 1];
		}

		hashmap.put(character, itemstack1);
	}

	ItemStack[] aitemstack = new ItemStack[j * k];

	for(int m = 0; m < j * k; ++m)
	{
		char c = str.charAt(m);

		if(hashmap.containsKey(Character.valueOf(c)))
		{
			aitemstack[m] = ((ItemStack)hashmap.get(Character.valueOf(c))).copy();
		}
		else
		{
			aitemstack[m] = null;
		}
	}

	KnappingStoneShapedRecipes shapedRecipies = new KnappingStoneShapedRecipes(j, k, aitemstack, result);
	this.recipes.add(shapedRecipies);
	return shapedRecipies;
}

public void addShapelessRecipe(ItemStack itemstack, Object ... objArray)
{
	ArrayList alist = new ArrayList();
	Object[] aobj = objArray;
	int i = objArray.length;

	for(int j = 0; j < i; ++j)
	{
		Object obj = aobj[j];

		if(obj instanceof ItemStack)
		{
			alist.add(((ItemStack)obj).copy());
		}
		else if(obj instanceof Item)
		{
			alist.add(new ItemStack((Item)obj));
		}
		else
		{
			if(!(obj instanceof Block))
			{
				throw new RuntimeException("Invalid Shapeless Recipe");
			}

			alist.add(new ItemStack((Block)obj));
		}
	}

	this.recipes.add(new ShapelessRecipes(itemstack, alist));
}

public ItemStack findMatchingRecipe(InventoryCrafting inventory, World world)
{
	int i = 0;
	ItemStack is1 = null;
	ItemStack is2 = null;
	int j;

	for(j = 0; j < inventory.getSizeInventory(); ++j)
	{
		ItemStack is3 = inventory.getStackInSlot(j);

		if(is3 != null)
		{
			if(i == 0)
				is1 =is3;
			if(i == 1)
				is2 = is3;
			++i;
		}
	}

	if(i == 2 && is1.getIsItemStackEqual(is2) && is1.stackSize == 1 && is2.stackSize == 1 && is1.getItem().isRepairable())
	{
		Item item = is1.getItem();
		int h = item.getMaxDamage() - is1.getItemDamage(); //TODO: Might have some oddity here since getItemDamageForDisplay doesn't exist
		int k = item.getMaxDamage() - is2.getItemDamage(); 
		int l = h + k + item.getMaxDamage() * 5/100;
		int m = item.getMaxDamage() - l;

		if(m < 0)
			m = 0;

		return new ItemStack(is1.getItem(), 1, m);
	}
	else
	{
		for(j = 0; j < this.recipes.size(); ++j)
		{
			IRecipe irecipie = (IRecipe)this.recipes.get(j);
			if(irecipie.matches(inventory, world))
			{
				return irecipie.getCraftingResult(inventory);
			}
		}
		return null;
	}
}

public List getRecipes()
{
	return this.recipes;
}

public static final KnappingStoneCraftingManager getInstance()
{
	return instance;
}
}

 

 

ShapedRecipes:

 

package net.nod3.survivalplus.crafting;
public class KnappingStoneShapedRecipes implements IRecipe
{

    /** How many horizontal slots this recipe is wide. */
    public final int recipeWidth;
    /** How many vertical slots this recipe uses. */
    public final int recipeHeight;
    /** Is a array of ItemStack that composes the recipe. */
    public final ItemStack[] recipeItems;
    /** Is the ItemStack that you get when craft the recipe. */
    private ItemStack recipeOutput;
    private boolean field_92101_f;
    private static final String __OBFID = "CL_00000093";

    public KnappingStoneShapedRecipes(int par1, int par2, ItemStack[] par3ArrayOfItemStack, ItemStack par4ItemStack)
    {
        this.recipeWidth = par1;
        this.recipeHeight = par2;
        this.recipeItems = par3ArrayOfItemStack;
        this.recipeOutput = par4ItemStack;
    }

    public ItemStack getRecipeOutput()
    {
        return this.recipeOutput;
    }

    /**
     * Used to check if a recipe matches current crafting inventory
     */
    public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World)
    {
        for (int i = 0; i <= 5 - this.recipeWidth; ++i)
        {
            for (int j = 0; j <= 5 - this.recipeHeight; ++j)
            {
                if (this.checkMatch(par1InventoryCrafting, i, j, true))
                {
                    return true;
                }

                if (this.checkMatch(par1InventoryCrafting, i, j, false))
                {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Checks if the region of a crafting inventory is match for the recipe.
     */
    private boolean checkMatch(InventoryCrafting par1InventoryCrafting, int par2, int par3, boolean par4)
    {
        for (int k = 0; k < 5; ++k)
        {
            for (int l = 0; l < 5; ++l)
            {
                int i1 = k - par2;
                int j1 = l - par3;
                ItemStack itemstack = null;

                if (i1 >= 0 && j1 >= 0 && i1 < this.recipeWidth && j1 < this.recipeHeight)
                {
                    if (par4)
                    {
                        itemstack = this.recipeItems[this.recipeWidth - i1 - 1 + j1 * this.recipeWidth];
                    }
                    else
                    {
                        itemstack = this.recipeItems[i1 + j1 * this.recipeWidth];
                    }
                }

                ItemStack itemstack1 = par1InventoryCrafting.getStackInRowAndColumn(k, l);

                if (itemstack1 != null || itemstack != null)
                {
                    if (itemstack1 == null && itemstack != null || itemstack1 != null && itemstack == null)
                    {
                        return false;
                    }

                    if (itemstack.getItem() != itemstack1.getItem())
                    {
                        return false;
                    }

                    if (itemstack.getItemDamage() != 32767 && itemstack.getItemDamage() != itemstack1.getItemDamage())
                    {
                        return false;
                    }
                }
            }
        }

        return true;
    }

    /**
     * Returns an Item that is the result of this recipe
     */
    public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting)
    {
        ItemStack itemstack = this.getRecipeOutput().copy();

        if (this.field_92101_f)
        {
            for (int i = 0; i < par1InventoryCrafting.getSizeInventory(); ++i)
            {
                ItemStack itemstack1 = par1InventoryCrafting.getStackInSlot(i);

                if (itemstack1 != null && itemstack1.hasTagCompound())
                {
                    itemstack.setTagCompound((NBTTagCompound)itemstack1.getTagCompound().copy());
                }
            }
        }

        return itemstack;
    }

    /**
     * Returns the size of the recipe area
     */
    public int getRecipeSize()
    {
        return this.recipeWidth * this.recipeHeight;
    }

    public KnappingStoneShapedRecipes func_92100_c()
    {
        this.field_92101_f = true;
        return this;
    }

@Override
public ItemStack[] getRemainingItems(InventoryCrafting invCrafting)
{
	return null;
}

}

 

 

ShapelessRecipes:

 

public class KnappingStoneShapelessRecipies implements IRecipe
{
    /** Is the ItemStack that you get when craft the recipe. */
    private final ItemStack recipeOutput;
    /** Is a List of ItemStack that composes the recipe. */
    public final List recipeItems;
    private static final String __OBFID = "CL_00000094";

    public KnappingStoneShapelessRecipies(ItemStack par1ItemStack, List par2List)
    {
        this.recipeOutput = par1ItemStack;
        this.recipeItems = par2List;
    }

    public ItemStack getRecipeOutput()
    {
        return this.recipeOutput;
    }

    /**
     * Used to check if a recipe matches current crafting inventory
     */
    public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World)
    {
        ArrayList arraylist = new ArrayList(this.recipeItems);

        for (int i = 0; i < 5; ++i)
        {
            for (int j = 0; j < 5; ++j)
            {
                ItemStack itemstack = par1InventoryCrafting.getStackInRowAndColumn(j, i);

                if (itemstack != null)
                {
                    boolean flag = false;
                    Iterator iterator = arraylist.iterator();

                    while (iterator.hasNext())
                    {
                        ItemStack itemstack1 = (ItemStack)iterator.next();

                        if (itemstack.getItem() == itemstack1.getItem() && (itemstack1.getItemDamage() == 32767 || itemstack.getItemDamage() == itemstack1.getItemDamage()))
                        {
                            flag = true;
                            arraylist.remove(itemstack1);
                            break;
                        }
                    }

                    if (!flag)
                    {
                        return false;
                    }
                }
            }
        }

        return arraylist.isEmpty();
    }

    /**
     * Returns an Item that is the result of this recipe
     */
    public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting)
    {
        return this.recipeOutput.copy();
    }

    /**
     * Returns the size of the recipe area
     */
    public int getRecipeSize()
    {
        return this.recipeItems.size();
    }

@Override
public ItemStack[] getRemainingItems(InventoryCrafting p_179532_1_) {
	// TODO Auto-generated method stub
	return null;
}
}

 

 

I'm not sure if there is a callback somewhere that I'm missing, but when items are placed into the grid, the appropriate result appears in the output slot. I can take the item out of the output slot, but another one appears in the slot, and the items in the crafting grid do not get removed, or their stack size does not decrement.

 

When a shaped recipe is in the grid, it does decrement, but leaves itemstacks with size 0, that can still be picked up and used. If shift clicking on the output, it will fill the inventory with items, and still leave an itemstack of size 0 in the crafting grid.

 

When a shapeless recipe is in the grid, it doesnt decrement the itemstacks at all, and if shift clicking the output slot, it will cause a crash, from what I can tell, due to an infinite loop from Container.slotClick and Container.retrySlotClick

 

EDIT: Solved the problem crashing, now shaped recipes and shapeless recipes act the same way, never decrementing craftMatrix stacks causing an infinite number of items to be crafted.

 

Really not sure what to do here, any help would be truly appreciated.

Thanks.

//Nodnarb3

 

//Nodnarb3

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.

Announcements



×
×
  • Create New...

Important Information

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