diff --git a/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch b/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch index 4b150ab48c..7bbd41060b 100644 --- a/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch +++ b/patches/minecraft/net/minecraft/entity/player/EntityPlayer.java.patch @@ -273,7 +273,20 @@ if (p_71059_1_.func_70075_an()) { if (!p_71059_1_.func_85031_j(this)) -@@ -1332,10 +1412,12 @@ +@@ -1203,9 +1283,11 @@ + boolean flag2 = flag && this.field_70143_R > 0.0F && !this.field_70122_E && !this.func_70617_f_() && !this.func_70090_H() && !this.func_70644_a(MobEffects.field_76440_q) && !this.func_184218_aH() && p_71059_1_ instanceof EntityLivingBase; + flag2 = flag2 && !this.func_70051_ag(); + ++ net.minecraftforge.event.entity.player.CriticalHitEvent hitResult = net.minecraftforge.common.ForgeHooks.getCriticalHit(this, p_71059_1_, flag2, flag2 ? 1.5F : 1.0F); ++ flag2 = hitResult != null; + if (flag2) + { +- f *= 1.5F; ++ f *= hitResult.getDamageModifier(); + } + + f = f + f1; +@@ -1332,10 +1414,12 @@ if (!itemstack1.func_190926_b() && entity instanceof EntityLivingBase) { @@ -286,7 +299,7 @@ this.func_184611_a(EnumHand.MAIN_HAND, ItemStack.field_190927_a); } } -@@ -1384,7 +1466,7 @@ +@@ -1384,7 +1468,7 @@ if (this.field_70146_Z.nextFloat() < f) { @@ -295,7 +308,7 @@ this.func_184602_cy(); this.field_70170_p.func_72960_a(this, (byte)30); } -@@ -1442,6 +1524,8 @@ +@@ -1442,6 +1526,8 @@ public EntityPlayer.SleepResult func_180469_a(BlockPos p_180469_1_) { @@ -304,7 +317,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 +1568,9 @@ +@@ -1484,8 +1570,9 @@ this.func_192030_dh(); this.func_70105_a(0.2F, 0.2F); @@ -316,7 +329,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 +1617,14 @@ +@@ -1532,13 +1619,14 @@ public void func_70999_a(boolean p_70999_1_, boolean p_70999_2_, boolean p_70999_3_) { @@ -334,7 +347,7 @@ if (blockpos == null) { -@@ -1547,6 +1633,10 @@ +@@ -1547,6 +1635,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)); } @@ -345,7 +358,7 @@ this.field_71083_bS = false; -@@ -1565,15 +1655,16 @@ +@@ -1565,15 +1657,16 @@ private boolean func_175143_p() { @@ -365,7 +378,7 @@ { if (!p_180467_2_) { -@@ -1588,16 +1679,17 @@ +@@ -1588,16 +1681,17 @@ } else { @@ -386,7 +399,7 @@ switch (enumfacing) { -@@ -1637,16 +1729,24 @@ +@@ -1637,16 +1731,24 @@ public BlockPos func_180470_cg() { @@ -413,7 +426,7 @@ if (p_180473_1_ != null) { this.field_71077_c = p_180473_1_; -@@ -1839,6 +1939,10 @@ +@@ -1839,6 +1941,10 @@ super.func_180430_e(p_180430_1_, p_180430_2_); } @@ -424,7 +437,7 @@ } protected void func_71061_d_() -@@ -2176,7 +2280,10 @@ +@@ -2176,7 +2282,10 @@ public ITextComponent func_145748_c_() { @@ -436,7 +449,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_()); -@@ -2185,7 +2292,7 @@ +@@ -2185,7 +2294,7 @@ public float func_70047_e() { @@ -445,7 +458,7 @@ if (this.func_70608_bn()) { -@@ -2421,6 +2528,168 @@ +@@ -2421,6 +2530,168 @@ return this.field_71075_bZ.field_75098_d && this.func_70003_b(2, ""); } diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index 542a662021..f300ed74b3 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.LivingSetAttackTargetEvent; import net.minecraftforge.event.entity.living.LootingLevelEvent; import net.minecraftforge.event.entity.player.AnvilRepairEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; +import net.minecraftforge.event.entity.player.CriticalHitEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.world.BlockEvent; @@ -1259,6 +1260,18 @@ public class ForgeHooks return errored; } + @Nullable + public static CriticalHitEvent getCriticalHit(EntityPlayer player, Entity target, boolean vanillaCritical, float damageModifier) + { + CriticalHitEvent hitResult = new CriticalHitEvent(player, target, damageModifier, vanillaCritical); + MinecraftForge.EVENT_BUS.post(hitResult); + if (hitResult.getResult() == Event.Result.ALLOW || (vanillaCritical && hitResult.getResult() == Event.Result.DEFAULT)) + { + return hitResult; + } + return null; + } + private static void setActiveModContainer(ModContainer mod) { if (Loader.instance().getLoaderState() != LoaderState.NOINIT) //Unit Tests.. diff --git a/src/main/java/net/minecraftforge/event/entity/player/CriticalHitEvent.java b/src/main/java/net/minecraftforge/event/entity/player/CriticalHitEvent.java new file mode 100644 index 0000000000..dea7f8d6a7 --- /dev/null +++ b/src/main/java/net/minecraftforge/event/entity/player/CriticalHitEvent.java @@ -0,0 +1,100 @@ +/* + * Minecraft Forge + * Copyright (c) 2016. + * + * 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.player; + +import net.minecraftforge.fml.common.eventhandler.Event.HasResult; +import net.minecraftforge.fml.common.eventhandler.Cancelable; +import net.minecraftforge.common.MinecraftForge; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; + +/** + * This event is fired whenever a player attacks an Entity in + * EntityPlayer#attackTargetEntityWithCurrentItem(Entity).
+ *
+ * This event is not {@link Cancelable}.
+ *
+ * This event has a result. {@link HasResult}
+ * DEFAULT: means the vanilla logic will determine if this a critical hit.
+ * DENY: it will not be a critical hit but the player still will attack
+ * ALLOW: this attack is forced to be critical + *
+ * This event is fired on the {@link MinecraftForge#EVENT_BUS}. + **/ +@HasResult +public class CriticalHitEvent extends PlayerEvent +{ + private float damageModifier; + private final float oldDamageModifier; + private final Entity target; + private final boolean vanillaCritical; + + public CriticalHitEvent(EntityPlayer player, Entity target, float damageModifier, boolean vanillaCritical) + { + super(player); + this.target = target; + this.damageModifier = damageModifier; + this.oldDamageModifier = damageModifier; + this.vanillaCritical = vanillaCritical; + } + + /** + * The Entity that was damaged by the player. + */ + public Entity getTarget() + { + return target; + } + + /** + * This set the damage multiplier for the hit. + * If you set it to 0, then the particles are still generated but damage is not done. + */ + public void setDamageModifier(float mod) + { + this.damageModifier = mod; + } + + /** + * The damage modifier for the hit.
+ * This is by default 1.5F for ciritcal hits and 1F for normal hits . + */ + public float getDamageModifier() + { + return this.damageModifier; + } + + /** + * The orignal damage modifier for the hit wthout any changes.
+ * This is 1.5F for ciritcal hits and 1F for normal hits . + */ + public float getOldDamageModifier() + { + return this.oldDamageModifier; + } + + /** + * Returns true if this hit was critical by vanilla + */ + public boolean isVanillaCritical() + { + return vanillaCritical; + } +} \ No newline at end of file diff --git a/src/test/java/net/minecraftforge/debug/CriticalHitEventTest.java b/src/test/java/net/minecraftforge/debug/CriticalHitEventTest.java new file mode 100644 index 0000000000..a5bc82ca51 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/CriticalHitEventTest.java @@ -0,0 +1,69 @@ +package net.minecraftforge.debug; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.CriticalHitEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.eventhandler.Event.Result; +import org.apache.logging.log4j.Logger; + +import net.minecraft.util.EnumHand; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; + +@Mod(modid = "criticalhiteventtest", name = "CriticalHitEventTest", version = "1.0.0", acceptableRemoteVersions = "*") +public class CriticalHitEventTest +{ + public static final boolean ENABLE = false; + private Logger log; + + @EventHandler + public void preInit(FMLPreInitializationEvent event) + { + log = event.getModLog(); + } + + @EventHandler + public void init(FMLInitializationEvent event) + { + if (ENABLE) + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onCriticalHit(CriticalHitEvent event) + { + ItemStack itemstack = event.getEntityPlayer().getHeldItem(EnumHand.MAIN_HAND); + + if(event.getDamageModifier()>1F) + { + log.info("By default this hit will be critical."); + } + else + { + log.info("By default this hit won't be critical."); + } + + if (itemstack.getItem() instanceof ItemSword) + { + event.setResult(Result.ALLOW); //Every hit is Critical + log.info("This hit will be critical."); + } + else if (!itemstack.isEmpty()) + { + event.setResult(Result.DENY);//No hit will be Critical + log.info("This hit wont be critical."); + } + else + { + event.setResult(Result.DEFAULT); //Vanilla Hits + } + + log.info("{} got hit by {} with a damagemodifier of {}" , event.getTarget(), event.getEntityPlayer(), event.getDamageModifier()); + event.setDamageModifier(2.0F); + log.info("The damagemodifier is changed to {}", event.getDamageModifier()); + } +}