Jump to content

[1.14 and 1.15] Make recipe book autofilling ignore data tags of ingredients


TheOnlyTrueEnte

Recommended Posts

I'm currently working on recipes for my custom paxel mod.
Explanation with pictures:

Spoiler

Recipe book works if all ingredients are undamaged and unenchanted:

gSeOGAP.png

Recipe book fails if any ingredient is damaged (or has any other NBT data):

yTks1nc.png

The recipe does, however, work with damaged items:

aIevfhE.png

 

I created a custom recipe class for the recipe. The recipe accepts an axe, pickaxe, shovel and two sticks and yields a paxel. My recipe also works if the tools are damaged: the result is a damaged paxel. My problem is that when clicking on the recipe in the recipe book, it doesn't accept damaged items (or even undamaged, enchanted ones) from my inventory.

 

Code of the 1.14.4 project for reference:

In this version of the code, I hadn't written a proper json serializer yet so my recipe constructor is hardcoded to create the recipe for the golden paxel. This is probably more readable anyway.

Spoiler

package com.theonlytrueente.entespaxel.item.crafting;

import com.google.gson.JsonObject;
import com.theonlytrueente.entespaxel.EntesPaxel;
import com.theonlytrueente.entespaxel.lists.EnteItems;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.common.crafting.IShapedRecipe;
import net.minecraftforge.registries.ForgeRegistryEntry;

import javax.annotation.Nullable;
import java.util.LinkedList;
import java.util.List;

public class PaxelRecipe implements ICraftingRecipe, IShapedRecipe<CraftingInventory> {

    private final ResourceLocation id;
    private final Item pickaxe, shovel, axe;
    private final Item paxel;
    private final Item stick;

    public PaxelRecipe(ResourceLocation idIn) {
        id = idIn;
        pickaxe = Items.GOLDEN_PICKAXE;
        shovel = Items.GOLDEN_SHOVEL;
        axe = Items.GOLDEN_AXE;
        paxel = EnteItems.GOLDEN_PAXEL;
        stick = Items.STICK;
    }

    @Override
    public boolean matches(CraftingInventory inv, World worldIn) {
        for(int x=0; x<=inv.getWidth()-3; x++){
            for(int y=0; y<=inv.getHeight()-3; y++){
                if(checkMatch(inv, x, y) != -1) {
                    return true;
                }
            }
        }
        return false;
    }

  	//returns -1 if no match, otherwise returns the damage of the result.
    private int checkMatch(CraftingInventory craftingInventory, int widthOffset, int heightOffset) {
        //check top row first
        List<Item> toolIngredients= new LinkedList<>();
        toolIngredients.add(pickaxe); toolIngredients.add(shovel); toolIngredients.add(axe);
        int totalDamage = 0;
        for(int x=0; x<3; x++){
            ItemStack stack = craftingInventory.getStackInSlot(x+widthOffset + heightOffset * craftingInventory.getWidth());
            if(toolIngredients.remove(stack.getItem())){
                totalDamage += stack.getItem() != shovel ? stack.getDamage()*3 : stack.getDamage();
            }
            else return -1;
        }
        if(totalDamage >= new ItemStack(paxel, 1).getMaxDamage()) return -1;
        //check sticks now
        for(int y=1; y<3; y++){
            if(!Ingredient.EMPTY.test(craftingInventory.getStackInSlot(widthOffset + (heightOffset+y) * craftingInventory.getWidth()))
                || !(stick == (craftingInventory.getStackInSlot(1 + widthOffset + (heightOffset+y) * craftingInventory.getWidth())).getItem())
                || !Ingredient.EMPTY.test(craftingInventory.getStackInSlot(2 + widthOffset + (heightOffset+y) * craftingInventory.getWidth()))) {
                return -1;
            }
        }
        return totalDamage;
    }


    @Override
    public ItemStack getCraftingResult(CraftingInventory inv) {
        for(int x=0; x<=inv.getWidth()-3; x++){
            for(int y=0; y<=inv.getHeight()-3; y++){
                int damage;
                if((damage = checkMatch(inv, x, y)) != -1) {
                    ItemStack result = new ItemStack(paxel);
                    result.setDamage(damage);
                    return result;
                }
            }
        }

        return ItemStack.EMPTY;
    }

    @Override
    public boolean canFit(int width, int height) {
        return width >= 3 && height >= 3;
    }

    //for recipe book
    @Override
    public ItemStack getRecipeOutput() {
        return new ItemStack(paxel);
    }

    @Override
    public NonNullList<Ingredient> getIngredients() {
        return NonNullList.from(Ingredient.EMPTY,
                Ingredient.fromItems(pickaxe), Ingredient.fromItems(axe), Ingredient.fromItems(shovel),
                Ingredient.EMPTY, Ingredient.fromItems(stick), Ingredient.EMPTY,
                Ingredient.EMPTY, Ingredient.fromItems(stick), Ingredient.EMPTY);
    }

    @Override
    public ResourceLocation getId() {
        return id;
    }

    @Override
    public boolean isDynamic() {
        return false;
    }

    @Override
    public IRecipeSerializer<?> getSerializer() {
        return EntesPaxel.PAXEL;
    }

    @Override
    public int getRecipeWidth() {
        return 3;
    }

    @Override
    public int getRecipeHeight() {
        return 3;
    }

    public static class Serializer extends ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<PaxelRecipe> {

        public Serializer(){
        }

        @Override
        public PaxelRecipe read(ResourceLocation recipeId, JsonObject json) {
            return new PaxelRecipe(recipeId);
        }

        @Nullable
        @Override
        public PaxelRecipe read(ResourceLocation recipeId, PacketBuffer buffer) {
            return new PaxelRecipe(recipeId);
        }

        @Override
        public void write(PacketBuffer buffer, PaxelRecipe recipe) {
        }
    }
}

 

 

The method responsible for matching a recipe from the recipe book to my inventory seems to be IRecipe#getIngredients. Since Ingredient#test only tests for the ItemStack's Item and not other data though, I'm very confused as to why item stack's nbt matters there.

Edited by TheOnlyTrueEnte
added version
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.