From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dodison <kacpik@mapik.eu>
Date: Mon, 26 Jul 2021 17:32:36 +0200
Subject: [PATCH] Add critical damage API


diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
index 80d19af2ad423bd3de0e039c5bb8f97af536aaa9..a828cad27fcd39f8bfbaefa97052a2a3b6650ee7 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -64,6 +64,19 @@ public class DamageSource {
         return this;
     }
     // CraftBukkit end
+    // Paper start - add critical damage API
+    private boolean critical;
+    public boolean isCritical() {
+        return this.critical;
+    }
+    public DamageSource critical() {
+        return this.critical(true);
+    }
+    public DamageSource critical(boolean critical) {
+        this.critical = critical;
+        return this;
+    }
+    // Paper end
 
     public static DamageSource sting(LivingEntity attacker) {
         return new EntityDamageSource("sting", attacker);
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index 909f5c26ca149687c03688c33c241e549f19a3e9..8c74787c81d2b72a8b1c9dfff0a9db38ab13c973 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -1230,7 +1230,7 @@ public abstract class Player extends LivingEntity {
                         flag1 = true;
                     }
 
-                    boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity;
+                    boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; // Paper - Add critical damage API - conflict on change
 
                     flag2 = flag2 && !level.paperConfig.disablePlayerCrits; // Paper
                     flag2 = flag2 && !this.isSprinting();
@@ -1270,7 +1270,7 @@ public abstract class Player extends LivingEntity {
                     }
 
                     Vec3 vec3d = target.getDeltaMovement();
-                    boolean flag5 = target.hurt(DamageSource.playerAttack(this), f);
+                    boolean flag5 = target.hurt(DamageSource.playerAttack(this).critical(flag2), f); // Paper - add critical damage API
 
                     if (flag5) {
                         if (i > 0) {
@@ -1298,7 +1298,7 @@ public abstract class Player extends LivingEntity {
 
                                 if (entityliving != this && entityliving != target && !this.isAlliedTo((Entity) entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) {
                                     // CraftBukkit start - Only apply knockback if the damage hits
-                                    if (entityliving.hurt(DamageSource.playerAttack(this).sweep(), f4)) {
+                                    if (entityliving.hurt(DamageSource.playerAttack(this).sweep().critical(flag2), f4)) { // Paper - add critical damage API
                                     entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this); // Paper
                                     }
                                     // CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
index b436103957113bff5e553dacb869c775a3f8b059..3d3dcb47720055f550d17d1f106a2c0e59de2919 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
@@ -381,6 +381,7 @@ public abstract class AbstractArrow extends Projectile {
             }
         }
 
+        if (this.isCritArrow()) damagesource = damagesource.critical(); // Paper - add critical damage API
         boolean flag = entity.getType() == EntityType.ENDERMAN;
         int k = entity.getRemainingFireTicks();
 
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 5c2beec59b0382d80bf97317cbbeab43df24ad55..a3c8a0291fa9ae6f3c96d937dd4621edd7c48535 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -980,7 +980,7 @@ public class CraftEventFactory {
                 } else {
                     damageCause = DamageCause.ENTITY_EXPLOSION;
                 }
-                event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), entity.getBukkitEntity(), damageCause, modifiers, modifierFunctions);
+                event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), entity.getBukkitEntity(), damageCause, modifiers, modifierFunctions, source.isCritical()); // Paper - add critical damage API
             }
             event.setCancelled(cancelled);
 
@@ -1007,7 +1007,7 @@ public class CraftEventFactory {
                 cause = DamageCause.THORNS;
             }
 
-            return CraftEventFactory.callEntityDamageEvent(damager, entity, cause, modifiers, modifierFunctions, cancelled);
+            return CraftEventFactory.callEntityDamageEvent(damager, entity, cause, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API
         } else if (source == DamageSource.OUT_OF_WORLD) {
             EntityDamageEvent event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.VOID, modifiers, modifierFunctions);
             event.setCancelled(cancelled);
@@ -1077,7 +1077,7 @@ public class CraftEventFactory {
             } else {
                 throw new IllegalStateException(String.format("Unhandled damage of %s by %s from %s", entity, damager.getHandle(), source.msgId));
             }
-            EntityDamageEvent event = new EntityDamageByEntityEvent(damager, entity.getBukkitEntity(), cause, modifiers, modifierFunctions);
+            EntityDamageEvent event = new EntityDamageByEntityEvent(damager, entity.getBukkitEntity(), cause, modifiers, modifierFunctions, source.isCritical()); // Paper - add critical damage API
             event.setCancelled(cancelled);
             CraftEventFactory.callEvent(event);
             if (!event.isCancelled()) {
@@ -1122,20 +1122,28 @@ public class CraftEventFactory {
         }
 
         if (cause != null) {
-            return CraftEventFactory.callEntityDamageEvent(null, entity, cause, modifiers, modifierFunctions, cancelled);
+            return CraftEventFactory.callEntityDamageEvent(null, entity, cause, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API
         }
 
         throw new IllegalStateException(String.format("Unhandled damage of %s from %s", entity, source.msgId));
     }
 
+    @Deprecated // Paper - Add critical damage API
     private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions) {
         return CraftEventFactory.callEntityDamageEvent(damager, damagee, cause, modifiers, modifierFunctions, false);
     }
 
+    // Paper start - Add critical damage API
+    @Deprecated
     private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled) {
+        return CraftEventFactory.callEntityDamageEvent(damager, damagee, cause, modifiers, modifierFunctions, false, false);
+    }
+
+    private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled, boolean critical) {
+        // Paper end
         EntityDamageEvent event;
         if (damager != null) {
-            event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, modifiers, modifierFunctions);
+            event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, modifiers, modifierFunctions, critical); // Paper - add critical damage API
         } else {
             event = new EntityDamageEvent(damagee.getBukkitEntity(), cause, modifiers, modifierFunctions);
         }
