Skip to content

minecraft:blocks_attacks non-vanilla behaviour #13426

@yorik100

Description

@yorik100

Expected behavior

If damage post block is above 0 :

  • Take knockback
  • setDeltaMovement of player accordingly to knockback
  • Play block_sound
  • Deal remaining damage to player

If damage post block is 0 :

  • Deal knockback to attacker
  • Play block_sound

Observed/Actual behavior

If damage post block is above 0 :

  • setDeltaMovement of player accordingly to knockback
  • Play block_sound
  • Deal remaining damage to player

If damage post block is 0 :

  • setDeltaMovement of player accordingly to knockback
  • Deal knockback to attacker
  • Play block_sound

Steps/models to reproduce

If damage post block is above 0 :
/give @s diamond_sword[blocks_attacks={disable_cooldown_scale:0,damage_reductions:[{types: [mob_attack,arrow,explosion],base:0,factor:0.5}],block_sound:block.anvil.place}]

Block with that sword, facing an enemy attacking you, you'll take damage but not knockback, this is not the case in Vanilla, in Vanilla you still take knockback if attacks deal over 0 damage

If damage post block is 0 :
Block with a shield, when blocking a hit, the server will still set your delta movement based off knockback the player received yet knockback was never sent to client, you shouldn't do setDeltaMovement from knockback function in LivingEntity.java if no damage was dealt, it's useless and could cause desync between client and server, server's delta movement is used for arrow speed calculation for example, it wouldn't make sense to make your arrows go faster after blocking a hit

Plugin and Datapack List

None

Paper version

1.21.10-129

Other

Note 1 : The main issue would be caused by this in LivingEntity.java

                if (!damageSource.is(DamageTypeTags.NO_IMPACT) && !flag) { // CraftBukkit - Prevent marking hurt if the damage is blocked
                    this.markHurt();
                }

flag is if damageBlocked is above 0 instead of if damage - damageBlocked is above 0, this.markHurt() sets this.hurtMarked to true which causes knockback to be sent to the client at the end of the tick, knockback equivalent to current deltaMovement value (which is properly set in this case by this.knockback function that is after that in note 2 but shouldn't be set if damage received is 0 or less)

Note 2 : The 2nd issue where it sets knockback even if damage is 0 is also there in LivingEntity.java

                if (!damageSource.is(DamageTypeTags.NO_KNOCKBACK)) {
                    double d = 0.0;
                    double d1 = 0.0;
                    if (damageSource.getDirectEntity() instanceof Projectile projectile) {
                        DoubleDoubleImmutablePair doubleDoubleImmutablePair = projectile.calculateHorizontalHurtKnockbackDirection(this, damageSource);
                        d = -doubleDoubleImmutablePair.leftDouble();
                        d1 = -doubleDoubleImmutablePair.rightDouble();
                    } else if (damageSource.getSourcePosition() != null) {
                        d = damageSource.getSourcePosition().x() - this.getX();
                        d1 = damageSource.getSourcePosition().z() - this.getZ();
                    }
                    // Paper start - Check distance in entity interactions; see for loop in knockback method
                    if (Math.abs(d) > 200) {
                        d = Math.random() - Math.random();
                    }
                    if (Math.abs(d1) > 200) {
                        d1 = Math.random() - Math.random();
                    }
                    // Paper end - Check distance in entity interactions

                    this.knockback(0.4F, d, d1, damageSource.getDirectEntity(), damageSource.getDirectEntity() == null ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.DAMAGE : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events
                    if (!flag) {
                        this.indicateDamage(d, d1);
                    }
                }

This sets player's serveride speed to knockback even though knockback isn't dealt, also, once again

                    if (!flag) {
                        this.indicateDamage(d, d1);
                    }

It is not indicatingDamage is flag is false and flag is false if blockedDamage is above 0 instead of checking if damage - damageBlocked is above 0

Note : If possible, add an option not to play shield sound if damage after block is above 0 and play the normal hurt sound normally

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: acceptedDisputed bug is accepted as valid or Feature accepted as desired to be added.version: 1.21.10Game version 1.21.10version: 1.21.11Game version 1.21.11

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions