Solved Cancelling a PlayerDeathEvent

Discussion in 'Plugin Development' started by BungeeTheCookie, May 25, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    BungeeTheCookie

    Hello Bukkitteers! I know cancelling a deathevent is not possible. How do you see if the damage done to a player kills the player?
    Code:java
    1. (p.getHealth() - e.getDamage()) <= 0
    does not take armor, potions, and other buffs into effect. How do you make it take all of the values into account, and then cancel the EntityDamageEvent. Is there some algorithm, method hidden in Bukkit, NMS or OBC, etc. that I can use? Thank you!
     
  2. Offline

    Bammerbom

    BungeeTheCookie Are you using this for fast respawn?
    If yes threre are much easier ways with reflection.
     
  3. Offline

    mine-care

    Umm mabe u need to get the health to (the health after da hit) but before the hit is executed and match it. Why bypass death event? I might think of a way if I know da reason
    Thanks
     
  4. Offline

    mythbusterma

    You could fake the respawn packet and then teleport the player for similar effect, beyond that I have nothing.
     
  5. Offline

    mine-care

    And if u willing to use packets use the auto respawn packet.
     
  6. mine-care What did you think he meant by the respawn packet? :p
     
  7. Offline

    1Rogue

    Code:java
    1. if (/*damage taken*/ >= /*total entity health*/) {...}
     
  8. Offline

    mine-care

    Cause he said fake the packet and teleport I thought he ment to block the packet and instead of auto respawn, just tp to spawn :S sorry
     
  9. Offline

    L33m4n123

    as 1Rogue said in the EntityDamageByEntity event. If the entity that gets damaged is a player and the damage is >= his health then cancel the damage event and do your respawn code
     
  10. Offline

    mine-care


    Ehm look at my older post... :p
    That's wha I said
     
  11. Offline

    BungeeTheCookie

    Bammerbom mine-care mythbusterma AdamQpzm 1Rogue
    No, this is actually what I do not want. I just simply do not want the player to die. Not by a player, but by any environmental thing, that is why I am only using EntityDamageEvent.
     
  12. Offline

    CoderMusgrove

    I use this all the time. Just a simple check:

    Code:
    @EventHandler
    public void onEntityDamage(EntityDamageEvent e) {
        if (e.getEntity() instanceof Player) {
            Player p = (Player) e.getEntity();
            double health = p.getHealth();
            double maxHealth = p.getMaxHealth();
            double damage = e.getDamage();
            if (health - damage >= 0) {
                e.setCancelled(true);
                p.setHealth(maxHealth);
                // fake rest of death here
            }
        }
    }
     
  13. Offline

    mythbusterma

    You could also consider cancelling any damage events, then they would never die.
     
  14. Offline

    1Rogue

    So then what's wrong with my method, considering that it can work for any type of damage?
     
  15. CoderMusgrove 1Rogue getDamage() returns the amount before taking into account things like armour. BungeeTheCookie wants the amount after taking into account the armour, potion effects, etc. so that, I assume, he can be sure the player would die without false positives.
     
  16. Offline

    BungeeTheCookie

    mythbusterma That's what I want to do. I need to get this check right first. Because it doesn't take any of the armor or potions into effect.

    CoderMusgrove That is the exact opposite of what I want to use. Please read the thread.
     
  17. Offline

    fireblast709

    BungeeTheCookie this should pretty much sum it up. Just ignore the placement of some methods, I have place some in a different spoiler, but kept them like this since it was the chronological order. Just a heads up, there are randoms involved, so unless you are going to manually override the damage system, you won't be able to properly predict the damage done (unless, of course, you wan to override the random in EnchantmentManager with a custom Random that stores the next value that will be used)
    EntityPlayer (open)
    Code:java
    1. public boolean damageEntity(DamageSource damagesource, float f)
    2. {
    3. if (this.isInvulnerable())
    4. {
    5. return false;
    6. }
    7. else
    8. {
    9. // CraftBukkit - this.server.getPvP() -> this.world.pvpMode
    10. boolean flag = this.server.X() && this.world.pvpMode && "fall".equals(damagesource.translationIndex);
    11.  
    12. if (!flag && this.invulnerableTicks > 0 && damagesource != DamageSource.OUT_OF_WORLD)
    13. {
    14. return false;
    15. }
    16. else
    17. {
    18. if (damagesource instanceof EntityDamageSource)
    19. {
    20. Entity entity = damagesource.getEntity();
    21. // this.a(EntityHuman) checks whether the other player can hurt this player.
    22. if (entity instanceof EntityHuman && !this.a((EntityHuman) entity))
    23. {
    24. return false;
    25. }
    26.  
    27. if (entity instanceof EntityArrow)
    28. {
    29. EntityArrow entityarrow = (EntityArrow) entity;
    30.  
    31. if (entityarrow.shooter instanceof EntityHuman && !this.a((EntityHuman) entityarrow.shooter))
    32. {
    33. return false;
    34. }
    35. }
    36. }
    37. return super.damageEntity(damagesource, f);
    38. }
    39. }
    40. }

    EntityHuman (open)
    Code:java
    1. public boolean damageEntity(DamageSource damagesource, float f) {
    2. if (this.isInvulnerable())
    3. {
    4. return false;
    5. }
    6. else if (this.abilities.isInvulnerable && !damagesource.ignoresInvulnerability())
    7. {
    8. return false;
    9. }
    10. else
    11. {
    12. this.aU = 0;
    13. if (this.getHealth() <= 0.0F)
    14. {
    15. return false;
    16. }
    17. else
    18. {
    19. // Just wakes people up I guess
    20. if (this.isSleeping() && !this.world.isStatic)
    21. {
    22. this.a(true, true, false);
    23. }
    24.  
    25. // Explosions
    26. if (damagesource.r())
    27. {
    28. if (this.world.difficulty == EnumDifficulty.PEACEFUL)
    29. {
    30. return false; // CraftBukkit - f = 0.0f -> return false
    31. }
    32.  
    33. if (this.world.difficulty == EnumDifficulty.EASY)
    34. {
    35. f = f / 2.0F + 1.0F;
    36. }
    37.  
    38. if (this.world.difficulty == EnumDifficulty.HARD)
    39. {
    40. f = f * 3.0F / 2.0F;
    41. }
    42. }
    43.  
    44. if (false && f == 0.0F)
    45. { // CraftBukkit - Don't filter out 0 damage
    46. return false;
    47. }
    48. else
    49. {
    50. Entity entity = damagesource.getEntity();
    51.  
    52. if (entity instanceof EntityArrow && ((EntityArrow) entity).shooter != null)
    53. {
    54. entity = ((EntityArrow) entity).shooter;
    55. }
    56.  
    57. this.a(StatisticList.u, Math.round(f * 10.0F));
    58. return super.damageEntity(damagesource, f);
    59. }
    60. }
    61. }
    62. }

    EntityLiving (open)
    Code:java
    1. public boolean damageEntity(DamageSource damagesource, float f)
    2. {
    3. if (this.isInvulnerable())
    4. {
    5. return false;
    6. }
    7. else if (this.world.isStatic)
    8. {
    9. return false;
    10. }
    11. else
    12. {
    13. // I guess this is the amount of damageless ticks
    14. this.aU = 0;
    15. if (this.getHealth() <= 0.0F)
    16. {
    17. return false;
    18. }
    19. // Is it fire damage (standing in fire/lava or fire ticks)
    20. else if (damagesource.o() && this.hasEffect(MobEffectList.FIRE_RESISTANCE))
    21. {
    22. return false;
    23. }
    24. else
    25. {
    26. // Using helmets, obviously
    27. if ((damagesource == DamageSource.ANVIL || damagesource == DamageSource.FALLING_BLOCK) && this.getEquipment(4) != null)
    28. {
    29. this.getEquipment(4).damage((int) (f * 4.0F + this.random.nextFloat() * f * 2.0F), this);
    30. f *= 0.75F;
    31. }
    32.  
    33. this.aF = 1.5F;
    34. boolean flag = true;
    35.  
    36. // CraftBukkit start
    37. EntityDamageEvent event = CraftEventFactory.handleEntityDamageEvent(this, damagesource, f);
    38. if (event != null)
    39. {
    40. if (event.isCancelled())
    41. {
    42. return false;
    43. }
    44. f = (float) event.getDamage();
    45. }
    46. // CraftBukkit end
    47.  
    48. if ((float) this.noDamageTicks > (float) this.maxNoDamageTicks / 2.0F)
    49. {
    50. if (f <= this.lastDamage)
    51. {
    52. return false;
    53. }
    54.  
    55. this.d(damagesource, f - this.lastDamage);
    56. this.lastDamage = f;
    57. flag = false;
    58. }
    59. else
    60. {
    61. this.lastDamage = f;
    62. this.aw = this.getHealth();
    63. this.noDamageTicks = this.maxNoDamageTicks;
    64. this.d(damagesource, f);
    65. this.hurtTicks = this.ay = 10;
    66. }
    67.  
    68. this.az = 0.0F;
    69. Entity entity = damagesource.getEntity();
    70.  
    71. if (entity != null)
    72. {
    73. if (entity instanceof EntityLiving)
    74. {
    75. this.b((EntityLiving) entity);
    76. }
    77.  
    78. if (entity instanceof EntityHuman)
    79. {
    80. this.lastDamageByPlayerTime = 100;
    81. this.killer = (EntityHuman) entity;
    82. }
    83. else if (entity instanceof EntityWolf)
    84. {
    85. EntityWolf entitywolf = (EntityWolf) entity;
    86.  
    87. if (entitywolf.isTamed())
    88. {
    89. this.lastDamageByPlayerTime = 100;
    90. this.killer = null;
    91. }
    92. }
    93. }
    94.  
    95. if (flag)
    96. {
    97. this.world.broadcastEntityEffect(this, (byte) 2);
    98. if (damagesource != DamageSource.DROWN)
    99. {
    100. this.P();
    101. }
    102.  
    103. if (entity != null)
    104. {
    105. double d0 = entity.locX - this.locX;
    106.  
    107. double d1;
    108.  
    109. for (d1 = entity.locZ - this.locZ; d0 * d0 + d1 * d1 < 1.0E-4D; d1 = (Math.random() - Math.random()) * 0.01D)
    110. {
    111. d0 = (Math.random() - Math.random()) * 0.01D;
    112. }
    113.  
    114. this.az = (float) (Math.atan2(d1, d0) * 180.0D / 3.1415927410125732D) - this.yaw;
    115. this.a(entity, f, d0, d1);
    116. }
    117. else
    118. {
    119. this.az = (float) ((int) (Math.random() * 2.0D) * 180);
    120. }
    121. }
    122.  
    123. String s;
    124.  
    125. if (this.getHealth() <= 0.0F)
    126. {
    127. s = this.aT();
    128. if (flag && s != null)
    129. {
    130. this.makeSound(s, this.be(), this.bf());
    131. }
    132.  
    133. this.die(damagesource);
    134. }
    135. else
    136. {
    137. s = this.aS();
    138. if (flag && s != null)
    139. {
    140. this.makeSound(s, this.be(), this.bf());
    141. }
    142. }
    143.  
    144. return true;
    145. }
    146. }
    147. }
    148.  
    149. protected void d(DamageSource damagesource, float f)
    150. {
    151. if (!this.isInvulnerable())
    152. {
    153. f = this.b(damagesource, f);
    154. f = this.c(damagesource, f);
    155. float f1 = f;
    156.  
    157. // br() returns the absorption
    158. f = Math.max(f - this.br(), 0.0F);
    159. this.m(this.br() - (f1 - f));
    160. if (f != 0.0F)
    161. {
    162. float f2 = this.getHealth();
    163.  
    164. this.setHealth(f2 - f);
    165. this.aV().a(damagesource, f2, f);
    166. this.m(this.br() - f);
    167. }
    168. }
    169. }
    170.  
    171. protected float b(DamageSource damagesource, float f)
    172. {
    173. if (!damagesource.ignoresArmor())
    174. {
    175. int i = 25 - this.aU();
    176. float f1 = f * (float) i;
    177.  
    178. this.h(f);
    179. f = f1 / 25.0F;
    180. }
    181.  
    182. return f;
    183. }
    184.  
    185. public int aU()
    186. {
    187. int i = 0;
    188. ItemStack[] aitemstack = this.getEquipment();
    189. int j = aitemstack.length;
    190.  
    191. for (int k = 0; k < j; ++k)
    192. {
    193. ItemStack itemstack = aitemstack[k];
    194.  
    195. if (itemstack != null && itemstack.getItem() instanceof ItemArmor)
    196. {
    197. // TYPE | HELMET | CHESTPLATE | LEGGINGS | BOOTS
    198. // CLOTH | 1 | 3 | 2 | 1
    199. // CHAIN | 2 | 5 | 4 | 1
    200. // IRON | 2 | 6 | 5 | 2
    201. // GOLD | 2 | 5 | 3 | 1
    202. // DIAMOND | 3 | 8 | 6 | 3
    203. int l = ((ItemArmor) itemstack.getItem()).c;
    204. i += l;
    205. }
    206. }
    207. return i;
    208. }
    209.  
    210. protected float c(DamageSource damagesource, float f)
    211. {
    212. // If it is damage dealt by hunger
    213. if (damagesource.h())
    214. {
    215. return f;
    216. }
    217. else
    218. {
    219. // Like, wat?
    220. if (this instanceof EntityZombie)
    221. {
    222. f = f;
    223. }
    224.  
    225. int i;
    226. int j;
    227. float f1;
    228.  
    229. if (this.hasEffect(MobEffectList.RESISTANCE) && damagesource != DamageSource.OUT_OF_WORLD)
    230. {
    231. i = (this.getEffect(MobEffectList.RESISTANCE).getAmplifier() + 1) * 5;
    232. j = 25 - i;
    233. f1 = f * (float) j;
    234. f = f1 / 25.0F;
    235. }
    236.  
    237. if (f <= 0.0F)
    238. {
    239. return 0.0F;
    240. }
    241. else
    242. {
    243. // This is where it gets random (literally)
    244. i = EnchantmentManager.a(this.getEquipment(), damagesource);
    245. if (i > 20) {
    246. i = 20;
    247. }
    248.  
    249. if (i > 0 && i <= 20) {
    250. j = 25 - i;
    251. f1 = f * (float) j;
    252. f = f1 / 25.0F;
    253. }
    254.  
    255. return f;
    256. }
    257. }
    258. }


    EnchantmentManager (open)
    Code:java
    1.  
    2. public static int a(ItemStack[] paramArrayOfItemStack, DamageSource paramDamageSource)
    3. {
    4. EnchantmentModifierProtection b = new EnchantmentModifierProtection(null);
    5. b.a = 0; // the int returned
    6. b.b = paramDamageSource; // the damage source
    7.  
    8. // For each ItemStack, calculate the modifiers found in
    9. // the Enchantment classes using a(level, damage source)
    10. // and add them to b.a
    11. a(b, paramArrayOfItemStack);
    12. if (b.a > 25)
    13. {
    14. b.a = 25;
    15. }
    16. return (b.a + 1 >> 1) + random.nextInt((b.a >> 1) + 1);
    17. }

    [edit] Added some sample code for the custom Random
     
  18. Offline

    BungeeTheCookie

    fireblast709
    Thank you! But... could you show me how to put it into like, an if statement. Or how to actually utilize these methods? Do you paste it in?
     
  19. Offline

    fireblast709

    BungeeTheCookie It was merely a paste showing the whole code. As I mentioned, it is not actually possible to utilize it without changing at least some NMS behaviour. Unless, of course, you are fine with that.
     
  20. Offline

    BungeeTheCookie

    Oh.. Is there any other way...?
     
  21. Offline

    fireblast709

    Not that I know of, due to the use of randoms
     
  22. Offline

    mythbusterma

    You can make educated guesses about the damage, but I doubt it would ever be 100 percent accurate, however like I said before, if you're just trying to make the player invincible just cancel all the damage events that apply to them, regardless of whether or not they would be been fatal.
     
  23. Offline

    BungeeTheCookie

    I am not. I just want to make them not die. I am making a minigame plugin, my point is to not make them invincible.
    fireblast709 Ok, thanks anyways!
     
  24. Offline

    mythbusterma

    Well I mean it's simple enough to adjust for Armor, the effects of which are well documented. And most potions too, so take a guess at the damage and if you think it could kill them cancel it. You'll get some false positives but not too many if you adjust for potions and Armor.
     
  25. Offline

    BungeeTheCookie

    Well 2 seconds later, I went to some random thread and I think I found a solution.
    Code:
    public int absoluteHealth(Player player, int damage, boolean ignoreArmor) {
            int health = (int)player.getHealth();
            CraftPlayer cp = (CraftPlayer)player;
            EntityPlayer ep = cp.getHandle();
            if((ep.noDamageTicks > ep.maxNoDamageTicks / 2.0F) && (damage <= ep.lastDamage)) {
                return health;
            }
            int aS = 0;
            boolean invulnerable = false;
            try {
                java.lang.reflect.Field faS = EntityLiving.class.getDeclaredField("aS");
                java.lang.reflect.Field fI = EntityLiving.class.getDeclaredField("invulnerable");
                faS.setAccessible(true);
                fI.setAccessible(true);
                if(faS != null) {
                    aS = faS.getInt(ep);
                }
                invulnerable = fI.getBoolean(ep);
            }
            catch(Exception e) {
                e.printStackTrace();
            }
            if(invulnerable) {
                return health;
            }
            if (!ignoreArmor) {
                int j = 25 - ep.aU();
                int k = damage * j + aS;
                damage = k / 25;
                aS = k % 25;
            }
            if(ep.hasEffect(MobEffectList.RESISTANCE)) {
                int j = (ep.getEffect(MobEffectList.RESISTANCE).getAmplifier() + 1) * 5;
                int k = 25 - j;
                int l = damage * k + aS;
                damage = l / 25;
            }
            return health -= damage;
        }
     
  26. Offline

    fireblast709

    BungeeTheCookie Just be wary this that code will have different random values than the actual damage dealt
     
  27. Offline

    BungeeTheCookie

    Ok. It is accurate enough for me! Thanks for your help!!!!!!
     
  28. Offline

    CoderMusgrove

    My apologies, that part just flew right over my head.
     
Thread Status:
Not open for further replies.

Share This Page