diff --git a/patches/minecraft/net/minecraft/client/multiplayer/PlayerControllerMP.java.patch b/patches/minecraft/net/minecraft/client/multiplayer/PlayerControllerMP.java.patch index e186be4d7..fdaf7f6b8 100644 --- a/patches/minecraft/net/minecraft/client/multiplayer/PlayerControllerMP.java.patch +++ b/patches/minecraft/net/minecraft/client/multiplayer/PlayerControllerMP.java.patch @@ -108,7 +108,7 @@ + { + // Give the server a chance to fire event as well. That way server event is not dependant on client event. + this.field_78774_b.func_147297_a(new CPacketPlayerTryUseItemOnBlock(p_187099_3_, p_187099_4_, p_187099_6_, f, f1, f2)); -+ return EnumActionResult.PASS; ++ return event.getCancellationResult(); + } + EnumActionResult result = EnumActionResult.PASS; + @@ -161,15 +161,16 @@ } } } -@@ -457,6 +490,7 @@ +@@ -457,6 +490,8 @@ } else { -+ if (net.minecraftforge.common.ForgeHooks.onItemRightClick(p_187101_1_, p_187101_3_)) return net.minecraft.util.EnumActionResult.PASS; ++ EnumActionResult cancelResult = net.minecraftforge.common.ForgeHooks.onItemRightClickAction(p_187101_1_, p_187101_3_); ++ if (cancelResult != null) return cancelResult; int i = itemstack.func_190916_E(); ActionResult actionresult = itemstack.func_77957_a(p_187101_2_, p_187101_1_, p_187101_3_); ItemStack itemstack1 = (ItemStack)actionresult.func_188398_b(); -@@ -464,6 +498,10 @@ +@@ -464,6 +499,10 @@ if (itemstack1 != itemstack || itemstack1.func_190916_E() != i) { p_187101_1_.func_184611_a(p_187101_3_, itemstack1); @@ -180,11 +181,13 @@ } return actionresult.func_188397_a(); -@@ -500,6 +538,7 @@ +@@ -500,6 +539,9 @@ this.func_78750_j(); Vec3d vec3d = new Vec3d(p_187102_3_.field_72307_f.field_72450_a - p_187102_2_.field_70165_t, p_187102_3_.field_72307_f.field_72448_b - p_187102_2_.field_70163_u, p_187102_3_.field_72307_f.field_72449_c - p_187102_2_.field_70161_v); this.field_78774_b.func_147297_a(new CPacketUseEntity(p_187102_2_, p_187102_4_, vec3d)); -+ if(net.minecraftforge.common.ForgeHooks.onInteractEntityAt(p_187102_1_, p_187102_2_, p_187102_3_, p_187102_4_)) return EnumActionResult.PASS; ++ if (this.field_78779_k == GameType.SPECTATOR) return EnumActionResult.PASS; // don't fire for spectators to match non-specific EntityInteract ++ EnumActionResult cancelResult = net.minecraftforge.common.ForgeHooks.onInteractEntityAtAction(p_187102_1_, p_187102_2_, p_187102_3_, p_187102_4_); ++ if(cancelResult != null) return cancelResult; return this.field_78779_k == GameType.SPECTATOR ? EnumActionResult.PASS : p_187102_2_.func_184199_a(p_187102_1_, vec3d, p_187102_4_); } diff --git a/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch b/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch index b8d6b4a44..1d0f0893b 100644 --- a/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch +++ b/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch @@ -217,15 +217,16 @@ p_70665_2_ = this.func_70672_c(p_70665_1_, p_70665_2_); float f = p_70665_2_; p_70665_2_ = Math.max(p_70665_2_ - this.func_110139_bj(), 0.0F); -@@ -1111,6 +1183,7 @@ +@@ -1111,6 +1183,8 @@ } else { -+ if (net.minecraftforge.common.ForgeHooks.onInteractEntity(this, p_190775_1_, p_190775_2_)) return EnumActionResult.PASS; ++ EnumActionResult cancelResult = net.minecraftforge.common.ForgeHooks.onInteractEntityAction(this, p_190775_1_, p_190775_2_); ++ if (cancelResult != null) return cancelResult; ItemStack itemstack = this.func_184586_b(p_190775_2_); ItemStack itemstack1 = itemstack.func_190926_b() ? ItemStack.field_190927_a : itemstack.func_77946_l(); -@@ -1120,7 +1193,10 @@ +@@ -1120,7 +1194,10 @@ { itemstack.func_190920_e(itemstack1.func_190916_E()); } @@ -237,7 +238,7 @@ return EnumActionResult.SUCCESS; } else -@@ -1136,6 +1212,7 @@ +@@ -1136,6 +1213,7 @@ { if (itemstack.func_190926_b() && !this.field_71075_bZ.field_75098_d) { @@ -245,7 +246,7 @@ this.func_184611_a(p_190775_2_, ItemStack.field_190927_a); } -@@ -1161,6 +1238,7 @@ +@@ -1161,6 +1239,7 @@ public void func_71059_n(Entity p_71059_1_) { @@ -253,7 +254,7 @@ if (p_71059_1_.func_70075_an()) { if (!p_71059_1_.func_85031_j(this)) -@@ -1333,11 +1411,13 @@ +@@ -1333,11 +1412,13 @@ if (!itemstack1.func_190926_b() && entity instanceof EntityLivingBase) { @@ -267,7 +268,7 @@ } } -@@ -1443,6 +1523,8 @@ +@@ -1443,6 +1524,8 @@ public EntityPlayer.SleepResult func_180469_a(BlockPos p_180469_1_) { @@ -276,7 +277,7 @@ EnumFacing enumfacing = (EnumFacing)this.field_70170_p.func_180495_p(p_180469_1_).func_177229_b(BlockHorizontal.field_185512_D); if (!this.field_70170_p.field_72995_K) -@@ -1484,8 +1566,9 @@ +@@ -1484,8 +1567,9 @@ this.func_70105_a(0.2F, 0.2F); @@ -288,7 +289,7 @@ float f1 = 0.5F + (float)enumfacing.func_82601_c() * 0.4F; float f = 0.5F + (float)enumfacing.func_82599_e() * 0.4F; this.func_175139_a(enumfacing); -@@ -1532,13 +1615,14 @@ +@@ -1532,13 +1616,14 @@ public void func_70999_a(boolean p_70999_1_, boolean p_70999_2_, boolean p_70999_3_) { @@ -306,7 +307,7 @@ if (blockpos == null) { -@@ -1547,6 +1631,10 @@ +@@ -1547,6 +1632,10 @@ this.func_70107_b((double)((float)blockpos.func_177958_n() + 0.5F), (double)((float)blockpos.func_177956_o() + 0.1F), (double)((float)blockpos.func_177952_p() + 0.5F)); } @@ -317,7 +318,7 @@ this.field_71083_bS = false; -@@ -1565,15 +1653,16 @@ +@@ -1565,15 +1654,16 @@ private boolean func_175143_p() { @@ -337,7 +338,7 @@ { if (!p_180467_2_) { -@@ -1588,16 +1677,17 @@ +@@ -1588,16 +1678,17 @@ } else { @@ -358,7 +359,7 @@ switch (enumfacing) { -@@ -1637,16 +1727,24 @@ +@@ -1637,16 +1728,24 @@ public BlockPos func_180470_cg() { @@ -385,7 +386,7 @@ if (p_180473_1_ != null) { this.field_71077_c = p_180473_1_; -@@ -1841,6 +1939,10 @@ +@@ -1841,6 +1940,10 @@ super.func_180430_e(p_180430_1_, p_180430_2_); } @@ -396,7 +397,7 @@ } protected void func_71061_d_() -@@ -2041,6 +2143,18 @@ +@@ -2041,6 +2144,18 @@ this.field_175152_f = p_71049_1_.field_175152_f; this.field_71078_a = p_71049_1_.field_71078_a; this.func_184212_Q().func_187227_b(field_184827_bp, p_71049_1_.func_184212_Q().func_187225_a(field_184827_bp)); @@ -415,7 +416,7 @@ } protected boolean func_70041_e_() -@@ -2145,7 +2259,10 @@ +@@ -2145,7 +2260,10 @@ public ITextComponent func_145748_c_() { @@ -427,7 +428,7 @@ itextcomponent.func_150256_b().func_150241_a(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/msg " + this.func_70005_c_() + " ")); itextcomponent.func_150256_b().func_150209_a(this.func_174823_aP()); itextcomponent.func_150256_b().func_179989_a(this.func_70005_c_()); -@@ -2154,7 +2271,7 @@ +@@ -2154,7 +2272,7 @@ public float func_70047_e() { @@ -436,7 +437,7 @@ if (this.func_70608_bn()) { -@@ -2370,6 +2487,168 @@ +@@ -2370,6 +2488,168 @@ return this.field_71075_bZ.field_75098_d && this.func_70003_b(2, ""); } diff --git a/patches/minecraft/net/minecraft/network/NetHandlerPlayServer.java.patch b/patches/minecraft/net/minecraft/network/NetHandlerPlayServer.java.patch index 715e35db2..77d87e9b4 100644 --- a/patches/minecraft/net/minecraft/network/NetHandlerPlayServer.java.patch +++ b/patches/minecraft/net/minecraft/network/NetHandlerPlayServer.java.patch @@ -38,7 +38,7 @@ else if (p_147340_1_.func_149565_c() == CPacketUseEntity.Action.INTERACT_AT) { EnumHand enumhand1 = p_147340_1_.func_186994_b(); -+ if(net.minecraftforge.common.ForgeHooks.onInteractEntityAt(field_147369_b, entity, p_147340_1_.func_179712_b(), enumhand1)) return; ++ if(net.minecraftforge.common.ForgeHooks.onInteractEntityAtAction(field_147369_b, entity, p_147340_1_.func_179712_b(), enumhand1) != null) return; entity.func_184199_a(this.field_147369_b, p_147340_1_.func_179712_b(), enumhand1); } else if (p_147340_1_.func_149565_c() == CPacketUseEntity.Action.ATTACK) diff --git a/patches/minecraft/net/minecraft/server/management/PlayerInteractionManager.java.patch b/patches/minecraft/net/minecraft/server/management/PlayerInteractionManager.java.patch index d72c68ab5..df28ae3e3 100644 --- a/patches/minecraft/net/minecraft/server/management/PlayerInteractionManager.java.patch +++ b/patches/minecraft/net/minecraft/server/management/PlayerInteractionManager.java.patch @@ -199,18 +199,19 @@ return flag1; } } -@@ -330,8 +352,10 @@ +@@ -330,8 +352,11 @@ } else { -+ if (net.minecraftforge.common.ForgeHooks.onItemRightClick(p_187250_1_, p_187250_4_)) return net.minecraft.util.EnumActionResult.PASS; ++ EnumActionResult cancelResult = net.minecraftforge.common.ForgeHooks.onItemRightClickAction(p_187250_1_, p_187250_4_); ++ if (cancelResult != null) return cancelResult; int i = p_187250_3_.func_190916_E(); int j = p_187250_3_.func_77960_j(); + ItemStack copyBeforeUse = p_187250_3_.func_77946_l(); ActionResult actionresult = p_187250_3_.func_77957_a(p_187250_2_, p_187250_1_, p_187250_4_); ItemStack itemstack = (ItemStack)actionresult.func_188398_b(); -@@ -360,6 +384,7 @@ +@@ -360,6 +385,7 @@ if (itemstack.func_190926_b()) { p_187250_1_.func_184611_a(p_187250_4_, ItemStack.field_190927_a); @@ -218,14 +219,14 @@ } if (!p_187250_1_.func_184587_cr()) -@@ -404,13 +429,23 @@ +@@ -404,13 +430,23 @@ } else { - if (!p_187251_1_.func_70093_af() || p_187251_1_.func_184614_ca().func_190926_b() && p_187251_1_.func_184592_cb().func_190926_b()) + net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock event = net.minecraftforge.common.ForgeHooks + .onRightClickBlock(p_187251_1_, p_187251_4_, p_187251_5_, p_187251_6_, net.minecraftforge.common.ForgeHooks.rayTraceEyeHitVec(p_187251_1_, getBlockReachDistance() + 1)); -+ if (event.isCanceled()) return EnumActionResult.PASS; ++ if (event.isCanceled()) return event.getCancellationResult(); + + EnumActionResult ret = p_187251_3_.onItemUseFirst(p_187251_1_, p_187251_2_, p_187251_5_, p_187251_4_, p_187251_6_, p_187251_7_, p_187251_8_, p_187251_9_); + if (ret != EnumActionResult.PASS) return ret; @@ -245,7 +246,7 @@ } } -@@ -438,14 +473,20 @@ +@@ -438,14 +474,20 @@ { int j = p_187251_3_.func_77960_j(); int i = p_187251_3_.func_190916_E(); @@ -266,7 +267,7 @@ } } } -@@ -455,4 +496,13 @@ +@@ -455,4 +497,13 @@ { this.field_73092_a = p_73080_1_; } diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index ad4cbccfd..809aa5666 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -1035,25 +1035,56 @@ public class ForgeHooks return git == null ? null : git.hitVec; } + // TODO 1.12 remove these three + @Deprecated public static boolean onInteractEntityAt(EntityPlayer player, Entity entity, RayTraceResult ray, EnumHand hand) { - Vec3d vec3d = new Vec3d(ray.hitVec.xCoord - entity.posX, ray.hitVec.yCoord - entity.posY, ray.hitVec.zCoord - entity.posZ); - return onInteractEntityAt(player, entity, vec3d, hand); + return onInteractEntityAtAction(player, entity, ray, hand) != null; } + @Deprecated public static boolean onInteractEntityAt(EntityPlayer player, Entity entity, Vec3d vec3d, EnumHand hand) { - return MinecraftForge.EVENT_BUS.post(new PlayerInteractEvent.EntityInteractSpecific(player, hand, entity, vec3d)); + return onInteractEntityAtAction(player, entity, vec3d, hand) != null; } + @Deprecated public static boolean onInteractEntity(EntityPlayer player, Entity entity, EnumHand hand) { - return MinecraftForge.EVENT_BUS.post(new PlayerInteractEvent.EntityInteract(player, hand, entity)); + return onInteractEntityAction(player, entity, hand) != null; } + public static EnumActionResult onInteractEntityAtAction(EntityPlayer player, Entity entity, RayTraceResult ray, EnumHand hand) + { + Vec3d vec3d = new Vec3d(ray.hitVec.xCoord - entity.posX, ray.hitVec.yCoord - entity.posY, ray.hitVec.zCoord - entity.posZ); + return onInteractEntityAtAction(player, entity, vec3d, hand); + } + + public static EnumActionResult onInteractEntityAtAction(EntityPlayer player, Entity entity, Vec3d vec3d, EnumHand hand) + { + PlayerInteractEvent.EntityInteractSpecific evt = new PlayerInteractEvent.EntityInteractSpecific(player, hand, entity, vec3d); + MinecraftForge.EVENT_BUS.post(evt); + return evt.isCanceled() ? evt.getCancellationResult() : null; + } + + public static EnumActionResult onInteractEntityAction(EntityPlayer player, Entity entity, EnumHand hand) + { + PlayerInteractEvent.EntityInteract evt = new PlayerInteractEvent.EntityInteract(player, hand, entity); + MinecraftForge.EVENT_BUS.post(evt); + return evt.isCanceled() ? evt.getCancellationResult() : null; + } + + @Deprecated // TODO 1.12 remove public static boolean onItemRightClick(EntityPlayer player, EnumHand hand) { - return MinecraftForge.EVENT_BUS.post(new PlayerInteractEvent.RightClickItem(player, hand)); + return onItemRightClickAction(player, hand) != null; + } + + public static EnumActionResult onItemRightClickAction(EntityPlayer player, EnumHand hand) + { + PlayerInteractEvent.RightClickItem evt = new PlayerInteractEvent.RightClickItem(player, hand); + MinecraftForge.EVENT_BUS.post(evt); + return evt.isCanceled() ? evt.getCancellationResult() : null; } public static PlayerInteractEvent.LeftClickBlock onLeftClickBlock(EntityPlayer player, BlockPos pos, EnumFacing face, Vec3d hitVec) diff --git a/src/main/java/net/minecraftforge/event/entity/player/PlayerInteractEvent.java b/src/main/java/net/minecraftforge/event/entity/player/PlayerInteractEvent.java index 4192786d4..fb256b965 100644 --- a/src/main/java/net/minecraftforge/event/entity/player/PlayerInteractEvent.java +++ b/src/main/java/net/minecraftforge/event/entity/player/PlayerInteractEvent.java @@ -23,6 +23,7 @@ import com.google.common.base.Preconditions; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; @@ -49,6 +50,7 @@ public class PlayerInteractEvent extends PlayerEvent private final BlockPos pos; @Nullable private final EnumFacing face; + private EnumActionResult cancellationResult = EnumActionResult.PASS; private PlayerInteractEvent(EntityPlayer player, EnumHand hand, BlockPos pos, @Nullable EnumFacing face) { @@ -63,11 +65,9 @@ public class PlayerInteractEvent extends PlayerEvent * * "Interact at" is an interact where the local vector (which part of the entity you clicked) is known. * The state of this event affects whether {@link Entity#applyPlayerInteraction} is called. - * If {@link Entity#applyPlayerInteraction} returns {@link net.minecraft.util.EnumActionResult#SUCCESS}, then processing ends. - * Otherwise processing will continue to {@link EntityInteract} * - * Canceling the event clientside will cause processing to continue to {@link EntityInteract}, - * while canceling serverside will simply do no further processing. + * Let result be the return value of {@link Entity#applyPlayerInteraction}, or {@link #cancellationResult} if the event is cancelled. + * If we are on the client and result is not {@link EnumActionResult#SUCCESS}, the client will then try {@link EntityInteract}. */ @Cancelable public static class EntityInteractSpecific extends PlayerInteractEvent @@ -103,14 +103,12 @@ public class PlayerInteractEvent extends PlayerEvent * This event is fired on both sides when the player right clicks an entity. * It is responsible for all general entity interactions. * - * This event is fired completely independently of the above {@link EntityInteractSpecific}, except for the case - * where the above call to {@link Entity#applyPlayerInteraction} returns {@link net.minecraft.util.EnumActionResult#SUCCESS}. - * In that case, general entity interactions, and hence this event, will not be called. See the above javadoc for more details. - * + * This event is fired only if the result of the above {@link EntityInteractSpecific} is not {@link EnumActionResult#SUCCESS}. * This event's state affects whether {@link Entity#processInitialInteract} and {@link net.minecraft.item.Item#itemInteractionForEntity} are called. * - * Canceling the event clientside will cause processing to continue to {@link RightClickItem}, - * while canceling serverside will simply do no further processing. + * Let result be {@link EnumActionResult#SUCCESS} if {@link Entity#processInitialInteract} or {@link net.minecraft.item.Item#itemInteractionForEntity} return true, + * or {@link #cancellationResult} if the event is cancelled. + * If we are on the client and result is not {@link EnumActionResult#SUCCESS}, the client will then try {@link RightClickItem}. */ @Cancelable public static class EntityInteract extends PlayerInteractEvent @@ -133,7 +131,11 @@ public class PlayerInteractEvent extends PlayerEvent * This event is fired on both sides whenever the player right clicks while targeting a block. * This event controls which of {@link net.minecraft.block.Block#onBlockActivated} and/or {@link net.minecraft.item.Item#onItemUse} * will be called after {@link net.minecraft.item.Item#onItemUseFirst} is called. - * Canceling the event will cause none of the above three to be called. + * Canceling the event will cause none of the above three to be called + * + * Let result be a return value of the above three methods, or {@link #cancellationResult} if the event is cancelled. + * If we are on the client and result is not {@link EnumActionResult#SUCCESS}, the client will then try {@link RightClickItem}. + * * There are various results to this event, see the getters below. * Note that handling things differently on the client vs server may cause desynchronizations! */ @@ -207,9 +209,10 @@ public class PlayerInteractEvent extends PlayerEvent /** * This event is fired on both sides before the player triggers {@link net.minecraft.item.Item#onItemRightClick}. - * Note that this is NOT fired if the player is targeting a block. For that case, see {@link RightClickBlock}. - * Canceling the event clientside causes processing to continue to the other hands, - * while canceling serverside will simply do no further processing. + * Note that this is NOT fired if the player is targeting a block {@link RightClickBlock} or entity {@link EntityInteract} {@link EntityInteractSpecific}. + * + * Let result be the return value of {@link net.minecraft.item.Item#onItemRightClick}, or {@link #cancellationResult} if the event is cancelled. + * If we are on the client and result is not {@link EnumActionResult#SUCCESS}, the client will then continue to other hands. */ @Cancelable public static class RightClickItem extends PlayerInteractEvent @@ -381,4 +384,24 @@ public class PlayerInteractEvent extends PlayerEvent return getWorld().isRemote ? Side.CLIENT : Side.SERVER; } + /** + * @return The EnumActionResult that will be returned to vanilla if the event is cancelled, instead of calling the relevant + * method of the event. By default, this is {@link EnumActionResult#PASS}, meaning cancelled events will cause + * the client to keep trying more interactions until something works. + */ + public EnumActionResult getCancellationResult() + { + return cancellationResult; + } + + /** + * Set the EnumActionResult that will be returned to vanilla if the event is cancelled, instead of calling the relevant + * method of the event. + * Note that this only has an effect on {@link RightClickBlock}, {@link RightClickItem}, {@link EntityInteract}, and {@link EntityInteractSpecific}. + */ + public void setCancellationResult(EnumActionResult result) + { + this.cancellationResult = result; + } + } diff --git a/src/test/java/net/minecraftforge/test/PlayerInteractEventTest.java b/src/test/java/net/minecraftforge/test/PlayerInteractEventTest.java index 116186bab..4dea7c2ed 100644 --- a/src/test/java/net/minecraftforge/test/PlayerInteractEventTest.java +++ b/src/test/java/net/minecraftforge/test/PlayerInteractEventTest.java @@ -5,9 +5,11 @@ import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.monster.EntitySkeleton; import net.minecraft.entity.passive.EntityHorse; import net.minecraft.init.Items; +import net.minecraft.item.ItemBlock; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.tileentity.TileEntityDropper; +import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.PlayerInteractEvent; @@ -49,7 +51,7 @@ public class PlayerInteractEventTest if (!ENABLE) return; logger.info("HIT VEC: {}", evt.getHitVec()); - if (evt.getItemStack() != null) + if (!evt.getItemStack().isEmpty()) { if (evt.getItemStack().getItem() == Items.GOLDEN_PICKAXE) evt.setCanceled(true); // Redstone should not activate and pick should not be able to dig anything @@ -89,22 +91,34 @@ public class PlayerInteractEventTest // Case: Flint and steel in main hand on top of a TE will light a fire, not open the TE. // Note that if you do this on a chest, the f+s will fail, but then your off hand will open the chest // If you dual wield flints and steels and right click a chest nothing should happen - if (evt.getItemStack() != null && evt.getItemStack().getItem() == Items.FLINT_AND_STEEL) + if (!evt.getItemStack().isEmpty() && evt.getItemStack().getItem() == Items.FLINT_AND_STEEL) evt.setUseBlock(Event.Result.DENY); // Case: Painting in main hand // Opening a TE will also place a painting on the TE if possible - if (evt.getHand() == EnumHand.MAIN_HAND && evt.getItemStack() != null && evt.getItemStack().getItem() == Items.PAINTING) { + if (evt.getHand() == EnumHand.MAIN_HAND && !evt.getItemStack().isEmpty() && evt.getItemStack().getItem() == Items.PAINTING) { evt.setUseItem(Event.Result.ALLOW); } // Spawn egg in main hand, block in offhand -> block should be placed - // Sword in main hand, spawn egg in offhand -> nothing should happen - if (evt.getItemStack() != null && evt.getItemStack().getItem() == Items.SPAWN_EGG) { + if (!evt.getItemStack().isEmpty() + && evt.getItemStack().getItem() == Items.SPAWN_EGG + && evt.getHand() == EnumHand.MAIN_HAND + && !evt.getEntityPlayer().getHeldItemOffhand().isEmpty() + && evt.getEntityPlayer().getHeldItemOffhand().getItem() instanceof ItemBlock) { evt.setCanceled(true); } - + // Spawn egg in main hand, potion in offhand -> potion should NOT be thrown + if (!evt.getItemStack().isEmpty() + && evt.getItemStack().getItem() == Items.SPAWN_EGG + && evt.getHand() == EnumHand.MAIN_HAND + && !evt.getEntityPlayer().getHeldItemOffhand().isEmpty() + && evt.getEntityPlayer().getHeldItemOffhand().getItem() == Items.SPLASH_POTION) { + evt.setCanceled(true); + // Fake spawn egg success so splash potion does not trigger + evt.setCancellationResult(EnumActionResult.SUCCESS); + } } @SubscribeEvent @@ -112,12 +126,24 @@ public class PlayerInteractEventTest { if (!ENABLE) return; - // Use survival mode + // Case: Ender pearl in main hand, block in offhand -> Block is NOT placed + if (!evt.getItemStack().isEmpty() + && evt.getItemStack().getItem() == Items.ENDER_PEARL + && evt.getHand() == EnumHand.MAIN_HAND + && !evt.getEntityPlayer().getHeldItemOffhand().isEmpty() + && evt.getEntityPlayer().getHeldItemOffhand().getItem() instanceof ItemBlock) + { + evt.setCanceled(true); + evt.setCancellationResult(EnumActionResult.SUCCESS); // We fake success on the ender pearl so block is not placed + return; + } + // Case: Ender pearl in main hand, bow in offhand with arrows in inv -> Bow should trigger // Case: Sword in main hand, ender pearl in offhand -> Nothing should happen - - if (evt.getItemStack() != null && evt.getItemStack().getItem() == Items.ENDER_PEARL) + if (!evt.getItemStack().isEmpty() && evt.getItemStack().getItem() == Items.ENDER_PEARL) + { evt.setCanceled(true); + } } @SubscribeEvent @@ -126,17 +152,27 @@ public class PlayerInteractEventTest if (!ENABLE) return; logger.info("LOCAL POS: {}", evt.getLocalPos()); - if (evt.getItemStack() != null + if (!evt.getItemStack().isEmpty() && evt.getTarget() instanceof EntityArmorStand && evt.getItemStack().getItem() == Items.IRON_HELMET) evt.setCanceled(true); // Should not be able to place iron helmet onto armor stand (you will put it on instead) - if (evt.getWorld().isRemote + if (!evt.getItemStack().isEmpty() + && evt.getTarget() instanceof EntityArmorStand + && evt.getItemStack().getItem() == Items.GOLDEN_HELMET) + { + evt.setCanceled(true); + evt.setCancellationResult(EnumActionResult.SUCCESS); + // Should not be able to place golden helmet onto armor stand + // However you will NOT put it on because we fake success on the armorstand. + } + + if (!evt.getWorld().isRemote && evt.getTarget() instanceof EntitySkeleton && evt.getLocalPos().yCoord > evt.getTarget().height / 2.0) { // If we right click the upper half of a skeleton it dies. - ((EntitySkeleton) evt.getTarget()).setDead(); + evt.getTarget().setDead(); evt.setCanceled(true); } } @@ -146,10 +182,18 @@ public class PlayerInteractEventTest { if (!ENABLE) return; - if (evt.getItemStack() != null && (evt.getTarget() instanceof EntityHorse || evt.getTarget() instanceof EntityCreeper)) + if (!evt.getItemStack().isEmpty() && evt.getTarget() instanceof EntityHorse) { // Should not be able to feed wild horses with golden apple (you will start eating it in survival) - // Should not be able to ignite creeper with F+S - // Applies to both hands - evt.setCanceled(true); + if (evt.getItemStack().getItem() == Items.GOLDEN_APPLE + && evt.getItemStack().getItemDamage() == 0) + evt.setCanceled(true); + // Should not be able to feed wild horses with notch apple but you will NOT eat it + if (evt.getItemStack().getItem() == Items.GOLDEN_APPLE + && evt.getItemStack().getItemDamage() == 1) + { + evt.setCanceled(true); + evt.setCancellationResult(EnumActionResult.SUCCESS); + } + } } }