[1.11] Fix ItemHandlerHelper canStack and ItemStack areTagsEqual methods not checking capabilities (#3500)

This commit is contained in:
Justin 2016-12-21 11:11:25 -08:00 committed by LexManos
parent b9ebc44790
commit 95e523f943
3 changed files with 97 additions and 42 deletions

View File

@ -186,6 +186,15 @@
if (this.field_77990_d != null) 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 @@ @@ -758,6 +782,7 @@
} }
} }

View File

@ -54,12 +54,10 @@ public class ItemHandlerHelper
public static boolean canItemStacksStack(@Nonnull ItemStack a, @Nonnull ItemStack b) 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; return false;
final NBTTagCompound aTag = a.getTagCompound(); return (!a.hasTagCompound() || a.getTagCompound().equals(b.getTagCompound())) && a.areCapsCompatible(b);
final NBTTagCompound bTag = b.getTagCompound();
return (aTag != null || bTag == null) && (aTag == null || aTag.equals(bTag));
} }
/** /**
@ -80,9 +78,10 @@ public class ItemHandlerHelper
if (a.getHasSubtypes() && a.getMetadata() != b.getMetadata()) if (a.getHasSubtypes() && a.getMetadata() != b.getMetadata())
return false; return false;
final NBTTagCompound aTag = a.getTagCompound(); if (a.hasTagCompound() != b.hasTagCompound())
final NBTTagCompound bTag = b.getTagCompound(); return false;
return (aTag != null || bTag == null) && (aTag == null || aTag.equals(bTag));
return (!a.hasTagCompound() || a.getTagCompound().equals(b.getTagCompound())) && a.areCapsCompatible(b);
} }
@Nonnull @Nonnull

View File

@ -3,6 +3,7 @@ package net.minecraftforge.test;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.init.Items; import net.minecraft.init.Items;
import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting; 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.Capability.IStorage;
import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager; 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.AttachCapabilitiesEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
@ -47,7 +48,6 @@ public class TestCapabilityMod
@SubscribeEvent @SubscribeEvent
public void onInteract(PlayerInteractEvent.LeftClickBlock event) public void onInteract(PlayerInteractEvent.LeftClickBlock event)
{ {
if (event.getItemStack().func_190926_b()) return;
if (event.getItemStack().getItem() != Items.STICK) 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 // 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()); IExampleCapability inv = te.getCapability(TEST_CAP, event.getFace());
System.out.println("Hi I'm a " + inv.getOwnerType()); 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); 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. // 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 // 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!"); 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<V> implements ICapabilitySerializable<NBTTagCompound>, 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> T getCapability(@Nonnull Capability<T> 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. // An example of how to attach a capability to an arbitrary Tile entity.
// Note: Doing this IS NOT recommended for normal implementations. // Note: Doing this IS NOT recommended for normal implementations.
// If you control the TE it is HIGHLY recommend that you implement a fast // If you control the TE it is HIGHLY recommend that you implement a fast
@ -83,39 +145,17 @@ public class TestCapabilityMod
@SubscribeEvent @SubscribeEvent
public void onTELoad(AttachCapabilitiesEvent.TileEntity event) 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. //Attach it! The resource location MUST be unique it's recommended that you tag it with your modid and what the cap is.
// 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> T getCapability(@Nonnull Capability<T> 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.
event.addCapability(new ResourceLocation("forge.testcapmod:dummy_cap"), new Provider(event.getTileEntity())); 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") @SuppressWarnings("rawtypes")
@SubscribeEvent @SubscribeEvent
public void attachEvent(AttachCapabilitiesEvent event) //Test Raw type gets everything still. public void attachEvent(AttachCapabilitiesEvent event) //Test Raw type gets everything still.
@ -127,7 +167,7 @@ public class TestCapabilityMod
public void attachTileEntity(AttachCapabilitiesEvent<TileEntity> event) public void attachTileEntity(AttachCapabilitiesEvent<TileEntity> event)
{ {
if (!(event.getObject() instanceof TileEntity)) 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 // Capabilities SHOULD be interfaces, NOT concrete classes, this allows for
@ -135,6 +175,8 @@ public class TestCapabilityMod
public static interface IExampleCapability public static interface IExampleCapability
{ {
String getOwnerType(); String getOwnerType();
boolean getVal();
void toggleVal();
} }
// Storage implementations are required, tho there is some flexibility here. // Storage implementations are required, tho there is some flexibility here.
@ -160,5 +202,10 @@ public class TestCapabilityMod
public String getOwnerType(){ public String getOwnerType(){
return "Default Implementation!"; return "Default Implementation!";
} }
public boolean getVal() {
return false;
}
@Override
public void toggleVal() {}
} }
} }