Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-216985

Some entities don't bounce on a slime block when falling down into it

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • None
    • 1.16.5, 21w08b, 21w11a, 21w13a, 21w15a, 1.17, 1.17.1, 1.18.1, 22w06a, 1.19.1 Pre-release 5, 1.19.3, 1.19.4 Pre-release 1, 1.19.4, 23w14a, 1.20.1, 1.20.4
    • None
    • Confirmed
    • Entities

      The bug

      Tnt, Falling blocks, and Xp orbs (only those that I know of currently, might be more) don't bounce on slime blocks when falling into them. This is due to the order or events in the entities tick phase where the onGround tag perpetuates downward motion instead of upwards.

      How to reproduce

      1. Place four slime blocks in a 2x2 pattern on the floor.
      2. Go in the middle of the 4 slime blocks and fly up 5 blocks
      3. Use the following command above the slime blocks
      4. /summon minecraft:tnt ~ ~ ~ {fuse:100,Motion:[0.0,-9.0,0.0]}

        It will not bounce

      Code analysis

      Using Fabric mapping 1.16.5

      Here, we will look at the tnt entity for this example. We will start in the tick phase where it handles its motion and velocity as well as other important stuff not related to this ticket.  We will say that this entity is moving down in this example (negative velocity y). We are first going to go into the move method as that is called first:

      public void tick() {
          REMOVED code as it was not needed
          this.move(MovementType.SELF, this.getVelocity());
          REMOVED code as it was not needed
          if (this.onGround) {
              this.setVelocity(this.getVelocity().multiply(0.7, -0.5, 0.7));
          }
          REMOVED code as it was not needed
      }
      

      In the move method of the Entity class:

      public void move(MovementType type, Vec3d movement) {
      
          REMOVE code above as it was not needed
      
          BlockPos lv2 = this.getLandingPos();
          BlockState lv3 = this.world.getBlockState(lv2);
      
          REMOVED code here as it was not needed
      
          this.fall(lv.y, this.onGround, lv3, lv2);
          Vec3d lv4 = this.getVelocity();
          Block lv5 = lv3.getBlock();
          if (movement.y != lv.y) {
              lv5.onEntityLand(this.world, this);
          }
      
          REMOVED code here as it was not needed
      }
      

      In the move method, the entity will try to go to it's final location using the velocity supplied in the parameters. If the y position hits a block, movement.y != lv.y, will be set to true and call onEntityLand, supplying a block, which in this case, that is a slime block.

      Now looking in the onEnitiyLand code

      @Override
      public void onEntityLand(BlockView world, Entity entity) {
          if (entity.bypassesLandingEffects()) {
              super.onEntityLand(world, entity);
          } else {
              this.bounce(entity);
          }
      }
      
      

      As the tnt can't bypassesLandingEffects, it will call this.bounce(entity).

      Now looking at the bounce:

      private void bounce(Entity entity) { 
         Vec3d lv = entity.getVelocity();
         if (lv.y < 0.0) {
           double d = entity instanceof LivingEntity ? 1.0 : 0.8;
           entity.setVelocity(lv.x, -lv.y * d, lv.z); 
         } 
      }
      

      As the tnt is being shot down, it has negative y velocity. Thus, the entities velocity will be set to a positive as it has its sign changed by -lv.y

      As the move method is now done, we are back in the tick method

      public void tick() { REMOVED code as it was not needed  
       this.move(MovementType.SELF, this.getVelocity());
       REMOVED code as it was not needed 
       if (this.onGround) { 
           this.setVelocity(this.getVelocity().multiply(0.7, -0.5, 0.7)); 
       }
       REMOVED code as it was not needed
      }
      

      We came out of the move method with a positive velocity. Now, as it hit a block going down, the onGround check was set to true. As the onGround check was set to true, the y velocity will be multiplied by -0.5, thus making it negative. When the tick is called again, the slime blocks will just keep smacking into the slime block, thus never bouncing up.

      Below is an MCP print statement to show the same thing above.

      [Player268: Summoned new Primed TNT]
      -9.04 before move in tick
      -9.04 pre move
      -9.04 Pre onLanded
      -9.04 enter bounce
      7.231999999999999 return from bounce
      7.231999999999999 Post onlanded
      7.231999999999999 Pre ground and stepping
      7.231999999999999 post ground and stepping
      7.231999999999999 post move
      7.231999999999999 after move in tick
      7.087359999999999 before ground in tick
      -3.5436799999999997 after ground in tick
      

      Solution

      Like MC-207866

      If an entity has collided with a slime block in the "bounce", set the OnGround tag to false. This may have unforeseen consequences, but I can't think of any as of now.

            Unassigned Unassigned
            Kman032317 Kyle Weber
            Votes:
            13 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              CHK: