Fix DamageSource API

Uses the correct entity in the EntityDamageByEntity event
Returns the correct entity for API's DamageSource#getCausingEntity
This commit is contained in:
Jake Potrebic 2024-03-09 14:13:04 -08:00
parent a87a5e10d9
commit d42ef390ea
12 changed files with 36 additions and 50 deletions

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/world/damagesource/DamageSource.java --- a/net/minecraft/world/damagesource/DamageSource.java
+++ b/net/minecraft/world/damagesource/DamageSource.java +++ b/net/minecraft/world/damagesource/DamageSource.java
@@ -21,7 +21,120 @@ @@ -21,7 +21,106 @@
private final Entity directEntity; private final Entity directEntity;
@Nullable @Nullable
private final Vec3 damageSourcePosition; private final Vec3 damageSourcePosition;
@ -12,8 +12,8 @@
+ private boolean sweep = false; + private boolean sweep = false;
+ private boolean melting = false; + private boolean melting = false;
+ private boolean poison = false; + private boolean poison = false;
+ private Entity customEntityDamager = null; // This field is a helper for when direct entity damage is not set by vanilla + @Nullable
+ private Entity customCausingEntityDamager = null; // This field is a helper for when causing entity damage is not set by vanilla + 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() { + public DamageSource sweep() {
+ this.sweep = true; + this.sweep = true;
@ -42,33 +42,19 @@
+ return this.poison; + return this.poison;
+ } + }
+ +
+ public Entity getDamager() { + // Paper start - fix DamageSource API
+ return (this.customEntityDamager != null) ? this.customEntityDamager : this.directEntity; + @Nullable
+ public Entity getCustomEventDamager() {
+ return (this.customEventDamager != null) ? this.customEventDamager : this.directEntity;
+ } + }
+ +
+ public Entity getCausingDamager() { + public DamageSource customEventDamager(Entity entity) {
+ return (this.customCausingEntityDamager != null) ? this.customCausingEntityDamager : this.causingEntity; + if (this.directEntity != null) {
+ } + throw new IllegalStateException("Cannot set custom event damager when direct entity is already set (report a bug to Paper)");
+
+ public DamageSource customEntityDamager(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.customEntityDamager != null || this.directEntity == entity || this.causingEntity == entity) {
+ return this;
+ } + }
+ DamageSource damageSource = this.cloneInstance(); + DamageSource damageSource = this.cloneInstance();
+ damageSource.customEntityDamager = entity; + damageSource.customEventDamager = entity;
+ return damageSource; + // Paper end - fix DamageSource API
+ }
+
+ public DamageSource customCausingEntityDamager(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.customCausingEntityDamager != null || this.directEntity == entity || this.causingEntity == entity) {
+ return this;
+ }
+ DamageSource damageSource = this.cloneInstance();
+ damageSource.customCausingEntityDamager = entity;
+ return damageSource; + return damageSource;
+ } + }
+ +
@ -121,7 +107,7 @@
public String toString() { public String toString() {
return "DamageSource (" + this.type().msgId() + ")"; return "DamageSource (" + this.type().msgId() + ")";
} }
@@ -163,4 +276,18 @@ @@ -163,4 +262,18 @@
public Holder<DamageType> typeHolder() { public Holder<DamageType> typeHolder() {
return this.type; return this.type;
} }

View file

@ -16,10 +16,11 @@
this.inFire = this.source(DamageTypes.IN_FIRE); this.inFire = this.source(DamageTypes.IN_FIRE);
this.campfire = this.source(DamageTypes.CAMPFIRE); this.campfire = this.source(DamageTypes.CAMPFIRE);
this.lightningBolt = this.source(DamageTypes.LIGHTNING_BOLT); this.lightningBolt = this.source(DamageTypes.LIGHTNING_BOLT);
@@ -84,6 +90,16 @@ @@ -83,7 +89,17 @@
private DamageSource source(ResourceKey<DamageType> key, @Nullable Entity source, @Nullable Entity attacker) { private DamageSource source(ResourceKey<DamageType> key, @Nullable Entity source, @Nullable Entity attacker) {
return new DamageSource(this.damageTypes.getOrThrow(key), source, attacker); return new DamageSource(this.damageTypes.getOrThrow(key), source, attacker);
} + }
+ +
+ // CraftBukkit start + // CraftBukkit start
+ public DamageSource melting() { + public DamageSource melting() {
@ -28,27 +29,21 @@
+ +
+ public DamageSource poison() { + public DamageSource poison() {
+ return this.poison; + return this.poison;
+ } }
+ // CraftBukkit end + // CraftBukkit end
public DamageSource inFire() { public DamageSource inFire() {
return this.inFire; return this.inFire;
@@ -254,17 +270,29 @@ @@ -254,7 +270,7 @@
} }
public DamageSource explosion(@Nullable Entity source, @Nullable Entity attacker) { public DamageSource explosion(@Nullable Entity source, @Nullable Entity attacker) {
- return this.source(attacker != null && source != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION, source, attacker); - return this.source(attacker != null && source != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION, source, attacker);
+ // CraftBukkit start + return this.source(attacker != null && source != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION, source, attacker); // Paper - revert to vanilla
+ return this.explosion(source, attacker, attacker != null && source != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION);
} }
+ public DamageSource explosion(@Nullable Entity entity, @Nullable Entity entity1, ResourceKey<DamageType> resourceKey) {
+ return this.source(resourceKey, entity, entity1);
+ // CraftBukkit end
+ }
+
public DamageSource sonicBoom(Entity attacker) { public DamageSource sonicBoom(Entity attacker) {
return this.source(DamageTypes.SONIC_BOOM, attacker); @@ -262,9 +278,15 @@
} }
public DamageSource badRespawnPointExplosion(Vec3 position) { public DamageSource badRespawnPointExplosion(Vec3 position) {

View file

@ -1391,7 +1391,7 @@
+ return; + return;
+ } + }
+ +
+ if (!this.hurtServer(world, this.damageSources().lightningBolt().customEntityDamager(lightning), 5.0F)) { + if (!this.hurtServer(world, this.damageSources().lightningBolt().customEventDamager(lightning), 5.0F)) { // Paper - fix DamageSource API
+ return; + return;
+ } + }
+ // CraftBukkit end + // CraftBukkit end

View file

@ -15,7 +15,7 @@
@Override @Override
public void thunderHit(ServerLevel world, LightningBolt lightning) { public void thunderHit(ServerLevel world, LightningBolt lightning) {
- this.hurtServer(world, this.damageSources().lightningBolt(), Float.MAX_VALUE); - this.hurtServer(world, this.damageSources().lightningBolt(), Float.MAX_VALUE);
+ this.hurtServer(world, this.damageSources().lightningBolt().customEntityDamager(lightning), Float.MAX_VALUE); // CraftBukkit + this.hurtServer(world, this.damageSources().lightningBolt().customEventDamager(lightning), Float.MAX_VALUE); // CraftBukkit // Paper - fix DamageSource API
} }
@Override @Override

View file

@ -72,7 +72,7 @@
} else { } else {
if (!this.isRemoved()) { if (!this.isRemoved()) {
+ // CraftBukkit start - fire break events + // CraftBukkit start - fire break events
+ Entity damager = (source.isDirect()) ? source.getDirectEntity() : source.getEntity(); + Entity damager = (!source.isDirect() && source.getEntity() != null) ? source.getEntity() : source.getDirectEntity(); // Paper - fix DamageSource API
+ HangingBreakEvent event; + HangingBreakEvent event;
+ if (damager != null) { + if (damager != null) {
+ event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY); + event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY);

View file

@ -73,7 +73,7 @@
+ // CraftBukkit end + // CraftBukkit end
this.dead = true; this.dead = true;
- worldserver.explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionRadius * f, Level.ExplosionInteraction.MOB); - worldserver.explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionRadius * f, Level.ExplosionInteraction.MOB);
+ worldserver.explode(this, net.minecraft.world.level.Explosion.getDefaultDamageSource(this.level(), this).customCausingEntityDamager(this.entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit + worldserver.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
this.spawnLingeringCloud(); this.spawnLingeringCloud();
this.triggerOnDeathMobEffects(worldserver, Entity.RemovalReason.KILLED); this.triggerOnDeathMobEffects(worldserver, Entity.RemovalReason.KILLED);
- this.discard(); - this.discard();

View file

@ -24,7 +24,7 @@
if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) { if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) {
if (entityliving1 == null) { if (entityliving1 == null) {
- target.hurt(this.damageSources().magic(), 6.0F); - target.hurt(this.damageSources().magic(), 6.0F);
+ target.hurt(this.damageSources().magic().customEntityDamager(this), 6.0F); // CraftBukkit + target.hurt(this.damageSources().magic().customEventDamager(this), 6.0F); // CraftBukkit // Paper - fix DamageSource API
} else { } else {
if (entityliving1.isAlliedTo((Entity) target)) { if (entityliving1.isAlliedTo((Entity) target)) {
return; return;

View file

@ -48,7 +48,7 @@
entityplayer1.resetFallDistance(); entityplayer1.resetFallDistance();
entityplayer1.resetCurrentImpulseContext(); entityplayer1.resetCurrentImpulseContext();
- entityplayer1.hurtServer(entityplayer.serverLevel(), this.damageSources().enderPearl(), 5.0F); - entityplayer1.hurtServer(entityplayer.serverLevel(), this.damageSources().enderPearl(), 5.0F);
+ entityplayer1.hurtServer(entityplayer.serverLevel(), this.damageSources().enderPearl().customEntityDamager(this), 5.0F); // CraftBukkit + entityplayer1.hurtServer(entityplayer.serverLevel(), this.damageSources().enderPearl().customEventDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API
} }
this.playSound(worldserver, vec3d); this.playSound(worldserver, vec3d);

View file

@ -21,7 +21,7 @@
} }
} else { } else {
- flag = entity.hurtServer(worldserver, this.damageSources().magic(), 5.0F); - flag = entity.hurtServer(worldserver, this.damageSources().magic(), 5.0F);
+ flag = entity.hurtServer(worldserver, this.damageSources().magic().customCausingEntity(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls + flag = entity.hurtServer(worldserver, this.damageSources().magic().customEventDamager(this), 5.0F); // Paper - Fire EntityDamageByEntityEvent for unowned wither skulls // Paper - fix DamageSource API
} }
if (flag && entity instanceof LivingEntity entityliving) { if (flag && entity instanceof LivingEntity entityliving) {

View file

@ -41,13 +41,13 @@ public class CraftDamageSource implements DamageSource {
@Override @Override
public org.bukkit.entity.Entity getCausingEntity() { public org.bukkit.entity.Entity getCausingEntity() {
net.minecraft.world.entity.Entity entity = this.getHandle().getCausingDamager(); net.minecraft.world.entity.Entity entity = this.getHandle().getEntity(); // Paper - fix DamageSource API - revert to vanilla
return (entity != null) ? entity.getBukkitEntity() : null; return (entity != null) ? entity.getBukkitEntity() : null;
} }
@Override @Override
public org.bukkit.entity.Entity getDirectEntity() { public org.bukkit.entity.Entity getDirectEntity() {
net.minecraft.world.entity.Entity entity = this.getHandle().getDamager(); net.minecraft.world.entity.Entity entity = this.getHandle().getDirectEntity(); // Paper - fix DamageSource API
return (entity != null) ? entity.getBukkitEntity() : null; return (entity != null) ? entity.getBukkitEntity() : null;
} }
@ -65,7 +65,7 @@ public class CraftDamageSource implements DamageSource {
@Override @Override
public boolean isIndirect() { public boolean isIndirect() {
return this.getHandle().getCausingDamager() != this.getHandle().getDamager(); return !this.getHandle().isDirect(); // Paper - fix DamageSource API
} }
@Override @Override

View file

@ -41,6 +41,11 @@ public class CraftDamageSourceBuilder implements DamageSource.Builder {
@Override @Override
public DamageSource build() { 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); return CraftDamageSource.buildFromBukkit(this.damageType, this.causingEntity, this.directEntity, this.damageLocation);
} }
} }

View file

@ -1092,7 +1092,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) { 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); CraftDamageSource bukkitDamageSource = new CraftDamageSource(source);
Entity damager = (source.getDamager() != null) ? source.getDamager() : source.getEntity(); final Entity damager = source.getCustomEventDamager(); // Paper - fix DamageSource API
if (source.is(DamageTypeTags.IS_EXPLOSION)) { if (source.is(DamageTypeTags.IS_EXPLOSION)) {
if (damager == null) { if (damager == null) {
return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), source.getDirectBlockState(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled); return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), source.getDirectBlockState(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled);