Create custom shapeless recipe matching system. Should solve #4516 damageable items in shapeless recipes.
This commit is contained in:
parent
ad16f15365
commit
89db87dbfc
11 changed files with 368 additions and 19 deletions
|
@ -1,6 +1,11 @@
|
|||
--- ../src-base/minecraft/net/minecraft/item/crafting/Ingredient.java
|
||||
+++ ../src-work/minecraft/net/minecraft/item/crafting/Ingredient.java
|
||||
@@ -13,6 +13,8 @@
|
||||
@@ -8,11 +8,11 @@
|
||||
import net.minecraft.client.util.RecipeItemHelper;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
-import net.minecraftforge.fml.relauncher.Side;
|
||||
-import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class Ingredient implements Predicate<ItemStack>
|
||||
{
|
||||
|
@ -9,12 +14,13 @@
|
|||
public static final Ingredient field_193370_a = new Ingredient(new ItemStack[0])
|
||||
{
|
||||
public boolean apply(@Nullable ItemStack p_apply_1_)
|
||||
@@ -21,17 +23,34 @@
|
||||
@@ -21,17 +21,41 @@
|
||||
}
|
||||
};
|
||||
private final ItemStack[] field_193371_b;
|
||||
+ private final ItemStack[] matchingStacksExploded;
|
||||
private IntList field_194140_c;
|
||||
+ private final boolean isSimple;
|
||||
|
||||
+ protected Ingredient(int size)
|
||||
+ {
|
||||
|
@ -23,6 +29,7 @@
|
|||
+
|
||||
protected Ingredient(ItemStack... p_i47503_1_)
|
||||
{
|
||||
+ boolean simple = true;
|
||||
this.field_193371_b = p_i47503_1_;
|
||||
+ net.minecraft.util.NonNullList<ItemStack> lst = net.minecraft.util.NonNullList.func_191196_a();
|
||||
+ for (ItemStack s : p_i47503_1_)
|
||||
|
@ -30,11 +37,16 @@
|
|||
+ if (s.func_190926_b())
|
||||
+ continue;
|
||||
+ if (s.func_77960_j() == net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE)
|
||||
+ {
|
||||
+ if (s.func_77973_b().func_77645_m())
|
||||
+ simple = false;
|
||||
+ s.func_77973_b().func_150895_a(net.minecraft.creativetab.CreativeTabs.field_78027_g, lst);
|
||||
+ }
|
||||
+ else
|
||||
+ lst.add(s);
|
||||
+ }
|
||||
+ this.matchingStacksExploded = lst.toArray(new ItemStack[lst.size()]);
|
||||
+ this.isSimple = simple && this.matchingStacksExploded.length > 0;
|
||||
+ Ingredient.INSTANCES.add(this);
|
||||
}
|
||||
|
||||
|
@ -46,7 +58,7 @@
|
|||
}
|
||||
|
||||
public boolean apply(@Nullable ItemStack p_apply_1_)
|
||||
@@ -63,9 +82,9 @@
|
||||
@@ -63,9 +87,9 @@
|
||||
{
|
||||
if (this.field_194140_c == null)
|
||||
{
|
||||
|
@ -58,7 +70,7 @@
|
|||
{
|
||||
this.field_194140_c.add(RecipeItemHelper.func_194113_b(itemstack));
|
||||
}
|
||||
@@ -76,6 +95,18 @@
|
||||
@@ -76,6 +100,18 @@
|
||||
return this.field_194140_c;
|
||||
}
|
||||
|
||||
|
@ -77,7 +89,7 @@
|
|||
public static Ingredient func_193367_a(Item p_193367_0_)
|
||||
{
|
||||
return func_193369_a(new ItemStack(p_193367_0_, 1, 32767));
|
||||
@@ -108,4 +139,17 @@
|
||||
@@ -108,4 +144,22 @@
|
||||
|
||||
return field_193370_a;
|
||||
}
|
||||
|
@ -93,5 +105,10 @@
|
|||
+ lst.add(stack);
|
||||
+ }
|
||||
+ return new Ingredient(lst.toArray(new ItemStack[lst.size()]));
|
||||
+ }
|
||||
+
|
||||
+ public boolean isSimple()
|
||||
+ {
|
||||
+ return isSimple || this == field_193370_a;
|
||||
+ }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- ../src-base/minecraft/net/minecraft/item/crafting/ShapelessRecipes.java
|
||||
+++ ../src-work/minecraft/net/minecraft/item/crafting/ShapelessRecipes.java
|
||||
@@ -10,10 +10,8 @@
|
||||
@@ -10,23 +10,25 @@
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -12,15 +12,25 @@
|
|||
{
|
||||
private final ItemStack field_77580_a;
|
||||
public final NonNullList<Ingredient> field_77579_b;
|
||||
@@ -26,7 +24,6 @@
|
||||
private final String field_194138_c;
|
||||
+ private final boolean isSimple;
|
||||
|
||||
public ShapelessRecipes(String p_i47500_1_, ItemStack p_i47500_2_, NonNullList<Ingredient> p_i47500_3_)
|
||||
{
|
||||
this.field_194138_c = p_i47500_1_;
|
||||
this.field_77580_a = p_i47500_2_;
|
||||
this.field_77579_b = p_i47500_3_;
|
||||
+ boolean simple = true;
|
||||
+ for (Ingredient i : p_i47500_3_)
|
||||
+ simple &= i.isSimple();
|
||||
+ this.isSimple = simple;
|
||||
}
|
||||
|
||||
- @SideOnly(Side.CLIENT)
|
||||
public String func_193358_e()
|
||||
{
|
||||
return this.field_194138_c;
|
||||
@@ -50,10 +47,7 @@
|
||||
@@ -50,10 +52,7 @@
|
||||
{
|
||||
ItemStack itemstack = p_179532_1_.func_70301_a(i);
|
||||
|
||||
|
@ -32,17 +42,18 @@
|
|||
}
|
||||
|
||||
return nonnulllist;
|
||||
@@ -61,7 +55,8 @@
|
||||
@@ -61,7 +60,9 @@
|
||||
|
||||
public boolean func_77569_a(InventoryCrafting p_77569_1_, World p_77569_2_)
|
||||
{
|
||||
- List<Ingredient> list = Lists.newArrayList(this.field_77579_b);
|
||||
+ int ingredientCount = 0;
|
||||
+ net.minecraft.client.util.RecipeItemHelper recipeItemHelper = new net.minecraft.client.util.RecipeItemHelper();
|
||||
+ List<ItemStack> inputs = Lists.newArrayList();
|
||||
|
||||
for (int i = 0; i < p_77569_1_.func_174923_h(); ++i)
|
||||
{
|
||||
@@ -71,27 +66,13 @@
|
||||
@@ -71,27 +72,22 @@
|
||||
|
||||
if (!itemstack.func_190926_b())
|
||||
{
|
||||
|
@ -63,17 +74,26 @@
|
|||
- return false;
|
||||
- }
|
||||
+ ++ingredientCount;
|
||||
+ recipeItemHelper.func_194112_a(itemstack);
|
||||
+ if (this.isSimple)
|
||||
+ recipeItemHelper.func_194112_a(itemstack);
|
||||
+ else
|
||||
+ inputs.add(itemstack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- return list.isEmpty();
|
||||
+ return ingredientCount == this.field_77579_b.size() && recipeItemHelper.func_194116_a(this, null);
|
||||
+ if (ingredientCount != this.field_77579_b.size())
|
||||
+ return false;
|
||||
+
|
||||
+ if (this.isSimple)
|
||||
+ return recipeItemHelper.func_194116_a(this, null);
|
||||
+
|
||||
+ return net.minecraftforge.common.util.RecipeMatcher.findMatches(inputs, this.field_77579_b) != null;
|
||||
}
|
||||
|
||||
public ItemStack func_77572_b(InventoryCrafting p_77572_1_)
|
||||
@@ -136,7 +117,6 @@
|
||||
@@ -136,7 +132,6 @@
|
||||
return nonnulllist;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,17 @@ public class CompoundIngredient extends Ingredient
|
|||
private Collection<Ingredient> children;
|
||||
private ItemStack[] stacks;
|
||||
private IntList itemIds;
|
||||
private final boolean isSimple;
|
||||
|
||||
protected CompoundIngredient(Collection<Ingredient> children)
|
||||
{
|
||||
super(0);
|
||||
this.children = children;
|
||||
|
||||
boolean simple = true;
|
||||
for (Ingredient child : children)
|
||||
simple &= child.isSimple();
|
||||
this.isSimple = simple;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,4 +84,10 @@ public class CompoundIngredient extends Ingredient
|
|||
this.stacks = null;
|
||||
//Shouldn't need to invalidate children as this is only called form invalidateAll..
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSimple()
|
||||
{
|
||||
return isSimple;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,4 +40,10 @@ public class IngredientNBT extends Ingredient
|
|||
//Can't use areItemStacksEqualUsingNBTShareTag because it compares stack size as well
|
||||
return this.stack.getItem() == input.getItem() && this.stack.getItemDamage() == input.getItemDamage() && ItemStack.areItemStackShareTagsEqual(this.stack, input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSimple()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
162
src/main/java/net/minecraftforge/common/util/RecipeMatcher.java
Normal file
162
src/main/java/net/minecraftforge/common/util/RecipeMatcher.java
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraftforge.common.util;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
public class RecipeMatcher
|
||||
{
|
||||
/**
|
||||
* Attempts to match inputs to the specified tests. In the best way that all inputs are used by one test.
|
||||
* Will return null in any of these cases:
|
||||
* input/test lengths don't match. This is only for matching paired outputs.
|
||||
* any input doesn't match a test
|
||||
* any test doesn't match a input
|
||||
* If we are unable to determine a proper pair
|
||||
*
|
||||
* @return An array mapping inputs to tests. ret[x] = y means input[x] = test[y]
|
||||
*/
|
||||
public static <T> int[] findMatches(List<T> inputs, List<? extends Predicate<T>> tests)
|
||||
{
|
||||
int elements = inputs.size();
|
||||
if (elements != tests.size())
|
||||
return null; // There will not be a 1:1 mapping of inputs -> tests
|
||||
|
||||
int[] ret = new int[elements];
|
||||
for (int x = 0; x < elements; x++)
|
||||
ret[x] = -1;
|
||||
|
||||
// [UnusedInputs] [UnusedIngredients] [IngredientMatchMask]...
|
||||
BitSet data = new BitSet((elements + 2) * elements);
|
||||
for (int x = 0; x < elements; x++)
|
||||
{
|
||||
int matched = 0;
|
||||
int offset = (x + 2) * elements;
|
||||
Predicate<T> test = tests.get(x);
|
||||
|
||||
for (int y = 0; y < elements; y++)
|
||||
{
|
||||
if (data.get(y))
|
||||
continue;
|
||||
|
||||
if (test.apply(inputs.get(y)))
|
||||
{
|
||||
data.set(offset + y);
|
||||
matched++;
|
||||
}
|
||||
}
|
||||
|
||||
if (matched == 0)
|
||||
return null; //We have an test that matched non of the inputs
|
||||
|
||||
if (matched == 1)
|
||||
{
|
||||
if (!claim(ret, data, x, elements))
|
||||
return null; //We failed to claim this index, which means it caused something else to go to 0 matches, which makes the whole thing fail
|
||||
}
|
||||
}
|
||||
|
||||
if (data.nextClearBit(0) >= elements) //All items have been used, which means all tests have a match!
|
||||
return ret;
|
||||
|
||||
// We should be in a state where multiple tests are satified by multiple inputs. So we need to try a branching recursive test.
|
||||
// However for performance reasons, we should probably make that check a sub-set of the entire graph.
|
||||
if (backtrack(data, ret, 0, elements))
|
||||
return ret;
|
||||
|
||||
return null; //Backtrack failed, no matches, we cry and go home now :(
|
||||
}
|
||||
|
||||
// This is bad... need to think of a better cascade, recursion instead of stack?
|
||||
private static boolean claim(int[] ret, BitSet data, int claimed, int elements)
|
||||
{
|
||||
Queue<Integer> pending = new LinkedList<Integer>();
|
||||
pending.add(claimed);
|
||||
|
||||
while (pending.peek() != null)
|
||||
{
|
||||
int test = pending.poll();
|
||||
int offset = (test + 2) * elements;
|
||||
int used = data.nextSetBit(offset) - offset;
|
||||
|
||||
if (used >= elements || used < 0)
|
||||
throw new IllegalStateException("What? We matched something, but it wasn't set in the range of this test! Test: " + test + " Used: " + used);
|
||||
|
||||
data.set(used);
|
||||
data.set(elements + test);
|
||||
ret[used] = test;
|
||||
|
||||
for (int x = 0; x < elements; x++)
|
||||
{
|
||||
offset = (x + 2) * elements;
|
||||
if (data.get(offset + used) && !data.get(elements + x))
|
||||
{
|
||||
data.clear(offset + used);
|
||||
int count = 0;
|
||||
for (int y = offset; y < offset + elements; y++)
|
||||
if (data.get(y))
|
||||
count++;
|
||||
|
||||
if (count == 0)
|
||||
return false; //Claiming this caused another test to lose its last match..
|
||||
|
||||
if (count == 1)
|
||||
pending.add(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//We use recursion here, why? Because I feel like it. Also because we should only ever be working in data sets < 9
|
||||
private static boolean backtrack(BitSet data, int[] ret, int start, int elements)
|
||||
{
|
||||
int test = data.nextClearBit(elements + start) - elements;
|
||||
if (test >= elements)
|
||||
return true; //Could not find the next unused test.
|
||||
|
||||
if (test < 0)
|
||||
throw new IllegalStateException("This should never happen, negative test in backtrack!");
|
||||
|
||||
int offset = (test + 2) * elements;
|
||||
for (int x = 0; x < elements; x++)
|
||||
{
|
||||
if (!data.get(offset + x) || data.get(x))
|
||||
continue;
|
||||
|
||||
data.set(x);
|
||||
|
||||
if (backtrack(data, ret, test + 1, elements))
|
||||
{
|
||||
ret[x] = test;
|
||||
return true;
|
||||
}
|
||||
|
||||
data.clear(x);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -114,4 +114,10 @@ public class OreIngredient extends Ingredient
|
|||
this.itemIds = null;
|
||||
this.array = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSimple()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import net.minecraft.util.ResourceLocation;
|
|||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.crafting.CraftingHelper;
|
||||
import net.minecraftforge.common.crafting.JsonContext;
|
||||
import net.minecraftforge.common.util.RecipeMatcher;
|
||||
import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -48,6 +49,7 @@ public class ShapelessOreRecipe extends IForgeRegistryEntry.Impl<IRecipe> implem
|
|||
protected ItemStack output = ItemStack.EMPTY;
|
||||
protected NonNullList<Ingredient> input = NonNullList.create();
|
||||
protected ResourceLocation group;
|
||||
protected boolean isSimple = true;
|
||||
|
||||
public ShapelessOreRecipe(ResourceLocation group, Block result, Object... recipe){ this(group, new ItemStack(result), recipe); }
|
||||
public ShapelessOreRecipe(ResourceLocation group, Item result, Object... recipe){ this(group, new ItemStack(result), recipe); }
|
||||
|
@ -56,6 +58,8 @@ public class ShapelessOreRecipe extends IForgeRegistryEntry.Impl<IRecipe> implem
|
|||
this.group = group;
|
||||
output = result.copy();
|
||||
this.input = input;
|
||||
for (Ingredient i : input)
|
||||
this.isSimple &= i.isSimple();
|
||||
}
|
||||
public ShapelessOreRecipe(ResourceLocation group, @Nonnull ItemStack result, Object... recipe)
|
||||
{
|
||||
|
@ -67,6 +71,7 @@ public class ShapelessOreRecipe extends IForgeRegistryEntry.Impl<IRecipe> implem
|
|||
if (ing != null)
|
||||
{
|
||||
input.add(ing);
|
||||
this.isSimple &= ing.isSimple();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -94,6 +99,7 @@ public class ShapelessOreRecipe extends IForgeRegistryEntry.Impl<IRecipe> implem
|
|||
{
|
||||
int ingredientCount = 0;
|
||||
RecipeItemHelper recipeItemHelper = new RecipeItemHelper();
|
||||
List<ItemStack> items = Lists.newArrayList();
|
||||
|
||||
for (int i = 0; i < inv.getSizeInventory(); ++i)
|
||||
{
|
||||
|
@ -101,11 +107,20 @@ public class ShapelessOreRecipe extends IForgeRegistryEntry.Impl<IRecipe> implem
|
|||
if (!itemstack.isEmpty())
|
||||
{
|
||||
++ingredientCount;
|
||||
recipeItemHelper.accountStack(itemstack);
|
||||
if (this.isSimple)
|
||||
recipeItemHelper.accountStack(itemstack);
|
||||
else
|
||||
items.add(itemstack);
|
||||
}
|
||||
}
|
||||
|
||||
return ingredientCount == this.input.size() && recipeItemHelper.canCraft(this, null);
|
||||
if (ingredientCount != this.input.size())
|
||||
return false;
|
||||
|
||||
if (this.isSimple)
|
||||
return recipeItemHelper.canCraft(this, null);
|
||||
|
||||
return RecipeMatcher.findMatches(items, this.input) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,44 +1,108 @@
|
|||
package net.minecraftforge.debug;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.item.crafting.ShapedRecipes;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.crafting.CraftingHelper;
|
||||
import net.minecraftforge.debug.OnItemUseFirstTest.CommonProxy;
|
||||
import net.minecraftforge.debug.OnItemUseFirstTest.ItemTest;
|
||||
import net.minecraftforge.event.RegistryEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.SidedProxy;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder;
|
||||
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.oredict.ShapedOreRecipe;
|
||||
|
||||
@Mod(modid = "recipetest", name = "Recipe test mod", version = "1.0", acceptableRemoteVersions = "*")
|
||||
@Mod(modid = RecipeTestMod.MODID, name = "Recipe test mod", version = "1.0", acceptableRemoteVersions = "*")
|
||||
public class RecipeTestMod
|
||||
{
|
||||
public static final String MODID = "recipetest";
|
||||
private static final boolean ENABLED = true;
|
||||
@SidedProxy
|
||||
public static CommonProxy proxy = null;
|
||||
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preinit(FMLPreInitializationEvent event)
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
if (ENABLED)
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void registerRecipes(RegistryEvent.Register<IRecipe> event)
|
||||
{
|
||||
ResourceLocation location1 = new ResourceLocation("recipetest", "dirt");
|
||||
ResourceLocation location1 = new ResourceLocation(MODID, "dirt");
|
||||
ShapedOreRecipe recipe1 = new ShapedOreRecipe(location1, new ItemStack(Blocks.DIAMOND_BLOCK), "DDD", 'D', new ItemStack(Blocks.DIRT));
|
||||
recipe1.setRegistryName(location1);
|
||||
event.getRegistry().register(recipe1);
|
||||
|
||||
if (FMLLaunchHandler.side() == Side.SERVER)
|
||||
{
|
||||
ResourceLocation location2 = new ResourceLocation("recipetest", "stone");
|
||||
ResourceLocation location2 = new ResourceLocation(MODID, "stone");
|
||||
CraftingHelper.ShapedPrimer primer1 = CraftingHelper.parseShaped("SSS", 'S', new ItemStack(Blocks.IRON_BLOCK));
|
||||
ShapedRecipes recipe2 = new ShapedRecipes(location2.getResourcePath(), primer1.width, primer1.height, primer1.input, new ItemStack(Blocks.GOLD_BLOCK));
|
||||
recipe2.setRegistryName(location2);
|
||||
event.getRegistry().register(recipe2);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void registerItems(RegistryEvent.Register<Item> event)
|
||||
{
|
||||
proxy.registerItem(event);
|
||||
}
|
||||
|
||||
public static abstract class CommonProxy
|
||||
{
|
||||
protected Item TOOL;
|
||||
public void registerItem(RegistryEvent.Register<Item> event)
|
||||
{
|
||||
TOOL = new Item()
|
||||
{
|
||||
Random RAND = new Random();
|
||||
@Override
|
||||
public ItemStack getContainerItem(ItemStack in)
|
||||
{
|
||||
ItemStack ret = in.copy();
|
||||
ret.attemptDamageItem(1, RAND, null);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasContainerItem()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}.setRegistryName(MODID, "tool").setMaxDamage(10).setCreativeTab(CreativeTabs.MISC).setUnlocalizedName("recipetest.tool").setMaxStackSize(1);
|
||||
event.getRegistry().register(TOOL);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ServerProxy extends CommonProxy
|
||||
{
|
||||
}
|
||||
|
||||
public static final class ClientProxy extends CommonProxy
|
||||
{
|
||||
@Override
|
||||
public void registerItem(RegistryEvent.Register<Item> event)
|
||||
{
|
||||
super.registerItem(event);
|
||||
ModelLoader.setCustomModelResourceLocation(TOOL, 0, new ModelResourceLocation("minecraft:stick#inventory"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "minecraft:bow",
|
||||
"data": 32767
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:wool",
|
||||
"data": 9
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "tool",
|
||||
"data": 32767
|
||||
},
|
||||
{
|
||||
"item": "minecraft:stone",
|
||||
"data": 32767
|
||||
},
|
||||
{
|
||||
"item": "minecraft:stone",
|
||||
"data": 0
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:wool",
|
||||
"data": 0
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{
|
||||
"item": "tool",
|
||||
"data": 32767
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:wool",
|
||||
"data": 9
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue