--- a/net/minecraft/world/damagesource/DamageSource.java +++ b/net/minecraft/world/damagesource/DamageSource.java @@ -20,6 +_,92 @@ private final Entity directEntity; @Nullable private final Vec3 damageSourcePosition; + // CraftBukkit start + @Nullable + private org.bukkit.event.entity.EntityDamageEvent.DamageCause knownCause; // When the damage event cause is known by the context of the call rather than the damage source data + @Nullable + private Entity eventEntityDamager = null; // Relevant entity set when the game doesn't normally set a causingEntity/directEntity + @Nullable + private org.bukkit.block.Block eventBlockDamager; // Relevant block set. damageSourcePosition is only used for bad respawn point explosion or custom damage + @Nullable + private org.bukkit.block.BlockState fromBlockSnapshot; // Captured block snapshot when the eventBlockDamager is not relevant (e.g. for bad respawn point explosions the block is already removed) + private boolean critical; // Supports arrows and sweeping damage + + public DamageSource knownCause(final org.bukkit.event.entity.EntityDamageEvent.DamageCause cause) { + final DamageSource damageSource = this.copy(); + damageSource.knownCause = cause; + return damageSource; + } + + @Nullable + public org.bukkit.event.entity.EntityDamageEvent.DamageCause knownCause() { + return this.knownCause; + } + + @Nullable + public Entity eventEntityDamager() { + return this.eventEntityDamager; + } + + public DamageSource eventEntityDamager(final Entity entity) { + if (this.directEntity != null) { + throw new IllegalStateException("Cannot set an event damager when a direct entity is already set (report a bug to Paper)"); + } + final DamageSource damageSource = this.copy(); + damageSource.eventEntityDamager = entity; + return damageSource; + } + + @Nullable + public org.bukkit.block.Block eventBlockDamager() { + return this.eventBlockDamager; + } + + public DamageSource eventBlockDamager(final net.minecraft.world.level.LevelAccessor level, final @Nullable net.minecraft.core.BlockPos pos) { + if (pos == null) { + return this; + } + + final DamageSource damageSource = this.copy(); + damageSource.eventBlockDamager = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); + return damageSource; + } + + @Nullable + public org.bukkit.block.BlockState causingBlockSnapshot() { + return this.fromBlockSnapshot; + } + + public DamageSource causingBlockSnapshot(final org.bukkit.block.BlockState blockState) { + if (this.eventBlockDamager != null) { + throw new IllegalStateException("Cannot set a block snapshot when an event block damager is already set (report a bug to Paper)"); + } + final DamageSource damageSource = this.copy(); + damageSource.fromBlockSnapshot = blockState; + return damageSource; + } + + public boolean isCritical() { + return this.critical; + } + + public DamageSource critical() { + final DamageSource damageSource = this.copy(); + damageSource.critical = true; + return damageSource; + } + + // Cloning the instance lets us return unique instances of DamageSource without affecting constants defined in DamageSources + private DamageSource copy() { + final DamageSource damageSource = new DamageSource(this.type, this.directEntity, this.causingEntity, this.damageSourcePosition); + damageSource.knownCause = this.knownCause; + damageSource.eventEntityDamager = this.eventEntityDamager; + damageSource.eventBlockDamager = this.eventBlockDamager; + damageSource.fromBlockSnapshot = this.fromBlockSnapshot; + damageSource.critical = this.critical; + return damageSource; + } + // CraftBukkit end @Override public String toString() {