diff --git a/patches/minecraft/net/minecraft/inventory/ContainerBrewingStand.java.patch b/patches/minecraft/net/minecraft/inventory/ContainerBrewingStand.java.patch index 63936eee0..e281d7c01 100644 --- a/patches/minecraft/net/minecraft/inventory/ContainerBrewingStand.java.patch +++ b/patches/minecraft/net/minecraft/inventory/ContainerBrewingStand.java.patch @@ -1,5 +1,14 @@ --- ../src-base/minecraft/net/minecraft/inventory/ContainerBrewingStand.java +++ ../src-work/minecraft/net/minecraft/inventory/ContainerBrewingStand.java +@@ -158,7 +158,7 @@ + + public boolean func_75214_a(ItemStack p_75214_1_) + { +- return p_75214_1_ != null ? p_75214_1_.func_77973_b().func_150892_m(p_75214_1_) : false; ++ return net.minecraftforge.common.brewing.BrewingRecipeRegistry.isValidIngredient(p_75214_1_); + } + + public int func_75219_a() @@ -190,7 +190,7 @@ public void func_82870_a(EntityPlayer p_82870_1_, ItemStack p_82870_2_) @@ -14,7 +23,7 @@ public static boolean func_75243_a_(ItemStack p_75243_0_) { - return p_75243_0_ != null && (p_75243_0_.func_77973_b() == Items.field_151068_bn || p_75243_0_.func_77973_b() == Items.field_151069_bo); -+ return p_75243_0_ != null && (p_75243_0_.func_77973_b() instanceof net.minecraft.item.ItemPotion || p_75243_0_.func_77973_b() == Items.field_151069_bo); ++ return net.minecraftforge.common.brewing.BrewingRecipeRegistry.isValidInput(p_75243_0_); } } } diff --git a/patches/minecraft/net/minecraft/tileentity/TileEntityBrewingStand.java.patch b/patches/minecraft/net/minecraft/tileentity/TileEntityBrewingStand.java.patch index df91475fe..91343f16a 100644 --- a/patches/minecraft/net/minecraft/tileentity/TileEntityBrewingStand.java.patch +++ b/patches/minecraft/net/minecraft/tileentity/TileEntityBrewingStand.java.patch @@ -1,5 +1,14 @@ --- ../src-base/minecraft/net/minecraft/tileentity/TileEntityBrewingStand.java +++ ../src-work/minecraft/net/minecraft/tileentity/TileEntityBrewingStand.java +@@ -104,7 +104,7 @@ + + private boolean func_145934_k() + { +- if (this.field_145945_j[3] != null && this.field_145945_j[3].field_77994_a > 0) ++ if (this.field_145945_j[3] != null && this.field_145945_j[3].field_77994_a > 0 && false) // Code moved to net.minecraftforge.common.brewing.VanillaBrewingRecipe + { + ItemStack itemstack = this.field_145945_j[3]; + @@ -118,7 +118,7 @@ for (int i = 0; i < 3; ++i) @@ -9,15 +18,24 @@ { int j = this.field_145945_j[i].func_77960_j(); int k = this.func_145936_c(j, itemstack); -@@ -151,13 +151,14 @@ +@@ -145,19 +145,22 @@ + } + else + { +- return false; ++ return net.minecraftforge.common.brewing.BrewingRecipeRegistry.canBrew(field_145945_j, field_145945_j[3], field_145947_i); + } + } private void func_145940_l() { + if (net.minecraftforge.event.ForgeEventFactory.onPotionAttemptBreaw(field_145945_j)) return; if (this.func_145934_k()) { ++ net.minecraftforge.common.brewing.BrewingRecipeRegistry.brewPotions(field_145945_j, field_145945_j[3], field_145947_i); ItemStack itemstack = this.field_145945_j[3]; ++ if (false) { // Code moved to net.minecraftforge.common.brewing.VanillaBrewingRecipe for (int i = 0; i < 3; ++i) { - if (this.field_145945_j[i] != null && this.field_145945_j[i].func_77973_b() == Items.field_151068_bn) @@ -25,9 +43,11 @@ { int j = this.field_145945_j[i].func_77960_j(); int k = this.func_145936_c(j, itemstack); -@@ -178,9 +179,9 @@ +@@ -177,10 +180,11 @@ + } } } ++ } - if (itemstack.func_77973_b().func_77634_r()) + if (itemstack.func_77973_b().hasContainerItem(itemstack)) @@ -37,7 +57,7 @@ } else { -@@ -191,6 +192,7 @@ +@@ -191,6 +195,7 @@ this.field_145945_j[3] = null; } } @@ -45,12 +65,14 @@ } } -@@ -306,7 +308,7 @@ +@@ -306,7 +311,9 @@ public boolean func_94041_b(int p_94041_1_, ItemStack p_94041_2_) { - return p_94041_1_ == 3 ? p_94041_2_.func_77973_b().func_150892_m(p_94041_2_) : p_94041_2_.func_77973_b() == Items.field_151068_bn || p_94041_2_.func_77973_b() == Items.field_151069_bo; -+ return p_94041_1_ == 3 ? p_94041_2_.func_77973_b().func_150892_m(p_94041_2_) : p_94041_2_.func_77973_b() instanceof ItemPotion || p_94041_2_.func_77973_b() == Items.field_151069_bo; ++ if (p_94041_1_ == 3 && net.minecraftforge.common.brewing.BrewingRecipeRegistry.isValidIngredient(p_94041_2_)) return true; ++ else if (p_94041_1_ != 3 && net.minecraftforge.common.brewing.BrewingRecipeRegistry.isValidInput(p_94041_2_)) return true; ++ return false; } public boolean[] func_174902_m() diff --git a/src/main/java/net/minecraftforge/common/brewing/AbstractBrewingRecipe.java b/src/main/java/net/minecraftforge/common/brewing/AbstractBrewingRecipe.java new file mode 100644 index 000000000..ceb3dd15a --- /dev/null +++ b/src/main/java/net/minecraftforge/common/brewing/AbstractBrewingRecipe.java @@ -0,0 +1,40 @@ +package net.minecraftforge.common.brewing; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +public abstract class AbstractBrewingRecipe implements IBrewingRecipe { + + public final ItemStack input; + public final T ingredient; + public final ItemStack output; + + protected AbstractBrewingRecipe(ItemStack input, T ingredient, ItemStack output) + { + this.input = input; + this.ingredient = ingredient; + this.output = output; + + if (this.input == null || this.ingredient == null || this.output == null) + { + throw new IllegalArgumentException("A brewing recipe cannot have a null parameter."); + } + + if (this.input.getMaxStackSize() != 1) + { + throw new IllegalArgumentException("Inputs must have a max size of 1 just like water bottles. Brewing Stands override the input with the output when the brewing is done, items that stack would end up getting lost."); + } + } + + @Override + public boolean isInput(ItemStack stack) + { + return OreDictionary.itemMatches(this.input, stack, false); + } + + @Override + public ItemStack getOutput(ItemStack input, ItemStack ingredient) + { + return isInput(input) && isIngredient(ingredient) ? ItemStack.copyItemStack(output) : null; + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/brewing/BrewingOreRecipe.java b/src/main/java/net/minecraftforge/common/brewing/BrewingOreRecipe.java new file mode 100644 index 000000000..8ac625cb9 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/brewing/BrewingOreRecipe.java @@ -0,0 +1,32 @@ +package net.minecraftforge.common.brewing; + +import java.util.List; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +public class BrewingOreRecipe extends AbstractBrewingRecipe> { + + public BrewingOreRecipe(ItemStack input, String ingredient, ItemStack output) + { + super(input, OreDictionary.getOres(ingredient), output); + } + + public BrewingOreRecipe(ItemStack input, List ingredient, ItemStack output) + { + super(input, ingredient, output); + } + + @Override + public boolean isIngredient(ItemStack stack) + { + for (ItemStack target : this.ingredient) + { + if (OreDictionary.itemMatches(target, stack, false)) + { + return true; + } + + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/brewing/BrewingRecipe.java b/src/main/java/net/minecraftforge/common/brewing/BrewingRecipe.java new file mode 100644 index 000000000..e2b6ce906 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/brewing/BrewingRecipe.java @@ -0,0 +1,18 @@ +package net.minecraftforge.common.brewing; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +public class BrewingRecipe extends AbstractBrewingRecipe { + + public BrewingRecipe(ItemStack input, ItemStack ingredient, ItemStack output) + { + super(input, ingredient, output); + } + + @Override + public boolean isIngredient(ItemStack stack) + { + return OreDictionary.itemMatches(this.ingredient, stack, false); + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/brewing/BrewingRecipeRegistry.java b/src/main/java/net/minecraftforge/common/brewing/BrewingRecipeRegistry.java new file mode 100644 index 000000000..07ea61ce7 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/brewing/BrewingRecipeRegistry.java @@ -0,0 +1,171 @@ +package net.minecraftforge.common.brewing; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import net.minecraft.item.ItemStack; + +public class BrewingRecipeRegistry { + + private static List recipes = new ArrayList(); + + static + { + addRecipe(new VanillaBrewingRecipe()); + } + + /** + * Adds a recipe to the registry. Due to the nature of the brewing stand + * inputs that stack (a.k.a max stack size > 1) are not allowed. + * + * @param input + * The ItemStack that goes in same slots as the water bottles + * would. + * @param ingredient + * The ItemStack that goes in the same slot as nether wart would. + * @param output + * The ItemStack that will replace the input once the brewing is + * done. + * @return true if the recipe was added. + */ + public static boolean addRecipe(ItemStack input, ItemStack ingredient, ItemStack output) + { + return addRecipe(new BrewingRecipe(input, ingredient, output)); + } + + /** + * Adds a recipe to the registry. Due to the nature of the brewing stand + * inputs that stack (a.k.a max stack size > 1) are not allowed. + * + * @param input + * The ItemStack that goes in same slots as the water bottles + * would. + * @param ingredient + * The ItemStack that goes in the same slot as nether wart would. + * @param output + * The ItemStack that will replace the input once the brewing is + * done. + * @return true if the recipe was added. + */ + public static boolean addRecipe(ItemStack input, String ingredient, ItemStack output) + { + return addRecipe(new BrewingOreRecipe(input, ingredient, output)); + } + + /** + * Adds a recipe to the registry. Due to the nature of the brewing stand + * inputs that stack (a.k.a max stack size > 1) are not allowed. + */ + public static boolean addRecipe(IBrewingRecipe recipe) + { + return recipes.add(recipe); + } + + /** + * Returns the output ItemStack obtained by brewing the passed input and + * ingredient. Null if no matches are found. + */ + public static ItemStack getOutput(ItemStack input, ItemStack ingredient) + { + if (input == null || input.getMaxStackSize() != 1 || input.stackSize != 1) return null; + if (ingredient == null || ingredient.stackSize <= 0) return null; + + for (IBrewingRecipe recipe : recipes) + { + ItemStack output = recipe.getOutput(input, ingredient); + if (output != null) + { + return output; + } + } + return null; + } + + /** + * Returns true if the passed input and ingredient have an output + */ + public static boolean hasOuput(ItemStack input, ItemStack ingredient) + { + return getOutput(input, ingredient) != null; + } + + /** + * Used by the brewing stand to determine if its contents can be brewed. + * Extra parameters exist to allow modders to create bigger brewing stands + * without much hassle + */ + public static boolean canBrew(ItemStack[] inputs, ItemStack ingredient, int[] inputIndexes) + { + if (ingredient == null || ingredient.stackSize <= 0) return false; + + for (int i : inputIndexes) + { + if (hasOuput(inputs[i], ingredient)) + { + return true; + } + } + + return false; + } + + /** + * Used by the brewing stand to brew its inventory Extra parameters exist to + * allow modders to create bigger brewing stands without much hassle + */ + public static void brewPotions(ItemStack[] inputs, ItemStack ingredient, int[] inputIndexes) + { + for (int i : inputIndexes) + { + ItemStack output = getOutput(inputs[i], ingredient); + if (output != null) + { + inputs[i] = output; + } + } + } + + /** + * Returns true if the passed ItemStack is a valid ingredient for any of the + * recipes in the registry. + */ + public static boolean isValidIngredient(ItemStack stack) + { + if (stack == null || stack.stackSize <= 0) return false; + + for (IBrewingRecipe recipe : recipes) + { + if (recipe.isIngredient(stack)) + { + return true; + } + } + return false; + } + + /** + * Returns true if the passed ItemStack is a valid input for any of the + * recipes in the registry. + */ + public static boolean isValidInput(ItemStack stack) + { + if (stack == null || stack.getMaxStackSize() != 1 || stack.stackSize != 1) return false; + + for (IBrewingRecipe recipe : recipes) + { + if (recipe.isInput(stack)) + { + return true; + } + } + return false; + } + + /** + * Returns an unmodifiable list containing all the recipes in the registry + */ + public static List getRecipes() + { + return Collections.unmodifiableList(recipes); + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/brewing/IBrewingRecipe.java b/src/main/java/net/minecraftforge/common/brewing/IBrewingRecipe.java new file mode 100644 index 000000000..c31ad926a --- /dev/null +++ b/src/main/java/net/minecraftforge/common/brewing/IBrewingRecipe.java @@ -0,0 +1,26 @@ +package net.minecraftforge.common.brewing; + +import net.minecraft.item.ItemStack; + +public interface IBrewingRecipe { + + /** + * Returns true is the passed ItemStack is an input for this recipe. "Input" + * being the item that goes in one of the three bottom slots of the brewing + * stand (e.g: water bottle) + */ + public boolean isInput(ItemStack input); + + /** + * Returns true if the passed ItemStack is an ingredient for this recipe. + * "Ingredient" being the item that goes in the top slot of the brewing + * stand (e.g: nether wart) + */ + public boolean isIngredient(ItemStack ingredient); + + /** + * Returns the output when the passed input is brewed with the passed + * ingredient. Null if invalid input or ingredient. + */ + public ItemStack getOutput(ItemStack input, ItemStack ingredient); +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/brewing/VanillaBrewingRecipe.java b/src/main/java/net/minecraftforge/common/brewing/VanillaBrewingRecipe.java new file mode 100644 index 000000000..cf94bc16c --- /dev/null +++ b/src/main/java/net/minecraftforge/common/brewing/VanillaBrewingRecipe.java @@ -0,0 +1,75 @@ +package net.minecraftforge.common.brewing; + +import java.util.List; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemPotion; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.PotionHelper; + +/** + * Used in BrewingRecipeRegistry to maintain the vanilla behaviour. + * + * Most of the code was simply adapted from net.minecraft.tileentity.TileEntityBrewingStand + */ +public class VanillaBrewingRecipe implements IBrewingRecipe { + + /** + * Code adapted from TileEntityBrewingStand.isItemValidForSlot(int index, ItemStack stack) + */ + @Override + public boolean isInput(ItemStack stack) + { + return stack.getItem() instanceof ItemPotion || stack.getItem() == Items.glass_bottle; + } + + /** + * Code adapted from TileEntityBrewingStand.isItemValidForSlot(int index, ItemStack stack) + */ + @Override + public boolean isIngredient(ItemStack stack) + { + return stack.getItem().isPotionIngredient(stack); + } + + /** + * Code copied from TileEntityBrewingStand.brewPotions() + * It brews the potion by doing the bit-shifting magic and then checking if the new PotionEffect list is different to the old one, + * or if the new potion is a splash potion when the old one wasn't. + */ + @Override + public ItemStack getOutput(ItemStack input, ItemStack ingredient) + { + if (ingredient != null && input != null && input.getItem() instanceof ItemPotion) + { + int inputMeta = input.getMetadata(); + int outputMeta = PotionHelper.applyIngredient(inputMeta, ingredient.getItem().getPotionEffect(ingredient)); + if (inputMeta == outputMeta) + { + return null; + } + + List oldEffects = Items.potionitem.getEffects(inputMeta); + List newEffects = Items.potionitem.getEffects(outputMeta); + + boolean hasResult = false; + if ((inputMeta <= 0 || oldEffects != newEffects) && (oldEffects == null || !oldEffects.equals(newEffects) && newEffects != null)) + { + hasResult = true; + } + else if (!ItemPotion.isSplash(inputMeta) && ItemPotion.isSplash(outputMeta)) + { + hasResult = true; + } + + if (hasResult) + { + ItemStack output = input.copy(); + output.setItemDamage(outputMeta); + return output; + } + } + + return null; + } +} \ No newline at end of file diff --git a/src/test/java/net/minecraftforge/test/BrewingRecipeRegistryTest.java b/src/test/java/net/minecraftforge/test/BrewingRecipeRegistryTest.java new file mode 100644 index 000000000..2d825de95 --- /dev/null +++ b/src/test/java/net/minecraftforge/test/BrewingRecipeRegistryTest.java @@ -0,0 +1,40 @@ +package net.minecraftforge.test; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.brewing.BrewingRecipeRegistry; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; + +@Mod(modid="BrewingRecipeRegistryTest", name="BrewingRecipeRegistryTest", version="0.0.0") +public class BrewingRecipeRegistryTest +{ + + public static final boolean ENABLE = false; + + @EventHandler + public void init(FMLInitializationEvent event) + { + if(!ENABLE) return; + + // The following adds a recipe that brews a piece of rotten flesh "into" a diamond sword resulting in a diamond hoe + BrewingRecipeRegistry.addRecipe(new ItemStack(Items.diamond_sword), new ItemStack(Items.rotten_flesh), new ItemStack(Items.diamond_hoe)); + + ItemStack output0 = BrewingRecipeRegistry.getOutput(new ItemStack(Items.diamond_sword), new ItemStack(Items.rotten_flesh)); + if(output0.getItem() == Items.diamond_hoe) + System.out.println("Recipe succefully registered and working. Diamond Hoe obtained."); + + // Testing if OreDictionary support is working. Register a recipe that brews a gemDiamond into a gold sword resulting in a diamond sword + BrewingRecipeRegistry.addRecipe(new ItemStack(Items.golden_sword), "gemDiamond", new ItemStack(Items.diamond_sword)); + + ItemStack output1 = BrewingRecipeRegistry.getOutput(new ItemStack(Items.golden_sword), new ItemStack(Items.diamond)); + if(output1.getItem() == Items.diamond_sword) + System.out.println("Recipe succefully registered and working. Diamond Sword obtained."); + + // In vanilla, brewing netherwart into a water bottle results in an awkward potion (with metadata 16). The following tests if that still happens + ItemStack output2 = BrewingRecipeRegistry.getOutput(new ItemStack(Items.potionitem, 1, 0), new ItemStack(Items.nether_wart)); + if(output2 != null && output2.getItem() == Items.potionitem && output2.getItemDamage() == 16) + System.out.println("Vanilla behaviour still in place. Brewed Water Bottle with Nether Wart and got Awkward Potion"); + } +}