The Bug
It's now noticeable because of the Sweeping Edge enchantment.
Steps to Reproduce
Obtain a netherite sword with the sweeping edge enchantment.
/give @s minecraft:netherite_sword{Enchantments:[{id:"sweeping",lvl:3}]}
Summon two creepers next to one another.
/summon minecraft:creeper ~ ~ ~-2.5 {NoAI:1b} /summon minecraft:creeper ~1 ~ ~-2.5 {NoAI:1b}
Damage any of the one creepers with a sweeping attack using the sword.
Take note as to whether or not the creeper that you didn't directly damage produces minecraft:damage_indicator particles.
Observed Behavior
Entities damaged with the sweeping attack indirectly don't produce minecraft:damage_indicator particles.
Expected Behavior
Entities damaged with the sweeping attack indirectly would produce minecraft:damage_indicator particles.
Linked issues
Attachments
Comments 15
I am able to confirm this behavior in 21w41a. Here are some extra details regarding this problem.
The Bug:
Entities damaged with the sweeping attack indirectly don't produce minecraft:damage_indicator particles.
Steps to Reproduce:
Obtain a netherite sword with the sweeping edge enchantment.
/give @s minecraft:netherite_sword{Enchantments:[{id:"sweeping",lvl:3}]}
Summon two creepers next to one another.
/summon minecraft:creeper ~ ~ ~-2.5 {NoAI:1b}
/summon minecraft:creeper ~1 ~ ~-2.5 {NoAI:1b}
Damage any of the one creepers with a sweeping attack using the sword.
Take note as to whether or not the creeper that you didn't directly damage produces minecraft:damage_indicator particles.
Observed Behavior:
Entities damaged with the sweeping attack indirectly don't produce minecraft:damage_indicator particles.
Expected Behavior:
Entities damaged with the sweeping attack indirectly would produce minecraft:damage_indicator particles.
Code analysis (Mojang mappings, 1.19.4 Pre-release 3): The attacking heart particles (DAMAGE_INDICATOR
) are added in Player#attack(Entity)
, but only for the directly attacked entity. If this is a bug, I believe a possible fix is to change this part of the function:
...
if ($$9) {
...
List<LivingEntity> $$18 = this.level.getEntitiesOfClass(LivingEntity.class, $$0.getBoundingBox().inflate(1.0, 0.25, 1.0));
for (LivingEntity $$19 : $$18) {
if ($$19 == this || $$19 == $$0 || this.isAlliedTo($$19) || $$19 instanceof ArmorStand && ((ArmorStand)$$19).isMarker() || !(this.distanceToSqr((Entity)$$19) < 9.0)) continue;
$$19.knockback(0.4f, Mth.sin(this.getYRot() * ((float)Math.PI / 180)), -Mth.cos(this.getYRot() * ((float)Math.PI / 180)));
$$19.hurt(this.damageSources().playerAttack(this), $$17);
}
...
}
...
to something along the lines of:
...
if ($$9) {
...
List<LivingEntity> $$18 = this.level.getEntitiesOfClass(LivingEntity.class, $$0.getBoundingBox().inflate(1.0, 0.25, 1.0));
for (LivingEntity $$19 : $$18) {
if ($$19 == this || $$19 == $$0 || this.isAlliedTo($$19) || $$19 instanceof ArmorStand && ((ArmorStand)$$19).isMarker() || !(this.distanceToSqr((Entity)$$19) < 9.0)) continue;
float healthBefore = $$19.getHealth();
$$19.knockback(0.4f, Mth.sin(this.getYRot() * ((float)Math.PI / 180)), -Mth.cos(this.getYRot() * ((float)Math.PI / 180)));
$$19.hurt(this.damageSources().playerAttack(this), $$17);
float damage = healthBefore - $$19.getHealth();
if (damage > 2.0f) {
int amount = (int)((double)damage * 0.5);
((ServerLevel)this.level).sendParticles(ParticleTypes.DAMAGE_INDICATOR, $$19.getX(), $$19.getY(0.5), $$19.getZ(), amount, 0.1, 0.0, 0.1, 0.2);
}
}
...
}
...
which would be in line with how the attacking particles are added later in the function.
Can confirm for MC 1.12.1.