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

Entity collision order is now locational

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • 1.21.2 Pre-Release 2
    • 24w40a
    • None
    • Community Consensus
    • Collision
    • Normal
    • Platform

      So, now the order in which an entity interacts with pressure plates and alike blocks is locational. This behavior was previosly non locational thus the change breaks redstone contraptions that relied on it.

      How to replicate:
      Create a redstone ready superflat world in 24w40a, run these commands:
      /execute in minecraft:overworld run tp @s 99999 63 19 -90 60
      /fill 100000 59 17 99999 59 20 minecraft:blue_concrete
      /fill 100000 60 17 99999 60 20 minecraft:heavy_weighted_pressure_plate
      /fill 100000 60 18 99999 60 19 air
      /setblock 100000 59 18 minecraft:sticky_piston[facing=west]
      /setblock 99999 59 18 minecraft:sticky_piston[facing=east]
      /setblock 100000 59 21 minecraft:sticky_piston[facing=west]
      /setblock 99999 59 21 minecraft:sticky_piston[facing=east]

      You should get a setup that looks something like this:

      Then perform these two commands and observe the pistons (which piston extends indicates which pressure plate is activated first by the armor stand)
      /summon minecraft:armor_stand 100000. 60.00 20.5
      /summon minecraft:armor_stand 100000. 60.00 17.5

      As you can see pistons on different sides activated, this means that the order in which an armor stand activates pressure plates below self is not consistent.

      The expected behavior is for an entity to activate the collideable blocks below self in a consistent order that does not depend on location (previously in 1.21.1 it was directional but not locational)

      Code analysis:
      Currently the block coords to be collided with are collected within the
      boxTraverseBlocks method in the BlockGetter.java file and in the
      addCollisionsAlongTravel method in the BlockGetter.java , there the block coords are put into a set (ObjectOpenHashSet), then the said set is returned to the
      collectBlockCollidedWith method in the Entity.java file
      Where it iterates through the set and puts all of the collected block coords into the
      blocksInside field of an Entity object, this field is a HashMap, and later within the
      applyEffectsFromBlocks method within the Entity.java it iterates through said map, executing block collisions for each collected block coordinate.

      Obviously collecting coordinates into a hashset, then puting them into a hashmap and then iterating through that scrambles the order of entries and is generally suboptimal.
      Moreover, there is no real reason to store the block coordinates in any container at all, as the collision can be computed while the block coordinates are collected (so directly within the uppermentioned boxTraverseBlocks and addCollisionsAlongTravel methods). Executing the collisions right when the collisiosn block coordinate is acquired will not only fix the issue with the collision order being inconsistent (locational), but will also increase the performance just a bit because the game wont have to initialise a set and a map of 1-8 entries per each entity per each game tick.

      For clarification, by "executing the collision" i mean checking if the entity intersects the collidable part of the hitbox of a block located at the collected block coordinate as done here in the collectBlockCollidedWith method:

      and later performing block reaction to entity collision as it is currently done here within the applyEffectsFromBlocks method:

      And by "executing collisions while the block coordinates are collected" i mean executing them inside inside the boxTraverseBlocks and addCollisionsAlongTravel immideately instead of puting the block coordinates into the set here:

      and here:

      and there has to be a check against performing the collision on the same position multiple times as currently this cant happen because of positions being stored in a set.

      Please note, that this issue does break certain redstone contraptions, and it does so in a very annoying way, as there are no meaningful alternatives to fix this issue with the ingame means, it just detracts from the gameplay.

      This issue happens in the same place in code as the MC-275437

        1. screenshot-2.png
          screenshot-2.png
          190 kB
        2. screenshot-1.png
          screenshot-1.png
          192 kB
        3. image-2024-10-02-23-16-44-248.png
          image-2024-10-02-23-16-44-248.png
          214 kB
        4. image-2024-10-02-23-13-49-169.png
          image-2024-10-02-23-13-49-169.png
          213 kB
        5. image-2024-10-02-22-49-09-277.png
          image-2024-10-02-22-49-09-277.png
          457 kB
        6. image-2024-10-02-22-42-55-168.png
          image-2024-10-02-22-42-55-168.png
          983 kB

            HugoHagglund [Mojang] SHugoh
            Savvvage_ Savva
            Votes:
            22 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved:
              CHK: