diff --git a/gradle.properties b/gradle.properties index b44e5e9db..04695e351 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,7 +39,7 @@ apiPackage = api # Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ # Example value: mymodid_at.cfg -accessTransformersFile = +accessTransformersFile = botania_at.cfg # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = false diff --git a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerBrewery.java b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerBrewery.java index af5546385..0f4a091e9 100644 --- a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerBrewery.java +++ b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerBrewery.java @@ -15,6 +15,7 @@ import vazkii.botania.api.brew.IBrewContainer; import vazkii.botania.api.brew.IBrewItem; import vazkii.botania.api.recipe.RecipeBrew; import vazkii.botania.client.lib.LibResources; +import vazkii.botania.common.core.helper.ItemNBTHelper; import vazkii.botania.common.item.ModItems; import codechicken.lib.gui.GuiDraw; import codechicken.nei.PositionedStack; @@ -131,7 +132,7 @@ public class RecipeHandlerBrewery extends TemplateRecipeHandler { continue; CachedBreweryRecipe crecipe = new CachedBreweryRecipe(recipe); - if(crecipe.containsWithNBT(crecipe.inputs, ingredient)) + if(ItemNBTHelper.cachedRecipeContainsWithNBT(crecipe.inputs, ingredient)) arecipes.add(crecipe); } } diff --git a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerElvenTrade.java b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerElvenTrade.java index a417ab01b..8f77cac6e 100644 --- a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerElvenTrade.java +++ b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerElvenTrade.java @@ -23,6 +23,7 @@ import codechicken.lib.gui.GuiDraw; import codechicken.nei.NEIServerUtils; import codechicken.nei.PositionedStack; import codechicken.nei.recipe.TemplateRecipeHandler; +import vazkii.botania.common.core.helper.ItemNBTHelper; public class RecipeHandlerElvenTrade extends TemplateRecipeHandler { @@ -131,7 +132,7 @@ public class RecipeHandlerElvenTrade extends TemplateRecipeHandler { if(recipe == null) continue; - if(NEIServerUtils.areStacksSameTypeCraftingWithNBT(recipe.getOutput(), result)) + if(ItemNBTHelper.areStacksSameTypeCraftingWithNBT(recipe.getOutput(), result)) arecipes.add(new CachedElvenTradeRecipe(recipe)); } } @@ -145,7 +146,7 @@ public class RecipeHandlerElvenTrade extends TemplateRecipeHandler { continue; CachedElvenTradeRecipe crecipe = new CachedElvenTradeRecipe(recipe); - if(crecipe.containsWithNBT(crecipe.inputs, ingredient)) + if(ItemNBTHelper.cachedRecipeContainsWithNBT(crecipe.inputs, ingredient)) arecipes.add(crecipe); } } diff --git a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerManaPool.java b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerManaPool.java index ff96da617..3548d4126 100644 --- a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerManaPool.java +++ b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerManaPool.java @@ -23,6 +23,7 @@ import codechicken.lib.gui.GuiDraw; import codechicken.nei.NEIServerUtils; import codechicken.nei.PositionedStack; import codechicken.nei.recipe.TemplateRecipeHandler; +import vazkii.botania.common.core.helper.ItemNBTHelper; public class RecipeHandlerManaPool extends TemplateRecipeHandler { @@ -117,7 +118,7 @@ public class RecipeHandlerManaPool extends TemplateRecipeHandler { if(recipe == null) continue; - if(NEIServerUtils.areStacksSameTypeCraftingWithNBT(recipe.getOutput(), result)) + if(ItemNBTHelper.areStacksSameTypeCraftingWithNBT(recipe.getOutput(), result)) arecipes.add(new CachedManaPoolRecipe(recipe)); } } @@ -129,7 +130,7 @@ public class RecipeHandlerManaPool extends TemplateRecipeHandler { continue; CachedManaPoolRecipe crecipe = new CachedManaPoolRecipe(recipe); - if(crecipe.containsWithNBT(crecipe.getIngredients(), ingredient) || crecipe.containsWithNBT(crecipe.getOtherStacks(), ingredient)) + if(ItemNBTHelper.cachedRecipeContainsWithNBT(crecipe.getIngredients(), ingredient) || ItemNBTHelper.cachedRecipeContainsWithNBT(crecipe.getOtherStacks(), ingredient)) arecipes.add(crecipe); } } diff --git a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerPetalApothecary.java b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerPetalApothecary.java index 7dd5439c4..f085bfb57 100644 --- a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerPetalApothecary.java +++ b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerPetalApothecary.java @@ -19,6 +19,7 @@ import codechicken.lib.gui.GuiDraw; import codechicken.nei.NEIServerUtils; import codechicken.nei.PositionedStack; import codechicken.nei.recipe.TemplateRecipeHandler; +import vazkii.botania.common.core.helper.ItemNBTHelper; public class RecipeHandlerPetalApothecary extends TemplateRecipeHandler { @@ -121,7 +122,7 @@ public class RecipeHandlerPetalApothecary extends TemplateRecipeHandler { if(recipe == null) continue; - if(recipe.getOutput().stackTagCompound != null && NEIServerUtils.areStacksSameTypeWithNBT(recipe.getOutput(), result) || recipe.getOutput().stackTagCompound == null && NEIServerUtils.areStacksSameTypeCrafting(recipe.getOutput(), result) && recipe.getOutput().getItem() != Items.skull) + if(recipe.getOutput().stackTagCompound != null && ItemNBTHelper.areStacksSameTypeWithNBT(recipe.getOutput(), result) || recipe.getOutput().stackTagCompound == null && NEIServerUtils.areStacksSameTypeCrafting(recipe.getOutput(), result) && recipe.getOutput().getItem() != Items.skull) arecipes.add(getCachedRecipe(recipe)); } } @@ -133,7 +134,7 @@ public class RecipeHandlerPetalApothecary extends TemplateRecipeHandler { continue; CachedPetalApothecaryRecipe crecipe = getCachedRecipe(recipe); - if(crecipe.containsWithNBT(crecipe.inputs, ingredient) && recipe.getOutput().getItem() != Items.skull) + if(ItemNBTHelper.cachedRecipeContainsWithNBT(crecipe.inputs, ingredient) && recipe.getOutput().getItem() != Items.skull) arecipes.add(crecipe); } } diff --git a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerPureDaisy.java b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerPureDaisy.java index 1b5b867cd..a4a49890a 100644 --- a/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerPureDaisy.java +++ b/src/main/java/vazkii/botania/client/integration/nei/recipe/RecipeHandlerPureDaisy.java @@ -15,6 +15,7 @@ import org.lwjgl.opengl.GL11; import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.recipe.RecipePureDaisy; import vazkii.botania.client.lib.LibResources; +import vazkii.botania.common.core.helper.ItemNBTHelper; import vazkii.botania.common.item.block.ItemBlockSpecialFlower; import vazkii.botania.common.lib.LibBlockNames; import codechicken.lib.gui.GuiDraw; @@ -106,7 +107,7 @@ public class RecipeHandlerPureDaisy extends TemplateRecipeHandler { if(recipe == null) continue; - if(NEIServerUtils.areStacksSameTypeCraftingWithNBT(new ItemStack(recipe.getOutput()), result)) + if(ItemNBTHelper.areStacksSameTypeCraftingWithNBT(new ItemStack(recipe.getOutput()), result)) arecipes.add(new CachedPureDaisyRecipe(recipe)); } } @@ -118,7 +119,7 @@ public class RecipeHandlerPureDaisy extends TemplateRecipeHandler { continue; CachedPureDaisyRecipe crecipe = new CachedPureDaisyRecipe(recipe); - if(crecipe.containsWithNBT(crecipe.getIngredients(), ingredient) || crecipe.containsWithNBT(crecipe.getOtherStacks(), ingredient)) + if(ItemNBTHelper.cachedRecipeContainsWithNBT(crecipe.getIngredients(), ingredient) || ItemNBTHelper.cachedRecipeContainsWithNBT(crecipe.getOtherStacks(), ingredient)) arecipes.add(crecipe); } } diff --git a/src/main/java/vazkii/botania/common/core/helper/ItemNBTHelper.java b/src/main/java/vazkii/botania/common/core/helper/ItemNBTHelper.java index 41c73315f..5a0f33421 100644 --- a/src/main/java/vazkii/botania/common/core/helper/ItemNBTHelper.java +++ b/src/main/java/vazkii/botania/common/core/helper/ItemNBTHelper.java @@ -13,9 +13,16 @@ */ package vazkii.botania.common.core.helper; +import codechicken.nei.PositionedStack; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.oredict.OreDictionary; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Set; public final class ItemNBTHelper { @@ -136,4 +143,100 @@ public final class ItemNBTHelper { return verifyExistance(stack, tag) ? getNBT(stack).getTagList(tag, objtype) : nullifyOnFail ? null : new NBTTagList(); } + // Utils /////////////////////////////////////////////////////////////////// + + /** + * NBT-friendly version of {@link codechicken.nei.NEIServerUtils#areStacksSameType(ItemStack, ItemStack)} + * @param stack1 The {@link ItemStack} being compared. + * @param stack2 The {@link ItemStack} to compare to. + * @return whether the two items are the same in terms of itemID, damage and NBT. + */ + public static boolean areStacksSameTypeWithNBT(ItemStack stack1, ItemStack stack2) { + return stack1 != null && stack2 != null && + stack1.getItem() == stack2.getItem() && + (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && + matchTag(stack1.getTagCompound(), stack2.getTagCompound()); + } + + /** + * NBT-friendly version of {@link codechicken.nei.NEIServerUtils#areStacksSameTypeCrafting(ItemStack, ItemStack)} + * @param stack1 The {@link ItemStack} being compared. + * @param stack2 The {@link ItemStack} to compare to. + * @return whether the two items are the same from the perspective of a crafting inventory. + */ + public static boolean areStacksSameTypeCraftingWithNBT(ItemStack stack1, ItemStack stack2) { + return stack1 != null && stack2 != null && + stack1.getItem() == stack2.getItem() && + ( + stack1.getItemDamage() == stack2.getItemDamage() || + stack1.getItemDamage() == OreDictionary.WILDCARD_VALUE || + stack2.getItemDamage() == OreDictionary.WILDCARD_VALUE || + stack1.getItem().isDamageable() + ) && + matchTag(stack1.getTagCompound(), stack2.getTagCompound()); + } + + /** + * Returns true if the `target` tag contains all of the tags and values present in the `template` tag. Recurses into + * compound tags and matches all template keys and values; recurses into list tags and matches the template against + * the first elements of target. Empty lists and compounds in the template will match target lists and compounds of + * any size. + */ + public static boolean matchTag(@Nullable NBTBase template, @Nullable NBTBase target) { + if (template instanceof NBTTagCompound && target instanceof NBTTagCompound) { + return matchTagCompound((NBTTagCompound) template, (NBTTagCompound) target); + } else if (template instanceof NBTTagList && target instanceof NBTTagList) { + return matchTagList((NBTTagList) template, (NBTTagList) target); + } else { + return template == null || (target != null && target.equals(template)); + } + } + + private static boolean matchTagCompound(NBTTagCompound template, NBTTagCompound target) { + if (template.tagMap.size() > target.tagMap.size()) return false; + + //noinspection unchecked + for (String key : (Set) template.func_150296_c()) { + if (!matchTag(template.getTag(key), target.getTag(key))) return false; + } + + return true; + } + + private static boolean matchTagList(NBTTagList template, NBTTagList target) { + if (template.tagCount() > target.tagCount()) return false; + + for (int i = 0; i < template.tagCount(); i++) { + if (!matchTag(get(template, i), get(target, i))) return false; + } + + return true; + } + + private static NBTBase get(NBTTagList tag, int idx) + { + return idx >= 0 && idx < tag.tagList.size() ? (NBTBase)tag.tagList.get(idx) : null; + } + + /** + * NBT-friendly version of {@link codechicken.nei.recipe.TemplateRecipeHandler.CachedRecipe#contains(Collection, ItemStack)} + */ + public static boolean cachedRecipeContainsWithNBT(Collection ingredients, ItemStack ingredient) { + for (PositionedStack stack : ingredients) + if (positionedStackContainsWithNBT(stack, ingredient)) + return true; + + return false; + } + + /** + * NBT-friendly version of {@link codechicken.nei.PositionedStack#contains(ItemStack)} + */ + public static boolean positionedStackContainsWithNBT(PositionedStack stack, ItemStack ingredient) { + for(ItemStack item : stack.items) + if(areStacksSameTypeCraftingWithNBT(item, ingredient)) + return true; + + return false; + } } diff --git a/src/main/resources/META-INF/botania_at.cfg b/src/main/resources/META-INF/botania_at.cfg new file mode 100644 index 000000000..4c143b92a --- /dev/null +++ b/src/main/resources/META-INF/botania_at.cfg @@ -0,0 +1,2 @@ +public net.minecraft.nbt.NBTTagCompound field_74784_a #tagMap +public net.minecraft.nbt.NBTTagList field_74747_a #taglist \ No newline at end of file