From 95e523f943c60d93ba2a384a7f2acb502f69a671 Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 21 Dec 2016 11:11:25 -0800 Subject: [PATCH] [1.11] Fix ItemHandlerHelper canStack and ItemStack areTagsEqual methods not checking capabilities (#3500) --- .../net/minecraft/item/ItemStack.java.patch | 9 ++ .../items/ItemHandlerHelper.java | 13 +- .../test/TestCapabilityMod.java | 117 ++++++++++++------ 3 files changed, 97 insertions(+), 42 deletions(-) diff --git a/patches/minecraft/net/minecraft/item/ItemStack.java.patch b/patches/minecraft/net/minecraft/item/ItemStack.java.patch index c66d1e3fe..7bdbeb891 100644 --- a/patches/minecraft/net/minecraft/item/ItemStack.java.patch +++ b/patches/minecraft/net/minecraft/item/ItemStack.java.patch @@ -186,6 +186,15 @@ if (this.field_77990_d != null) { +@@ -344,7 +368,7 @@ + + public static boolean func_77970_a(ItemStack p_77970_0_, ItemStack p_77970_1_) + { +- return p_77970_0_.func_190926_b() && p_77970_1_.func_190926_b() ? true : (!p_77970_0_.func_190926_b() && !p_77970_1_.func_190926_b() ? (p_77970_0_.field_77990_d == null && p_77970_1_.field_77990_d != null ? false : p_77970_0_.field_77990_d == null || p_77970_0_.field_77990_d.equals(p_77970_1_.field_77990_d)) : false); ++ return p_77970_0_.func_190926_b() && p_77970_1_.func_190926_b() ? true : (!p_77970_0_.func_190926_b() && !p_77970_1_.func_190926_b() ? (p_77970_0_.field_77990_d == null && p_77970_1_.field_77990_d != null ? false : (p_77970_0_.field_77990_d == null || p_77970_0_.field_77990_d.equals(p_77970_1_.field_77990_d)) && p_77970_0_.areCapsCompatible(p_77970_1_)) : false); + } + + public static boolean func_77989_b(ItemStack p_77989_0_, ItemStack p_77989_1_) @@ -758,6 +782,7 @@ } } diff --git a/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java b/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java index 8bdf29792..a1b77c87e 100644 --- a/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java +++ b/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java @@ -54,12 +54,10 @@ public class ItemHandlerHelper public static boolean canItemStacksStack(@Nonnull ItemStack a, @Nonnull ItemStack b) { - if (a.func_190926_b() || !a.isItemEqual(b)) + if (a.func_190926_b() || !a.isItemEqual(b) || a.hasTagCompound() != b.hasTagCompound()) return false; - final NBTTagCompound aTag = a.getTagCompound(); - final NBTTagCompound bTag = b.getTagCompound(); - return (aTag != null || bTag == null) && (aTag == null || aTag.equals(bTag)); + return (!a.hasTagCompound() || a.getTagCompound().equals(b.getTagCompound())) && a.areCapsCompatible(b); } /** @@ -80,9 +78,10 @@ public class ItemHandlerHelper if (a.getHasSubtypes() && a.getMetadata() != b.getMetadata()) return false; - final NBTTagCompound aTag = a.getTagCompound(); - final NBTTagCompound bTag = b.getTagCompound(); - return (aTag != null || bTag == null) && (aTag == null || aTag.equals(bTag)); + if (a.hasTagCompound() != b.hasTagCompound()) + return false; + + return (!a.hasTagCompound() || a.getTagCompound().equals(b.getTagCompound())) && a.areCapsCompatible(b); } @Nonnull diff --git a/src/test/java/net/minecraftforge/test/TestCapabilityMod.java b/src/test/java/net/minecraftforge/test/TestCapabilityMod.java index 7ca33de0b..3cdd513a8 100644 --- a/src/test/java/net/minecraftforge/test/TestCapabilityMod.java +++ b/src/test/java/net/minecraftforge/test/TestCapabilityMod.java @@ -3,6 +3,7 @@ package net.minecraftforge.test; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; @@ -13,7 +14,7 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability.IStorage; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityManager; -import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.fml.common.Mod; @@ -47,7 +48,6 @@ public class TestCapabilityMod @SubscribeEvent public void onInteract(PlayerInteractEvent.LeftClickBlock event) { - if (event.getItemStack().func_190926_b()) return; if (event.getItemStack().getItem() != Items.STICK) return; // This is just a example of how to interact with the TE, note the strong type binding that getCapability has @@ -58,13 +58,27 @@ public class TestCapabilityMod IExampleCapability inv = te.getCapability(TEST_CAP, event.getFace()); System.out.println("Hi I'm a " + inv.getOwnerType()); } - if (event.getWorld().getBlockState(event.getPos()).getBlock() == Blocks.DIRT) + if (event.getWorld().getBlockState(event.getPos()).getBlock() == Blocks.DIRT && event.getItemStack().hasCapability(TEST_CAP, null)) { - event.getEntityPlayer().addChatMessage(new TextComponentString(TextFormatting.RED + "" + TextFormatting.ITALIC + "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST")); + IExampleCapability cap = event.getItemStack().getCapability(TEST_CAP, null); + event.getEntityPlayer().addChatMessage(new TextComponentString((cap.getVal() ? TextFormatting.GREEN : TextFormatting.RED) + "" + TextFormatting.ITALIC + "TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST")); event.setCanceled(true); } } + @SubscribeEvent + public void onInteractItem(PlayerInteractEvent.RightClickItem event) + { + if (!event.getEntityPlayer().isSneaking()) return; + if (event.getItemStack().getItem() != Items.STICK) return; + + if (event.getItemStack().hasCapability(TEST_CAP, null)) + { + IExampleCapability cap = event.getItemStack().getCapability(TEST_CAP, null); + cap.toggleVal(); + System.out.println("Test value is now: " + (cap.getVal() ? "TRUE" : "FALSE")); + } + } // Example of having this annotation on a method, this will be called when the capability is present. // You could do something like register event handlers to attach these capabilities to objects, or @@ -75,6 +89,54 @@ public class TestCapabilityMod System.out.println("IExampleCapability was registered wheeeeee!"); } + // Having the Provider implement the cap is not recommended as this creates a hard dep on the cap interface. + // And does not allow for sidedness. + // But as this is a example and we do not care about that here we go. + class Provider implements ICapabilitySerializable, IExampleCapability + { + private V obj; + private boolean value; + + Provider(V obj) + { + this.obj = obj; + } + @Override + public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) + { + return TEST_CAP != null && capability == TEST_CAP; + } + @Override + @Nullable + public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) + { + if (TEST_CAP != null && capability == TEST_CAP) return TEST_CAP.cast(this); + return null; + } + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setBoolean("CapTestVal", this.value); + return tag; + } + @Override + public void deserializeNBT(NBTTagCompound tag) { + this.value = tag.getBoolean("CapTestVal"); + } + @Override + public String getOwnerType() { + return obj.getClass().getName(); + } + @Override + public boolean getVal() { + return this.value; + } + @Override + public void toggleVal() { + this.value = !this.value; + } + } + // An example of how to attach a capability to an arbitrary Tile entity. // Note: Doing this IS NOT recommended for normal implementations. // If you control the TE it is HIGHLY recommend that you implement a fast @@ -83,39 +145,17 @@ public class TestCapabilityMod @SubscribeEvent public void onTELoad(AttachCapabilitiesEvent.TileEntity event) { - // Having the Provider implement the cap is not recomended as this creates a hard dep on the cap interface. - // And doesnt allow for sidedness. - // But as this is a example and we dont care about that here we go. - class Provider implements ICapabilityProvider, IExampleCapability - { - private TileEntity te; - - Provider(TileEntity te) - { - this.te = te; - } - @Override - public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) - { - return TEST_CAP != null && capability == TEST_CAP; - } - @Override - @Nullable - public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) - { - if (TEST_CAP != null && capability == TEST_CAP) return TEST_CAP.cast(this); - return null; - } - @Override - public String getOwnerType() { - return te.getClass().getName(); - } - } - - //Attach it! The resource location MUST be unique it's recomneded that you tag it with your modid and what the cap is. + //Attach it! The resource location MUST be unique it's recommended that you tag it with your modid and what the cap is. event.addCapability(new ResourceLocation("forge.testcapmod:dummy_cap"), new Provider(event.getTileEntity())); } + @SubscribeEvent + public void onItemLoad(AttachCapabilitiesEvent.Item event) + { + if (event.getItemStack().getItem() == Items.STICK) + event.addCapability(new ResourceLocation("forge.testcapmod:dummy_cap"), new Provider(event.getItemStack())); + } + @SuppressWarnings("rawtypes") @SubscribeEvent public void attachEvent(AttachCapabilitiesEvent event) //Test Raw type gets everything still. @@ -127,7 +167,7 @@ public class TestCapabilityMod public void attachTileEntity(AttachCapabilitiesEvent event) { if (!(event.getObject() instanceof TileEntity)) - throw new IllegalArgumentException("Generic event handler failed! Exprected Tile Entity got " + event.getObject()); + throw new IllegalArgumentException("Generic event handler failed! Expected Tile Entity got " + event.getObject()); } // Capabilities SHOULD be interfaces, NOT concrete classes, this allows for @@ -135,6 +175,8 @@ public class TestCapabilityMod public static interface IExampleCapability { String getOwnerType(); + boolean getVal(); + void toggleVal(); } // Storage implementations are required, tho there is some flexibility here. @@ -160,5 +202,10 @@ public class TestCapabilityMod public String getOwnerType(){ return "Default Implementation!"; } + public boolean getVal() { + return false; + } + @Override + public void toggleVal() {} } }