--- a/net/minecraft/world/damagesource/DamageSource.java +++ b/net/minecraft/world/damagesource/DamageSource.java @@ -20,6 +_,105 @@ private final Entity directEntity; @Nullable private final Vec3 damageSourcePosition; + // CraftBukkit start + @Nullable + private org.bukkit.block.Block directBlock; // The block that caused the damage. damageSourcePosition is not used for all block damages + @Nullable + private org.bukkit.block.BlockState directBlockState; // The block state of the block relevant to this damage source + private boolean sweep = false; + private boolean melting = false; + private boolean poison = false; + @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.sweep = true; + return this; + } + + public boolean isSweep() { + return this.sweep; + } + + public DamageSource melting() { + this.melting = true; + return this; + } + + public boolean isMelting() { + return this.melting; + } + + public DamageSource poison() { + this.poison = true; + return this; + } + + public boolean isPoison() { + return this.poison; + } + + // Paper start - fix DamageSource API + @Nullable + public Entity getCustomEventDamager() { + return (this.customEventDamager != null) ? this.customEventDamager : this.directEntity; + } + + 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.customEventDamager = entity; + // Paper end - fix DamageSource API + return damageSource; + } + + public org.bukkit.block.Block getDirectBlock() { + return this.directBlock; + } + + public DamageSource directBlock(net.minecraft.world.level.Level world, net.minecraft.core.BlockPos blockPosition) { + if (blockPosition == null || world == null) { + return this; + } + return this.directBlock(org.bukkit.craftbukkit.block.CraftBlock.at(world, blockPosition)); + } + + public DamageSource directBlock(org.bukkit.block.Block block) { + if (block == null) { + return this; + } + // Cloning the instance lets us return unique instances of DamageSource without affecting constants defined in DamageSources + DamageSource damageSource = this.cloneInstance(); + damageSource.directBlock = block; + return damageSource; + } + + public org.bukkit.block.BlockState getDirectBlockState() { + return this.directBlockState; + } + + public DamageSource directBlockState(org.bukkit.block.BlockState blockState) { + if (blockState == null) { + return this; + } + // Cloning the instance lets us return unique instances of DamageSource without affecting constants defined in DamageSources + DamageSource damageSource = this.cloneInstance(); + damageSource.directBlockState = blockState; + return damageSource; + } + + private DamageSource cloneInstance() { + DamageSource damageSource = new DamageSource(this.type, this.directEntity, this.causingEntity, this.damageSourcePosition); + damageSource.directBlock = this.getDirectBlock(); + damageSource.directBlockState = this.getDirectBlockState(); + damageSource.sweep = this.isSweep(); + damageSource.poison = this.isPoison(); + damageSource.melting = this.isMelting(); + return damageSource; + } + // CraftBukkit end @Override public String toString() { @@ -134,4 +_,18 @@ public Holder typeHolder() { return this.type; } + + // 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 - add critical damage API }