diff --git a/patches/minecraft/net/minecraft/entity/EntityLivingBase.java.patch b/patches/minecraft/net/minecraft/entity/EntityLivingBase.java.patch
index 14d681529c..294442cf19 100644
--- a/patches/minecraft/net/minecraft/entity/EntityLivingBase.java.patch
+++ b/patches/minecraft/net/minecraft/entity/EntityLivingBase.java.patch
@@ -141,7 +141,17 @@
}
this.field_70170_p.func_72960_a(this, (byte)3);
-@@ -1253,15 +1273,7 @@
+@@ -1195,6 +1215,9 @@
+
+ public void func_70653_a(Entity p_70653_1_, float p_70653_2_, double p_70653_3_, double p_70653_5_)
+ {
++ net.minecraftforge.event.entity.living.LivingKnockBackEvent event = net.minecraftforge.common.ForgeHooks.onLivingKnockBack(this, p_70653_1_, p_70653_2_, p_70653_3_, p_70653_5_);
++ if(event.isCanceled()) return;
++ p_70653_2_ = event.getStrength(); p_70653_3_ = event.getRatioX(); p_70653_5_ = event.getRatioZ();
+ if (this.field_70146_Z.nextDouble() >= this.func_110148_a(SharedMonsterAttributes.field_111266_c).func_111126_e())
+ {
+ this.field_70160_al = true;
+@@ -1253,15 +1276,7 @@
BlockPos blockpos = new BlockPos(i, j, k);
IBlockState iblockstate = this.field_70170_p.func_180495_p(blockpos);
Block block = iblockstate.func_177230_c();
@@ -158,7 +168,7 @@
}
}
-@@ -1287,6 +1299,9 @@
+@@ -1287,6 +1302,9 @@
public void func_180430_e(float p_180430_1_, float p_180430_2_)
{
@@ -168,7 +178,7 @@
super.func_180430_e(p_180430_1_, p_180430_2_);
PotionEffect potioneffect = this.func_70660_b(MobEffects.field_76430_j);
float f = potioneffect == null ? 0.0F : (float)(potioneffect.func_76458_c() + 1);
-@@ -1303,7 +1318,7 @@
+@@ -1303,7 +1321,7 @@
if (iblockstate.func_185904_a() != Material.field_151579_a)
{
@@ -177,7 +187,7 @@
this.func_184185_a(soundtype.func_185842_g(), soundtype.func_185843_a() * 0.5F, soundtype.func_185847_b() * 0.75F);
}
}
-@@ -1380,17 +1395,20 @@
+@@ -1380,17 +1398,20 @@
{
if (!this.func_180431_b(p_70665_1_))
{
@@ -199,7 +209,7 @@
this.func_110149_m(this.func_110139_bj() - p_70665_2_);
}
}
-@@ -1447,6 +1465,11 @@
+@@ -1447,6 +1468,11 @@
public void func_184609_a(EnumHand p_184609_1_)
{
@@ -211,7 +221,7 @@
if (!this.field_82175_bq || this.field_110158_av >= this.func_82166_i() / 2 || this.field_110158_av < 0)
{
this.field_110158_av = -1;
-@@ -1694,7 +1717,7 @@
+@@ -1694,7 +1720,7 @@
if (!this.field_70170_p.func_184143_b(axisalignedbb1))
{
@@ -220,7 +230,7 @@
{
this.func_70634_a(d11, this.field_70163_u + 1.0D, d12);
return;
-@@ -1702,14 +1725,14 @@
+@@ -1702,14 +1728,14 @@
BlockPos blockpos = new BlockPos(d11, this.field_70163_u - 1.0D, d12);
@@ -237,7 +247,7 @@
{
d1 = d11;
d13 = this.field_70163_u + 2.0D;
-@@ -1781,6 +1804,7 @@
+@@ -1781,6 +1807,7 @@
}
this.field_70160_al = true;
@@ -245,7 +255,7 @@
}
protected void func_70629_bd()
-@@ -1874,7 +1898,8 @@
+@@ -1874,7 +1901,8 @@
if (this.field_70122_E)
{
@@ -255,7 +265,7 @@
}
float f7 = 0.16277136F / (f6 * f6 * f6);
-@@ -1894,7 +1919,8 @@
+@@ -1894,7 +1922,8 @@
if (this.field_70122_E)
{
@@ -265,7 +275,7 @@
}
if (this.func_70617_f_())
-@@ -2054,6 +2080,7 @@
+@@ -2054,6 +2083,7 @@
public void func_70071_h_()
{
@@ -273,7 +283,7 @@
super.func_70071_h_();
this.func_184608_ct();
-@@ -2096,7 +2123,9 @@
+@@ -2096,7 +2126,9 @@
if (!ItemStack.func_77989_b(itemstack1, itemstack))
{
@@ -283,7 +293,7 @@
if (!itemstack.func_190926_b())
{
-@@ -2575,6 +2604,40 @@
+@@ -2575,6 +2607,40 @@
this.field_70752_e = true;
}
@@ -324,7 +334,7 @@
public abstract EnumHandSide func_184591_cq();
public boolean func_184587_cr()
-@@ -2595,12 +2658,19 @@
+@@ -2595,12 +2661,19 @@
if (itemstack == this.field_184627_bm)
{
@@ -345,7 +355,7 @@
{
this.func_71036_o();
}
-@@ -2618,8 +2688,10 @@
+@@ -2618,8 +2691,10 @@
if (!itemstack.func_190926_b() && !this.func_184587_cr())
{
@@ -357,7 +367,7 @@
if (!this.field_70170_p.field_72995_K)
{
-@@ -2700,7 +2772,9 @@
+@@ -2700,7 +2775,9 @@
if (!this.field_184627_bm.func_190926_b() && this.func_184587_cr())
{
this.func_184584_a(this.field_184627_bm, 16);
@@ -368,7 +378,7 @@
this.func_184602_cy();
}
}
-@@ -2724,7 +2798,8 @@
+@@ -2724,7 +2801,8 @@
{
if (!this.field_184627_bm.func_190926_b())
{
@@ -378,7 +388,7 @@
}
this.func_184602_cy();
-@@ -2852,6 +2927,31 @@
+@@ -2852,6 +2930,31 @@
return true;
}
diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java
index 355ba5187f..1396139c98 100644
--- a/src/main/java/net/minecraftforge/common/ForgeHooks.java
+++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java
@@ -120,6 +120,7 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingJumpEvent;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.event.entity.living.LivingFallEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
+import net.minecraftforge.event.entity.living.LivingKnockBackEvent;
import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent;
import net.minecraftforge.event.entity.living.LootingLevelEvent;
import net.minecraftforge.event.entity.player.AnvilRepairEvent;
@@ -560,6 +561,13 @@ public class ForgeHooks
return !MinecraftForge.EVENT_BUS.post(new LivingAttackEvent(entity, src, amount));
}
+ public static LivingKnockBackEvent onLivingKnockBack(EntityLivingBase target, Entity attacker, float strength, double ratioX, double ratioZ)
+ {
+ LivingKnockBackEvent event = new LivingKnockBackEvent(target, attacker, strength, ratioX, ratioZ);
+ MinecraftForge.EVENT_BUS.post(event);
+ return event;
+ }
+
public static float onLivingHurt(EntityLivingBase entity, DamageSource src, float amount)
{
LivingHurtEvent event = new LivingHurtEvent(entity, src, amount);
diff --git a/src/main/java/net/minecraftforge/event/entity/living/LivingKnockBackEvent.java b/src/main/java/net/minecraftforge/event/entity/living/LivingKnockBackEvent.java
new file mode 100644
index 0000000000..138c7ab193
--- /dev/null
+++ b/src/main/java/net/minecraftforge/event/entity/living/LivingKnockBackEvent.java
@@ -0,0 +1,95 @@
+/*
+ * Minecraft Forge
+ * Copyright (c) 2017.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package net.minecraftforge.event.entity.living;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.monster.EntityMob;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.util.DamageSource;
+import net.minecraftforge.common.ForgeHooks;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.common.eventhandler.Cancelable;
+
+/**
+ * LivingKnockBackEvent is fired when a living entity is about to be knocked back.
+ * This event is fired whenever an Entity is knocked back in
+ * {@link EntityLivingBase#attackEntityFrom(DamageSource, float)},
+ * {@link EntityLivingBase#blockWithShield(EntityLivingBase)},
+ * {@link EntityMob#attackEntityAsMob(Entity)} and
+ * {@link EntityPlayer#attackTargetEntityWithCurrentItem(Entity)}
+ *
+ * This event is fired via {@link ForgeHooks#onLivingKnockBack(EntityLivingBase, Entity, float, double, double)}.
+ *
+ * {@link #attacker} contains the Entity that caused the knock back.
+ * {@link #strength} contains the strength of the knock back.
+ * {@link #ratioX} contains the x ratio of the knock back.
+ * {@link #ratioZ} contains the z ratio of the knock back.
+ *
+ * This event is {@link Cancelable}.
+ * If this event is canceled, the entity is not knocked back.
+ *
+ * This event does not have a result. {@link HasResult}
+ *
+ * This event is fired on the {@link MinecraftForge#EVENT_BUS}.
+ **/
+@Cancelable
+public class LivingKnockBackEvent extends LivingEvent
+{
+ protected Entity attacker;
+ protected float strength;
+ protected double ratioX, ratioZ;
+ protected final Entity originalAttacker;
+ protected final float originalStrength;
+ protected final double originalRatioX, originalRatioZ;
+
+ public LivingKnockBackEvent(EntityLivingBase target, Entity attacker, float strength, double ratioX, double ratioZ)
+ {
+ super(target);
+ this.attacker = this.originalAttacker = attacker;
+ this.strength = this.originalStrength = strength;
+ this.ratioX = this.originalRatioX = ratioX;
+ this.ratioZ = this.originalRatioZ = ratioZ;
+ }
+
+ public Entity getAttacker() {return this.attacker;}
+
+ public float getStrength() {return this.strength;}
+
+ public double getRatioX() {return this.ratioX;}
+
+ public double getRatioZ() {return this.ratioZ;}
+
+ public Entity getOriginalAttacker() {return this.originalAttacker;}
+
+ public float getOriginalStrength() {return this.originalStrength;}
+
+ public double getOriginalRatioX() {return this.originalRatioX;}
+
+ public double getOriginalRatioZ() {return this.originalRatioZ;}
+
+ public void setAttacker(Entity attacker) {this.attacker = attacker;}
+
+ public void setStrength(float strength) {this.strength = strength;}
+
+ public void setRatioX(double ratioX) {this.ratioX = ratioX;}
+
+ public void setRatioZ(double ratioZ) {this.ratioZ = ratioZ;}
+}
\ No newline at end of file
diff --git a/src/test/java/net/minecraftforge/debug/KnockBackHookTest.java b/src/test/java/net/minecraftforge/debug/KnockBackHookTest.java
new file mode 100644
index 0000000000..a494ec887e
--- /dev/null
+++ b/src/test/java/net/minecraftforge/debug/KnockBackHookTest.java
@@ -0,0 +1,30 @@
+package net.minecraftforge.debug;
+
+import net.minecraft.entity.passive.EntityCow;
+import net.minecraft.entity.passive.EntitySheep;
+import net.minecraftforge.event.entity.living.LivingKnockBackEvent;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+@Mod(modid = "kbhtest", name = "Knock Back Hook Test", version = "1.0")
+@Mod.EventBusSubscriber
+public class KnockBackHookTest
+{
+ private static final boolean ENABLED = false;
+
+ @SubscribeEvent
+ public static void onKnockBack(LivingKnockBackEvent event)
+ {
+ if(ENABLED)
+ {
+ if(event.getEntityLiving() instanceof EntitySheep)
+ {
+ event.setStrength(0.2F);
+ }
+ else if(event.getEntityLiving() instanceof EntityCow)
+ {
+ event.setCanceled(true);
+ }
+ }
+ }
+}
\ No newline at end of file