Jump to content

Recommended Posts

Posted

I have an item that is supposed to return a damaged container upon crafting, however within the new JSON recipe format the damage is not being accepted from the '"data":' tag.

While seen in the attached recipe JSON, I am attempting to fix the damage value for the mold template to 10, yet the crafting recipe only works with an undamaged template.

 

Am I doing something incorrectly or do I just need to create my own recipe factory to account for damage values?

 

There are no errors printed to the console.

I am using forge: 1.12.2 - 14.23.0.2491

Here is a link to my GitHub:

https://github.com/Rijento/Clockwork-Mechanicals

 

Here is the item file

Spoiler

package net.rijento.clockwork_mechanicals.items;

import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;


public class ItemMoldTemplate extends Item
{
    public ItemMoldTemplate()
    {
        this.setMaxStackSize(1);
        this.setMaxDamage(100);
        this.setNoRepair();
    }
    @Override
    public ItemStack getContainerItem(ItemStack itemstack){
        ItemStack stack = itemstack.copy();
        stack.attemptDamageItem(1, itemRand, null);
        return stack;
    }

    @Override
    public boolean hasContainerItem(ItemStack stack){
        return true;
    }
}
 

Here is the recipe file:

Spoiler

{
  "type": "forge:ore_shapeless",
  "ingredients": [
    {
        "item":"clockwork_mechanicals:mold_template",
        "data": 10
    },
    {
        "item": "minecraft:clay_ball"
    }
  ],
  "result": {
    "item": "clockwork_mechanicals:blank_mold"
  }
}

 

Posted

Container items are not handled by the json recipe files. Its handled by the item class as it always has been. 

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
2 hours ago, Draco18s said:

Container items are not handled by the json recipe files. Its handled by the item class as it always has been. 

The container is successfully being returned from the crafting recipe, however it cannot be used for any successive crafts. I should have better phrased my question: what is the correct way to use items with damage values in a JSON recipe? The '"data":' tag does not seem to be working.

Posted

You would need to use the oredict wildcard value, but I think it is broken at the moment. 

Ok, not broken, short of intentional. 

See this issue: https://github.com/MinecraftForge/MinecraftForge/issues/4516

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)

Ah I see, thank you. I guess for now I'll increase the clay cost per mold and make the templates unbreakable. Thank you for pointing me to the issue.

Edited by Rijento
Posted

Or you can write your own Ingredient or IRecipe class. 

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Fixed it. Thanks Draco, I created a new shapeless recipe class that allows the use of the OreDictionary Wildcard value and it is working properly.

 

Spoiler

package net.rijento.clockwork_mechanicals.lib;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nonnull;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;

import net.minecraft.block.Block;
import net.minecraft.client.util.RecipeItemHelper;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.IRecipeFactory;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import net.minecraftforge.registries.IForgeRegistryEntry;

public class ShapelessWildcardRecipe extends IForgeRegistryEntry.Impl<IRecipe> implements IRecipe
{
    protected List<Integer> inputused = new ArrayList<Integer>();
    
    @Nonnull
    protected ItemStack output = ItemStack.EMPTY;
    protected NonNullList<Ingredient> input = NonNullList.create();
    protected ResourceLocation group;

    public ShapelessWildcardRecipe(ResourceLocation group, Block result, Object... recipe){ this(group, new ItemStack(result), recipe); }
    public ShapelessWildcardRecipe(ResourceLocation group, Item  result, Object... recipe){ this(group, new ItemStack(result), recipe); }
    public ShapelessWildcardRecipe(ResourceLocation group, NonNullList<Ingredient> input, @Nonnull ItemStack result)
    {
        this.group = group;
        output = result.copy();
        this.input = input;
    }
    public ShapelessWildcardRecipe(ResourceLocation group, @Nonnull ItemStack result, Object... recipe)
    {
        this.group = group;
        output = result.copy();
        for (Object in : recipe)
        {
            Ingredient ing = CraftingHelper.getIngredient(in);
            if (ing != null)
            {
                input.add(ing);
            }
            else
            {
                String ret = "Invalid shapeless wildcard recipe: ";
                for (Object tmp :  recipe)
                {
                    ret += tmp + ", ";
                }
                ret += output;
                throw new RuntimeException(ret);
            }
        }
    }

    @Override
    public boolean matches(InventoryCrafting inv, World worldIn)
    {
        int ingredientCount = 0;

        for (int i = 0; i < inv.getSizeInventory(); ++i)
        {
            ItemStack itemstack = inv.getStackInSlot(i);
            if (!itemstack.isEmpty())
            {
                ++ingredientCount;
            }
        }
        if (!(ingredientCount == this.input.size())){return false;}
        int width = inv.getWidth();
        int height = inv.getHeight();
        for (int ing = 0; ing < input.size(); ing++)
        {
            boolean flag = false;
            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);
                Ingredient target = Ingredient.EMPTY;
                target = input.get(ing);

                if (target.apply(itemstack) && !inputused.contains(i))
                {
                    inputused.add(i);
                    flag = true;
                }
            }
            if (!flag)
            {
                inputused.clear();
                return false;
            }
        }
        inputused.clear();
        return true;
    }

    @Override
    @Nonnull
    public ItemStack getCraftingResult(@Nonnull InventoryCrafting var1){ return output.copy(); }

    @Override
    @Nonnull
    public ItemStack getRecipeOutput(){ return output; }
    
    @Override
    public boolean canFit(int width, int height)
    {
        return width * height >= this.input.size();
    }
    
    
    public static class Factory implements IRecipeFactory
    {

        @Override
        public IRecipe parse(JsonContext context, JsonObject json)
        {
            final String group = JsonUtils.getString(json, "group", "");
            final NonNullList<Ingredient> ingredients = NonNullList.create();
            for (JsonElement ele : JsonUtils.getJsonArray(json, "ingredients"))
                ingredients.add(CraftingHelper.getIngredient(ele, context));
            if (ingredients.isEmpty())
                throw new JsonParseException("No ingredients for shapeless recipe");
            final ItemStack result = CraftingHelper.getItemStack(JsonUtils.getJsonObject(json, "result"), context);
            return new ShapelessWildcardRecipe(group.isEmpty() ? null : new ResourceLocation(group), ingredients, result);
        }
        
    }
}
 

 

Posted

OreDict wildcards work just fine.

And copy pasting the old recipe class isn't creating anything new. It's also not legal if you don't include credit.. so.. work on that...

OreDict wildcard and normal Ingredient wildcards work fine.

The problem is when you use 'damageable' items. As that fundamentally breaks the GuideBook.

Once people actually put their input in, we can start working on a secondary matching implementation that works correctly with wide and narrow ingredients.

 

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Posted (edited)

Thank you for that knowledge.

And my appologies on the copypaste. I have now extended the standard ShapelessRecipe class, added the Factory, and overrided the matches(...) function. Is this a more acceptable format?

Spoiler

package net.rijento.clockwork_mechanicals.lib;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nonnull;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;

import net.minecraft.block.Block;
import net.minecraft.client.util.RecipeItemHelper;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapelessRecipes;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.IRecipeFactory;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import net.minecraftforge.registries.IForgeRegistryEntry;

public class ShapelessWildcardRecipe extends ShapelessRecipes
{
    protected List<Integer> inputused = new ArrayList<Integer>();
    
    public ShapelessWildcardRecipe(String group, NonNullList<Ingredient> input, @Nonnull ItemStack result)
    {
        super(group, result, input);
    }
 
    @Override
    public boolean matches(InventoryCrafting inv, World worldIn)
    {
        int ingredientCount = 0;

        for (int i = 0; i < inv.getSizeInventory(); ++i)
        {
            ItemStack itemstack = inv.getStackInSlot(i);
            if (!itemstack.isEmpty())
            {
                ++ingredientCount;
            }
        }
        if (!(ingredientCount == this.getIngredients().size())){return false;}
        int width = inv.getWidth();
        int height = inv.getHeight();
        for (int ing = 0; ing < this.getIngredients().size(); ing++)
        {
            boolean flag = false;
            for (int i = 0; i < inv.getSizeInventory(); ++i)
            {
                ItemStack itemstack = inv.getStackInSlot(i);
                Ingredient target = Ingredient.EMPTY;
                target = this.getIngredients().get(ing);

                if (target.apply(itemstack) && !inputused.contains(i))
                {
                    inputused.add(i);
                    flag = true;
                }
            }
            if (!flag)
            {
                inputused.clear();
                return false;
            }
        }
        inputused.clear();
        return true;
    }
    
    public static class Factory implements IRecipeFactory
    {

        @Override
        public IRecipe parse(JsonContext context, JsonObject json)
        {
            final String group = JsonUtils.getString(json, "group", "");
            final NonNullList<Ingredient> ingredients = NonNullList.create();
            for (JsonElement ele : JsonUtils.getJsonArray(json, "ingredients"))
                ingredients.add(CraftingHelper.getIngredient(ele, context));
            if (ingredients.isEmpty())
                throw new JsonParseException("No ingredients for shapeless recipe");
            final ItemStack result = CraftingHelper.getItemStack(JsonUtils.getJsonObject(json, "result"), context);
            return new ShapelessWildcardRecipe(group, ingredients, result);
        }
        
    }
}
 

Edit:

Is that what you meant by pasting the old recipe class? Or did I unintentionally recreate code from a previous release of forge?

Edited by Rijento

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.