From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 9 Mar 2024 14:13:04 -0800
Subject: [PATCH] Fix DamageSource API

Uses the correct entity in the EntityDamageByEntity event
Returns the correct entity for API's DamageSource#getCausingEntity

diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
index ffb7c966617bdfa2c3f05ec4e753e32996493343..359a2f0492a9b938a4f015c546e100e0092ae1d4 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -29,7 +29,8 @@ public class DamageSource {
     private boolean withSweep = false;
     private boolean melting = false;
     private boolean poison = false;
-    private Entity customCausingEntity = null; // This field is a helper for when causing entity damage is not set by vanilla
+    @Nullable
+    private Entity customEventDamager = null; // This field is a helper for when causing entity damage is not set by vanilla // Paper - fix DamageSource API
 
     public DamageSource sweep() {
         this.withSweep = true;
@@ -58,18 +59,18 @@ public class DamageSource {
         return this.poison;
     }
 
-    public Entity getCausingEntity() {
-        return (this.customCausingEntity != null) ? this.customCausingEntity : this.causingEntity;
+    // Paper start - fix DamageSource API
+    public @Nullable Entity getCustomEventDamager() {
+        return (this.customEventDamager != null) ? this.customEventDamager : this.directEntity;
     }
 
-    public DamageSource customCausingEntity(Entity entity) {
-        // This method is not intended for change the causing entity if is already set
-        // also is only necessary if the entity passed is not the direct entity or different from the current causingEntity
-        if (this.customCausingEntity != null || this.directEntity == entity || this.causingEntity == entity) {
-            return this;
+    public DamageSource customEventDamager(Entity entity) {
+        if (this.directEntity != null) {
+            throw new IllegalStateException("Cannot set custom event damager when direct entity is already set (report a bug to Paper)");
         }
         DamageSource damageSource = this.cloneInstance();
-        damageSource.customCausingEntity = entity;
+        damageSource.customEventDamager = entity;
+        // Paper end - fix DamageSource API
         return damageSource;
     }
 
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 4e96b6c05bf8b8235e91bdd26e5615c5299fd9aa..3c1bcf8d1a07b35a8688160c9f05f792451338a3 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3195,7 +3195,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
             return;
         }
 
-        if (!this.hurt(this.damageSources().lightningBolt().customCausingEntity(lightning), 5.0F)) {
+        if (!this.hurt(this.damageSources().lightningBolt().customEventDamager(lightning), 5.0F)) { // Paper - fix DamageSource API
             return;
         }
         // CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
index 3eabf1e94c0a1086f471e30bf523581907169c58..ffffa53fcaa6ec8681b283fa20bb5a3320ad9c11 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
@@ -334,7 +334,7 @@ public class Turtle extends Animal {
 
     @Override
     public void thunderHit(ServerLevel world, LightningBolt lightning) {
-        this.hurt(this.damageSources().lightningBolt().customCausingEntity(lightning), Float.MAX_VALUE); // CraftBukkit
+        this.hurt(this.damageSources().lightningBolt().customEventDamager(lightning), Float.MAX_VALUE); // CraftBukkit // Paper - fix DamageSource API
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
index 0ffff5329fa2c7833f9ec71528cb7f951cf78109..bf2d91bbb4bf401696f5f5d14a67e3920a179084 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java
@@ -203,7 +203,7 @@ public abstract class HangingEntity extends Entity {
         } else {
             if (!this.isRemoved() && !this.level().isClientSide) {
                 // CraftBukkit start - fire break events
-                Entity damager = (source.isIndirect()) ? source.getEntity() : source.getDirectEntity();
+                Entity damager = (source.isIndirect() && source.getEntity() != null) ? source.getEntity() : source.getDirectEntity(); // Paper - fix DamageSource API
                 HangingBreakEvent event;
                 if (damager != null) {
                     event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY);
diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
index 4b94e21d05d6deae75f0c2fb711e43a4c7d06f90..cbcb2bfa8f91099e5c374f590f48885390bdf7a7 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
@@ -271,7 +271,7 @@ public class Creeper extends Monster implements PowerableMob {
             if (!event.isCancelled()) {
             // CraftBukkit end
             this.dead = true;
-            this.level().explode(this, net.minecraft.world.level.Explosion.getDefaultDamageSource(this.level(), this).customCausingEntity(this.entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit
+            this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API
             this.discard(EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
             this.spawnLingeringCloud();
             // CraftBukkit start
diff --git a/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java b/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java
index eb764829bde34a835a151934267bfcf36d5239fa..f8aa723f18e28b02d4b7055404922ff8d7a73f8d 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java
@@ -133,7 +133,7 @@ public class EvokerFangs extends Entity implements TraceableEntity {
 
         if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) {
             if (entityliving1 == null) {
-                target.hurt(this.damageSources().magic().customCausingEntity(this), 6.0F); // CraftBukkit
+                target.hurt(this.damageSources().magic().customEventDamager(this), 6.0F); // CraftBukkit // Paper - fix DamageSource API
             } else {
                 if (entityliving1.isAlliedTo((Entity) target)) {
                     return;
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
index 28690877c443ceb2bdf20e6d251c9d32f667814c..1fb1e729d6879568d8b4943071fa940325b2e5b0 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
@@ -86,7 +86,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
 
                         entityplayer.connection.teleport(teleEvent.getTo());
                         entity.resetFallDistance();
-                        entity.hurt(this.damageSources().fall().customCausingEntity(this), 5.0F); // CraftBukkit
+                        entity.hurt(this.damageSources().fall().customEventDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API
                     }
                     // CraftBukkit end
                     this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS);
diff --git a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
index 02931861de955352e71d6f5ffc720a17304815fe..55b4b5ad5f084c9a271a716d076672478d6486ba 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
@@ -72,7 +72,7 @@ public class WitherSkull extends AbstractHurtingProjectile {
                     }
                 }
             } else {
-                flag = entity.hurt(this.damageSources().magic().customCausingEntity(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls
+                flag = entity.hurt(this.damageSources().magic().customEventDamager(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls // Paper - fix DamageSource API
             }
 
             if (flag && entity instanceof LivingEntity) {
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index 414297ab9e953049b5f0b091e54d37c6e9edf861..2f9be855815d8db0098f969c2d1bd0c3c25f0892 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -104,7 +104,7 @@ public class Explosion {
         this.z = z;
         this.fire = createFire;
         this.blockInteraction = destructionType;
-        this.damageSource = damageSource == null ? world.damageSources().explosion(this).customCausingEntity(entity) : damageSource.customCausingEntity(entity); // CraftBukkit - handle source entity
+        this.damageSource = damageSource == null ? world.damageSources().explosion(this) : damageSource; // CraftBukkit - handle source entity // Paper - revert to fix DamageSource API
         this.damageCalculator = behavior == null ? this.makeDamageCalculator(entity) : behavior;
         this.smallExplosionParticles = particle;
         this.largeExplosionParticles = emitterParticle;
diff --git a/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java b/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java
index 6ae1ad21807c039726021f8f26f92042acce2fda..b7e2327c50195e8d3ca3ca3b47c7c0f9ea8e289c 100644
--- a/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java
+++ b/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java
@@ -41,7 +41,7 @@ public class CraftDamageSource implements DamageSource {
 
     @Override
     public org.bukkit.entity.Entity getCausingEntity() {
-        net.minecraft.world.entity.Entity entity = this.getHandle().getCausingEntity();
+        net.minecraft.world.entity.Entity entity = this.getHandle().getEntity(); // Paper - fix DamageSource API
         return (entity != null) ? entity.getBukkitEntity() : null;
     }
 
@@ -65,7 +65,7 @@ public class CraftDamageSource implements DamageSource {
 
     @Override
     public boolean isIndirect() {
-        return this.getHandle().getCausingEntity() != this.getHandle().getDirectEntity();
+        return this.getHandle().isIndirect(); // Paper - fix DamageSource API
     }
 
     @Override
diff --git a/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSourceBuilder.java b/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSourceBuilder.java
index 4c6e15535fa40aad8cf1920f392589404f9ba79c..35eb95ef6fb6a0f7ea63351e90741c489fdd15f9 100644
--- a/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSourceBuilder.java
+++ b/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSourceBuilder.java
@@ -41,6 +41,11 @@ public class CraftDamageSourceBuilder implements DamageSource.Builder {
 
     @Override
     public DamageSource build() {
+        // Paper start - fix DamageCause API
+        if (this.causingEntity != null && this.directEntity == null) {
+            throw new IllegalArgumentException("Direct entity must be set if causing entity is set");
+        }
+        // Paper end - fix DamageCause API
         return CraftDamageSource.buildFromBukkit(this.damageType, this.causingEntity, this.directEntity, this.damageLocation);
     }
 }
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 31bc4a0408da3bf3b0d8eb56b045e9742a898a39..92a9643a31d3b753c997854a0db0ceabe883fd29 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1082,7 +1082,7 @@ public class CraftEventFactory {
 
     private static EntityDamageEvent handleEntityDamageEvent(Entity entity, DamageSource source, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions, boolean cancelled) {
         CraftDamageSource bukkitDamageSource = new CraftDamageSource(source);
-        Entity damager = (bukkitDamageSource.isIndirect() && source.getDirectEntity() != null) ? source.getDirectEntity() : source.getCausingEntity();
+        final Entity damager = source.getCustomEventDamager(); // Paper - fix DamageSource API
         if (source.is(DamageTypeTags.IS_EXPLOSION)) {
             if (damager == null) {
                 return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled, source.blockState); // Paper - Include BlockState for damage
