From 066665a9790c5eede2bc39b2079e256ba1f1884c Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Sat, 4 May 2024 08:15:51 +1000 Subject: [PATCH] #1390: Improve internal handling of damage sources By: Doc --- .../world/damagesource/DamageSource.patch | 39 +++++++++++++------ .../world/damagesource/DamageSources.patch | 27 +++++++++---- .../net/minecraft/world/entity/Entity.patch | 2 +- .../world/entity/animal/EntityTurtle.patch | 2 +- .../world/entity/monster/EntityCreeper.patch | 2 +- .../entity/projectile/EntityEnderPearl.patch | 13 +++---- .../entity/projectile/EntityEvokerFangs.patch | 2 +- .../net/minecraft/world/level/Explosion.patch | 10 ++--- .../world/level/block/BlockBed.patch | 7 ++-- .../level/block/BlockRespawnAnchor.patch | 8 ++-- .../craftbukkit/damage/CraftDamageSource.java | 6 +-- .../craftbukkit/event/CraftEventFactory.java | 2 +- 12 files changed, 72 insertions(+), 48 deletions(-) diff --git a/paper-server/nms-patches/net/minecraft/world/damagesource/DamageSource.patch b/paper-server/nms-patches/net/minecraft/world/damagesource/DamageSource.patch index 11c2d5168e..391ba3af68 100644 --- a/paper-server/nms-patches/net/minecraft/world/damagesource/DamageSource.patch +++ b/paper-server/nms-patches/net/minecraft/world/damagesource/DamageSource.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/damagesource/DamageSource.java +++ b/net/minecraft/world/damagesource/DamageSource.java -@@ -21,6 +21,88 @@ +@@ -21,6 +21,103 @@ private final Entity directEntity; @Nullable private final Vec3D damageSourcePosition; @@ -8,19 +8,19 @@ + @Nullable + private org.bukkit.block.Block directBlock; // The block that caused the damage. damageSourcePosition is not used for all block damages + @Nullable -+ public org.bukkit.block.BlockState blockState; // The block state of the block relevant to this damage source -+ private boolean withSweep = false; ++ 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; -+ private Entity customCausingEntity = null; // This field is a helper for when causing entity damage is not set by vanilla ++ private Entity customEntityDamager = null; // This field is a helper for when causing entity damage is not set by vanilla + + public DamageSource sweep() { -+ this.withSweep = true; ++ this.sweep = true; + return this; + } + + public boolean isSweep() { -+ return this.withSweep; ++ return this.sweep; + } + + public DamageSource melting() { @@ -41,18 +41,18 @@ + return this.poison; + } + -+ public Entity getCausingEntity() { -+ return (this.customCausingEntity != null) ? this.customCausingEntity : this.causingEntity; ++ public Entity getDamager() { ++ return (this.customEntityDamager != null) ? this.customEntityDamager : this.directEntity; + } + -+ public DamageSource customCausingEntity(Entity entity) { ++ 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.customCausingEntity != null || this.directEntity == entity || this.causingEntity == entity) { ++ if (this.customEntityDamager != null || this.directEntity == entity || this.causingEntity == entity) { + return this; + } + DamageSource damageSource = this.cloneInstance(); -+ damageSource.customCausingEntity = entity; ++ damageSource.customEntityDamager = entity; + return damageSource; + } + @@ -77,10 +77,25 @@ + 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 = directBlockState; ++ return damageSource; ++ } ++ + private DamageSource cloneInstance() { + DamageSource damageSource = new DamageSource(this.type, this.directEntity, this.causingEntity, this.damageSourcePosition); + damageSource.directBlock = this.getDirectBlock(); -+ damageSource.withSweep = this.isSweep(); ++ damageSource.directBlockState = this.getDirectBlockState(); ++ damageSource.sweep = this.isSweep(); + damageSource.poison = this.isPoison(); + damageSource.melting = this.isMelting(); + return damageSource; diff --git a/paper-server/nms-patches/net/minecraft/world/damagesource/DamageSources.patch b/paper-server/nms-patches/net/minecraft/world/damagesource/DamageSources.patch index e8e616bd43..104e23c4ea 100644 --- a/paper-server/nms-patches/net/minecraft/world/damagesource/DamageSources.patch +++ b/paper-server/nms-patches/net/minecraft/world/damagesource/DamageSources.patch @@ -33,21 +33,32 @@ public DamageSource inFire() { return this.inFire; } -@@ -250,7 +266,17 @@ +@@ -242,7 +258,13 @@ + } + + public DamageSource explosion(@Nullable Entity entity, @Nullable Entity entity1) { +- return this.source(entity1 != null && entity != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION, entity, entity1); ++ // CraftBukkit start ++ return this.explosion(entity, entity1, entity1 != null && entity != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION); ++ } ++ ++ public DamageSource explosion(@Nullable Entity entity, @Nullable Entity entity1, ResourceKey resourceKey) { ++ return this.source(resourceKey, entity, entity1); ++ // CraftBukkit end + } + + public DamageSource sonicBoom(Entity entity) { +@@ -250,7 +272,13 @@ } public DamageSource badRespawnPointExplosion(Vec3D vec3d) { - return new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), vec3d); + // CraftBukkit start -+ return badRespawnPointExplosion(vec3d, null, null, null); ++ return badRespawnPointExplosion(vec3d, null); + } + -+ public DamageSource badRespawnPointExplosion(Vec3D vec3d, net.minecraft.world.level.World world, net.minecraft.world.level.block.state.IBlockData blockData, net.minecraft.core.BlockPosition position) { -+ DamageSource damageSource = new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), vec3d); -+ if (world != null && blockData != null && position != null) { -+ damageSource.blockState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(world, position, blockData, null); -+ } -+ return damageSource; ++ public DamageSource badRespawnPointExplosion(Vec3D vec3d, org.bukkit.block.BlockState blockState) { ++ return new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), vec3d).directBlockState(blockState); + // CraftBukkit end } diff --git a/paper-server/nms-patches/net/minecraft/world/entity/Entity.patch b/paper-server/nms-patches/net/minecraft/world/entity/Entity.patch index 54d9040f99..f09c987e3d 100644 --- a/paper-server/nms-patches/net/minecraft/world/entity/Entity.patch +++ b/paper-server/nms-patches/net/minecraft/world/entity/Entity.patch @@ -776,7 +776,7 @@ + return; + } + -+ if (!this.hurt(this.damageSources().lightningBolt().customCausingEntity(entitylightning), 5.0F)) { ++ if (!this.hurt(this.damageSources().lightningBolt().customEntityDamager(entitylightning), 5.0F)) { + return; + } + // CraftBukkit end diff --git a/paper-server/nms-patches/net/minecraft/world/entity/animal/EntityTurtle.patch b/paper-server/nms-patches/net/minecraft/world/entity/animal/EntityTurtle.patch index fb0d940077..379fe48abf 100644 --- a/paper-server/nms-patches/net/minecraft/world/entity/animal/EntityTurtle.patch +++ b/paper-server/nms-patches/net/minecraft/world/entity/animal/EntityTurtle.patch @@ -15,7 +15,7 @@ @Override public void thunderHit(WorldServer worldserver, EntityLightning entitylightning) { - this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE); -+ this.hurt(this.damageSources().lightningBolt().customCausingEntity(entitylightning), Float.MAX_VALUE); // CraftBukkit ++ this.hurt(this.damageSources().lightningBolt().customEntityDamager(entitylightning), Float.MAX_VALUE); // CraftBukkit } @Override diff --git a/paper-server/nms-patches/net/minecraft/world/entity/monster/EntityCreeper.patch b/paper-server/nms-patches/net/minecraft/world/entity/monster/EntityCreeper.patch index 98721c85ce..e8d0f71fdb 100644 --- a/paper-server/nms-patches/net/minecraft/world/entity/monster/EntityCreeper.patch +++ b/paper-server/nms-patches/net/minecraft/world/entity/monster/EntityCreeper.patch @@ -65,7 +65,7 @@ this.dead = true; - this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionRadius * f, World.a.MOB); - this.discard(); -+ 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(), World.a.MOB); // CraftBukkit ++ this.level().explode(this, this.level().damageSources().explosion(this, this.entityIgniter, net.minecraft.world.damagesource.DamageTypes.EXPLOSION), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), World.a.MOB); // CraftBukkit + this.discard(EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause this.spawnLingeringCloud(); + // CraftBukkit start diff --git a/paper-server/nms-patches/net/minecraft/world/entity/projectile/EntityEnderPearl.patch b/paper-server/nms-patches/net/minecraft/world/entity/projectile/EntityEnderPearl.patch index 2011a8d422..e67aa1b758 100644 --- a/paper-server/nms-patches/net/minecraft/world/entity/projectile/EntityEnderPearl.patch +++ b/paper-server/nms-patches/net/minecraft/world/entity/projectile/EntityEnderPearl.patch @@ -1,12 +1,11 @@ --- a/net/minecraft/world/entity/projectile/EntityEnderPearl.java +++ b/net/minecraft/world/entity/projectile/EntityEnderPearl.java -@@ -18,6 +18,14 @@ +@@ -18,6 +18,13 @@ import net.minecraft.world.phys.MovingObjectPosition; import net.minecraft.world.phys.MovingObjectPositionEntity; +// CraftBukkit start +import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.event.CraftEventFactory; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityRemoveEvent; +import org.bukkit.event.player.PlayerTeleportEvent; @@ -15,7 +14,7 @@ public class EntityEnderPearl extends EntityProjectileThrowable { public EntityEnderPearl(EntityTypes entitytypes, World world) { -@@ -54,23 +62,34 @@ +@@ -54,23 +61,34 @@ EntityPlayer entityplayer = (EntityPlayer) entity; if (entityplayer.connection.isAcceptingMessages() && entityplayer.level() == this.level() && !entityplayer.isSleeping()) { @@ -57,13 +56,13 @@ - entity.hurt(this.damageSources().fall(), 5.0F); + entityplayer.connection.teleport(teleEvent.getTo()); + entity.resetFallDistance(); -+ entity.hurt(this.damageSources().fall().customCausingEntity(this), 5.0F); // CraftBukkit ++ entity.hurt(this.damageSources().fall().customEntityDamager(this), 5.0F); // CraftBukkit + } + // CraftBukkit end this.level().playSound((EntityHuman) null, this.getX(), this.getY(), this.getZ(), SoundEffects.PLAYER_TELEPORT, SoundCategory.PLAYERS); } } else if (entity != null) { -@@ -78,7 +97,7 @@ +@@ -78,7 +96,7 @@ entity.resetFallDistance(); } @@ -72,7 +71,7 @@ } } -@@ -88,7 +107,7 @@ +@@ -88,7 +106,7 @@ Entity entity = this.getOwner(); if (entity instanceof EntityPlayer && !entity.isAlive() && this.level().getGameRules().getBoolean(GameRules.RULE_ENDER_PEARLS_VANISH_ON_DEATH)) { @@ -81,7 +80,7 @@ } else { super.tick(); } -@@ -100,7 +119,7 @@ +@@ -100,7 +118,7 @@ public Entity changeDimension(WorldServer worldserver) { Entity entity = this.getOwner(); diff --git a/paper-server/nms-patches/net/minecraft/world/entity/projectile/EntityEvokerFangs.patch b/paper-server/nms-patches/net/minecraft/world/entity/projectile/EntityEvokerFangs.patch index 625a2219dc..45c815c834 100644 --- a/paper-server/nms-patches/net/minecraft/world/entity/projectile/EntityEvokerFangs.patch +++ b/paper-server/nms-patches/net/minecraft/world/entity/projectile/EntityEvokerFangs.patch @@ -25,7 +25,7 @@ if (entityliving.isAlive() && !entityliving.isInvulnerable() && entityliving != entityliving1) { if (entityliving1 == null) { - entityliving.hurt(this.damageSources().magic(), 6.0F); -+ entityliving.hurt(this.damageSources().magic().customCausingEntity(this), 6.0F); // CraftBukkit ++ entityliving.hurt(this.damageSources().magic().customEntityDamager(this), 6.0F); // CraftBukkit } else { if (entityliving1.isAlliedTo((Entity) entityliving)) { return; diff --git a/paper-server/nms-patches/net/minecraft/world/level/Explosion.patch b/paper-server/nms-patches/net/minecraft/world/level/Explosion.patch index 7e65299c7a..28df90838c 100644 --- a/paper-server/nms-patches/net/minecraft/world/level/Explosion.patch +++ b/paper-server/nms-patches/net/minecraft/world/level/Explosion.patch @@ -28,7 +28,7 @@ public static DamageSource getDefaultDamageSource(World world, @Nullable Entity entity) { return world.damageSources().explosion(entity, getIndirectSourceEntityInternal(entity)); -@@ -86,17 +100,18 @@ +@@ -86,7 +100,7 @@ this.hitPlayers = Maps.newHashMap(); this.level = world; this.source = entity; @@ -37,11 +37,7 @@ this.x = d0; this.y = d1; this.z = d2; - this.fire = flag; - this.blockInteraction = explosion_effect; -- this.damageSource = damagesource == null ? world.damageSources().explosion(this) : damagesource; -+ this.damageSource = damagesource == null ? world.damageSources().explosion(this).customCausingEntity(entity) : damagesource.customCausingEntity(entity); // CraftBukkit - handle source entity - this.damageCalculator = explosiondamagecalculator == null ? this.makeDamageCalculator(entity) : explosiondamagecalculator; +@@ -97,6 +111,7 @@ this.smallExplosionParticles = particleparam; this.largeExplosionParticles = particleparam1; this.explosionSound = holder; @@ -144,7 +140,7 @@ + this.yield = event.getYield(); + } else { + org.bukkit.block.Block block = location.getBlock(); -+ org.bukkit.block.BlockState blockState = (damageSource.blockState != null) ? damageSource.blockState : block.getState(); ++ org.bukkit.block.BlockState blockState = (damageSource.getDirectBlockState() != null) ? damageSource.getDirectBlockState() : block.getState(); + BlockExplodeEvent event = new BlockExplodeEvent(block, blockState, blockList, this.yield); + this.level.getCraftServer().getPluginManager().callEvent(event); + this.wasCanceled = event.isCancelled(); diff --git a/paper-server/nms-patches/net/minecraft/world/level/block/BlockBed.patch b/paper-server/nms-patches/net/minecraft/world/level/block/BlockBed.patch index dbb8c3605b..9f9c5700f1 100644 --- a/paper-server/nms-patches/net/minecraft/world/level/block/BlockBed.patch +++ b/paper-server/nms-patches/net/minecraft/world/level/block/BlockBed.patch @@ -27,7 +27,7 @@ if (entityhuman_enumbedresult.getMessage() != null) { entityhuman.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); } -@@ -123,8 +133,29 @@ +@@ -123,8 +133,30 @@ } } @@ -35,6 +35,7 @@ + private EnumInteractionResult explodeBed(IBlockData iblockdata, World world, BlockPosition blockposition) { + { + { ++ org.bukkit.block.BlockState blockState = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition).getState(); // CraftBukkit - capture BlockState before remove block + world.removeBlock(blockposition, false); + BlockPosition blockposition1 = blockposition.relative(((EnumDirection) iblockdata.getValue(BlockBed.FACING)).getOpposite()); + @@ -44,7 +45,7 @@ + + Vec3D vec3d = blockposition.getCenter(); + -+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, world, iblockdata, blockposition), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, World.a.BLOCK); // CraftBukkit - add state ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, blockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, World.a.BLOCK); // CraftBukkit - add state + return EnumInteractionResult.SUCCESS; + } + } @@ -58,7 +59,7 @@ } private boolean kickVillagerOutOfBed(World world, BlockPosition blockposition) { -@@ -323,6 +354,11 @@ +@@ -323,6 +355,11 @@ BlockPosition blockposition1 = blockposition.relative((EnumDirection) iblockdata.getValue(BlockBed.FACING)); world.setBlock(blockposition1, (IBlockData) iblockdata.setValue(BlockBed.PART, BlockPropertyBedPart.HEAD), 3); diff --git a/paper-server/nms-patches/net/minecraft/world/level/block/BlockRespawnAnchor.patch b/paper-server/nms-patches/net/minecraft/world/level/block/BlockRespawnAnchor.patch index 3e715a01bf..30a49ff43d 100644 --- a/paper-server/nms-patches/net/minecraft/world/level/block/BlockRespawnAnchor.patch +++ b/paper-server/nms-patches/net/minecraft/world/level/block/BlockRespawnAnchor.patch @@ -9,9 +9,11 @@ world.playSound((EntityHuman) null, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, SoundEffects.RESPAWN_ANCHOR_SET_SPAWN, SoundCategory.BLOCKS, 1.0F, 1.0F); return EnumInteractionResult.SUCCESS; } -@@ -129,14 +129,14 @@ +@@ -128,15 +128,16 @@ + } private void explode(IBlockData iblockdata, World world, final BlockPosition blockposition) { ++ org.bukkit.block.BlockState blockState = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition).getState(); // CraftBukkit - capture BlockState before remove block world.removeBlock(blockposition, false); - Stream stream = EnumDirection.EnumDirectionLimit.HORIZONTAL.stream(); + Stream stream = EnumDirection.EnumDirectionLimit.HORIZONTAL.stream(); // CraftBukkit - decompile error @@ -26,12 +28,12 @@ @Override public Optional getBlockExplosionResistance(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition1, IBlockData iblockdata1, Fluid fluid) { return blockposition1.equals(blockposition) && flag1 ? Optional.of(Blocks.WATER.getExplosionResistance()) : super.getBlockExplosionResistance(explosion, iblockaccess, blockposition1, iblockdata1, fluid); -@@ -144,7 +144,7 @@ +@@ -144,7 +145,7 @@ }; Vec3D vec3d = blockposition.getCenter(); - world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), explosiondamagecalculator, vec3d, 5.0F, true, World.a.BLOCK); -+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, world, iblockdata, blockposition), explosiondamagecalculator, vec3d, 5.0F, true, World.a.BLOCK); // CraftBukkit - add state ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, blockState), explosiondamagecalculator, vec3d, 5.0F, true, World.a.BLOCK); // CraftBukkit - add state } public static boolean canSetSpawn(World world) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java b/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java index 9fd14743d7..4a1b01c735 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/damage/CraftDamageSource.java @@ -41,13 +41,13 @@ 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(); return (entity != null) ? entity.getBukkitEntity() : null; } @Override public org.bukkit.entity.Entity getDirectEntity() { - net.minecraft.world.entity.Entity entity = this.getHandle().getDirectEntity(); + net.minecraft.world.entity.Entity entity = this.getHandle().getDamager(); 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().getEntity() != this.getHandle().getDamager(); } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java index c8fc7b8481..9fa6c121c0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -939,7 +939,7 @@ public class CraftEventFactory { private static EntityDamageEvent handleEntityDamageEvent(Entity entity, DamageSource source, Map modifiers, Map> modifierFunctions, boolean cancelled) { CraftDamageSource bukkitDamageSource = new CraftDamageSource(source); - Entity damager = (bukkitDamageSource.isIndirect() && source.getDirectEntity() != null) ? source.getDirectEntity() : source.getCausingEntity(); + Entity damager = (source.getDamager() != null) ? source.getDamager() : source.getEntity(); if (source.is(DamageTypeTags.IS_EXPLOSION)) { if (damager == null) { return callEntityDamageEvent(source.getDirectBlock(), entity, DamageCause.BLOCK_EXPLOSION, bukkitDamageSource, modifiers, modifierFunctions, cancelled);