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.



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Update: I managed to make the item not disappear after crafting, but it doesn't remove any durability. import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.Enchantments; import net.minecraft.enchantment.UnbreakingEnchantment; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; public class NuggetHammer extends Item { private boolean damage; public NuggetHammer(Properties p_i48487_1_) { super(p_i48487_1_); } @Override public int getMaxDamage(ItemStack stack) { return 54 - 1; } public boolean isBarVisible(ItemStack stack) { return false; } @Override public ItemStack getContainerItem(ItemStack stack) { ItemStack copy = stack.copy(); copy.setCount(1); if (!this.damage) return copy; int unbreaking = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.UNBREAKING, stack); for (int i = 0; i < unbreaking; i++) { if (UnbreakingEnchantment.shouldIgnoreDurabilityDrop(stack, unbreaking, random)) return copy; } copy.setDamageValue(stack.getDamageValue() + 1); if (copy.getDamageValue() > stack.getMaxDamage()) return ItemStack.EMPTY; return copy; } }  
    • I cannot find the answer anywhere public static void onPlayerConsumeXp(PlayerXpEvent.PickupXp event){ if(event.getEntity().getMainHandItem().getAllEnchantments().get(*value i need*) != null){ int shorthand = event.getEntity().getMainHandItem().getAllEnchantments().get(*value i need*); I am trying to get my custom enchant inside that *value i need*, I have tried using strings and Enchantments. does not show my enchantment. This is my enchantment class package net.test.tutorialmod.enchants; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.EnchantmentCategory; public class clever extends Enchantment { public clever(Rarity pRarity, EnchantmentCategory pCategory, EquipmentSlot... pApplicableSlots) { super(pRarity, pCategory, pApplicableSlots); } @Override public int getMaxLevel() { return 10; } @Override public int getMinLevel() { return 1; } }  What am i doing wrong?  
    • I had this same issue, it was one of the mods I had installed, some mods seem to break with certain versions of forge and cause others to break as well, trial and error different mods till you find the broken one.  
    • Hi, I'm asking for your help because I can't figure out how to make it so that when an item is crafted on the Crafting Table, it returns the item to the player's inventory and makes the item lose durability. I've tried looking everywhere without success. Like for the crafting of the cake which returns the empty bucket to the player, but also makes it lose durability.  
  • Topics

×
×
  • Create New...

Important Information

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