mojira.dev
MC-88533

Entities without hitboxes cannot properly be tested for with target argument "distance=0" or "dy=0"

These experiments involve marker armorstands – it also affects area effect clouds with zero radius. Most likely the bug occurs due to these armorstands lacking a hitbox.

Setup experiment
In this scenerio the armorstands involved in the testing were obtained as follows:

/summon armor_stand ~ ~ ~ {CustomName:"\"A\"",Marker:X}
/execute at @e[name=A] run summon armor_stand ~ ~ ~ {CustomName:"\"B\"",Marker:X}

Note that the X is either a 0 or 1 depending on the following cases.

Results experiment
We distinguish the following 3 cases

  • Case 1: ArmorStand A is not a marker, ArmorStand B is not a marker.

    execute at @e[name=A] run kill @e[name=B,distance=0]

    Kills B, works as expected

    execute at @e[name=B] run kill @e[name=A,distance=0]

    Kills A, works as expected

  • Case 2: ArmorStand A is a marker, ArmorStand B is not a marker.

    execute at @e[name=A] run kill @e[name=B,distance=0]

    Kills B, works as expected

    execute at @e[name=B] run kill @e[name=A,distance=0]

    Does not kill A, does not work as expected

  • Case 3: ArmorStand A is a marker, ArmorStand B is a marker.

    execute at @e[name=A] run kill @e[name=B,distance=0]

    Does not kill B, does not work as expected

    execute at @e[name=B] run kill @e[name=A,distance=0]

    Does not kill A, does not work as expected

Further research
I've had a talk about these seemingly bugs with SkylinerW who in the MC community is a well respected modder/'expert' on Minecraft. This talk can be found back in this reddit topic:
https://www.reddit.com/r/Minecraft/comments/3cgck7/the_nbt_tag_marker1b_made_a_position_glitch_of/

Here are some extracts from our conversation that might help you guys further, credit to SkylinerW:

"That one definitely seems to be a bug. It's not just armor stands, but any entity that is in the ground; I can't get the command to work even if there's a villager with its feet stuck in a block directly underneath the armor stand without increasing the radius to 2 (r=1 still presents the problem, so it's not restricted to r=0). It's specific to the Y coordinate, so it seems like their interpreted location is being skewed for being within a block. I imagine the eye height for marker stands being at the exact Y value causes it to be seen as being within a block.


Code analysis by @unknown can be found in this comment.


Also this can be more easily tested with this being run in chat while you don't move:

summon armor_stand ~ ~ ~ {NoGravity:1b,Marker:1b,CustomName:"\"c\""}
say @e[distance=0]

this'll only show your name and not the armor stand's, unless you change it to Marker:0b

Linked issues

Comments

[Bot] Arisa

Please do not mark unreleased versions as affected.
You don't have access to them yet.

--- This action was performed automagically. If you believe this was done erroneously, please :light_bulb_on: raise an issue.

SlaxX

Please fix this ;_; i can't do it otherwise...

user-f2760

You can temperarely make it r=1, and when it's fixed you can change it to r=0

I hate this bug too, it makes some systems suck, but that's why there is a bug tracker, and this will get fixed at one point

SlaxX

Thats the problem. I can't ^^
Cause there are other Armorstands around it that should not be affected.
And something like /execute (...) ~ ~1 ~ (...) @e[r=1] doesn't work either.
With an offset of 0.999 none of the Armorstands react, and with 0.998 all of them do...

user-f2760

You could add c=1

SlaxX

Oooooh guess i misunderstood the purpose of c...
good thing i looked it up before writing you an answer ^^
thats the exact thing i'm looking for, thanks!

GamerGuppy

UPDATE: Previously this bug report contained a different scenerio in which the target argument "r" failed to test for the right entity. This scenerio has been moved to a new bug-report since it is completely unrelated as to why marker armorstands can't be tested for. See MC-95352.

marcono1234

Confirmed for

  • 16w05b

user-f2760

In 16w07a seems to effect all entities, not only marker armor stands.
I suggest collecting them all here, as this issue is the same, and already assigned.

GamerGuppy

And I suggest not to, since these are 2 entirely different problems.

I do understand where you are coming from FVbico, since many of my contraptions are broken too. After the fix of MC-95352, "r" now works as it should; /execute @e[name=A] ~ ~ ~ testfor @e[name=B,r=0] now only succesfully finds B if B is located exactly at the center of the block where A is too. Why is it working as it should? Well a command is always executed with respect to the center of a block, even if you do /execute @e[name=A]. But as I said, maybe r=0 should be an exception to this rule, since so many people use it to target an entity somewhere in the same block as the entity the command is executed from.

Adrodoc55

Confirmed for 1.9-pre4

Plagiatus

Confirmed for 1.9.1-pre3

koder

How long has Searge been working on this?

user-f2760

He only assigned himself, that doesn't mean he works on it at the moment, only that he is the one willing to fix it

koder

In that case, how long has be been assigned to this?

FaRo1

Since 11/Feb/16 3:56 PM, like you can see in the activity feed.

Ely G

confirmed up to 1.9.4

Adrodoc55

Confirmed for 16w21b

marcono1234

Please link to this comment in the description

The following is based on a decompiled version of Minecraft 1.10 using MCP 9.30.

The reason for this is very likely that the method net.minecraft.command.EntitySelector.filterResults(Map<String, String>, Class<? extends T>, List<Predicate<Entity>>, String, World, BlockPos) creates a bounding box which is expanded in the negative and positive directions by the radius but only in the positive direction by an additional 1. It looks like this bounding box is only used to reduce the amount of entities that will be tested. It then searches for entities whose bounding box intersects with it. A bounding box counts as intersecting if bb1.minX < bb2.maxX AND bb1.minY < bb2.maxY AND bb1.minZ < bb2.maxZ AND bb1.maxX > bb2.minX AND bb1.maxY > bb2.minY AND bb1.maxZ > bb2.minZ. The problem is that both armor stands are at the same Y block coordinate. As the bounding box is only expanded in the positive direction by an additional 1 the bounding boxes which will be compared have both the same minY value which means they don't intersect.

This could be solved by expanding the bounding box by an additional 1 in the negative direction as well.
Edit: This solution might be flawed and could cause issues similar to MC-123441.

private static <T extends Entity> List<T> filterResults(Map<String, String> params, Class <? extends T > entityClass, List<Predicate<Entity>> inputList, String type, World worldIn, BlockPos position)
{
    List<T> list = Lists.<T>newArrayList();
    String s = getArgument(params, "type");
    s = s != null && s.startsWith("!") ? s.substring(1) : s;
    boolean flag = !type.equals("e");
    boolean flag1 = type.equals("r") && s != null;
    int i = parseIntWithDefault(params, "dx", 0);
    int j = parseIntWithDefault(params, "dy", 0);
    int k = parseIntWithDefault(params, "dz", 0);
    int l = parseIntWithDefault(params, "r", -1);
    Predicate<Entity> predicate = Predicates.and(inputList);
    Predicate<Entity> predicate1 = Predicates.<Entity> and (EntitySelectors.IS_ALIVE, predicate);
    int i1 = worldIn.playerEntities.size();
    int j1 = worldIn.loadedEntityList.size();
    boolean flag2 = i1 < j1 / 16;

    if (!params.containsKey("dx") && !params.containsKey("dy") && !params.containsKey("dz"))
    {
        if (l >= 0)
        {
            // Changed this
            //AxisAlignedBB axisalignedbb1 = new AxisAlignedBB((double)(position.getX() - l), (double)(position.getY() - l), (double)(position.getZ() - l), (double)(position.getX() + l + 1), (double)(position.getY() + l + 1), (double)(position.getZ() + l + 1));
            AxisAlignedBB axisalignedbb1 = new AxisAlignedBB((double)(position.getX() - l - 1), (double)(position.getY() - l - 1), (double)(position.getZ() - l - 1), (double)(position.getX() + l + 1), (double)(position.getY() + l + 1), (double)(position.getZ() + l + 1));

            if (flag && flag2 && !flag1)
            {
                list.addAll(worldIn.<T>getPlayers(entityClass, predicate1));
            }
            else
            {
                list.addAll(worldIn.<T>getEntitiesWithinAABB(entityClass, axisalignedbb1, predicate1));
            }
        }
        else if (type.equals("a"))
        {
            list.addAll(worldIn.<T>getPlayers(entityClass, predicate));
        }
        else if (!type.equals("p") && (!type.equals("r") || flag1))
        {
            list.addAll(worldIn.<T>getEntities(entityClass, predicate1));
        }
        else
        {
            list.addAll(worldIn.<T>getPlayers(entityClass, predicate1));
        }
    }
    else
    {
        final AxisAlignedBB axisalignedbb = getAABB(position, i, j, k);

        if (flag && flag2 && !flag1)
        {
            Predicate<Entity> predicate2 = new Predicate<Entity>()
            {
                public boolean apply(@Nullable Entity p_apply_1_)
                {
                    return p_apply_1_ != null && axisalignedbb.intersectsWith(p_apply_1_.getEntityBoundingBox());
                }
            };
            list.addAll(worldIn.<T>getPlayers(entityClass, Predicates.<T> and (predicate1, predicate2)));
        }
        else
        {
            list.addAll(worldIn.<T>getEntitiesWithinAABB(entityClass, axisalignedbb, predicate1));
        }
    }

    return list;
}
SunCat

Fixed for 16w38a

user-f2760

Confirmed fixed.

Bytenka

Back (or still, idk) in 16w42a for me.

FaRo1

Nope, not in 16w42a.

/summon armor_stand ~ ~ ~ {Marker:1,NoGravity:1}
/execute @e[type=armor_stand,r=1] ~ ~ ~ summon armor_stand ~ ~ ~ {Marker:1,NoGravity:1}
/execute @e[type=armor_stand,r=1] ~ ~ ~ tesfor @e[type=armor_stand,r=0]

gives out:

Found Armor Stand
Found Armor Stand
Found Armor Stand
Found Armor Stand
SunCat

Confirmed for 1.11-pre1. Please reopen

Ersatz

Confirmed for 1.11. Hopefully this gets fixed soon.

AjaxGb

Confirmed for 1.12-pre5.

Maxaxik

Confirmed for 1.12-pre7

JochCool

Can confirm for 1.12.2 😞

vdvman1

Can confirm for 18w10d

AlexMCool

Confirmed for 18w16a

AlexMCool

confirmed for 1.13pre-3

AlexMCool

Affects 1.13-pre4

AlexMCool

Affects 1.13-pre5. Also this can be more easily tested with this being run in chat while you don't move:

summon armor_stand ~ ~ ~ {NoGravity:1b,Marker:1b,CustomName:"\"c\""}
say @e[distance=0]

this'll only show your name and not the armor stand's, unless you change it to Marker:0b

AlexMCool

Affects 1.13-pre6

AlexMCool

Affects 1.13-pre7

AlexMCool

And 1.13-pre8

AlexMCool

And 1.13-pre9

AlexMCool

And 1.13

AlexMCool

And 18w30a

AlexMCool

And 18w30b

[Bot] Arisa

Please do not mark unreleased versions as affected.
You don't have access to them yet.

JochCool

And it's still here in 1.16.3

SolidBlock

I found any markers can't be selected via volume.

Triton365

(Workaround)

This does not occur in predicate's distance detection. Use that instead.

JochCool

Still affects 1.17.1

Simpy

still a problem in 1.18.1

user-f2760

This could be solved by expanding the bounding box by an additional 1 in the negative direction as well.

(for the code analysis comment)

This is actually a horrible way to fix it, as it makes making small selection cubes even harder, amplifying MC-123441 to be twice as severe.

The actual problem is that these entities are only a point in existence, as the point is not accepted in the selection box, because it's on the very edge. (The selector check is "in between min and max, excluding min and max values", rather than "in between min and max, including min and max values".)
You can literally offset the selection box by 0.00001 on x y and z, and then find it with dx/dy/dz just fine.
Example:

/summon marker
/execute as @e[type=marker] at @s run say @s[dy=0] <- no result
/execute as @e[type=marker] at @s positioned ~-0.00001 ~-0.00001 ~-0.00001 run say @s[dy=0] <- result

For distance= there doesn't seem to be a command-workaround, but you can use predicates are previously pointed out (because they properly check for including, not excluding).

RoarkCats

Can confirm in 1.21.1 with marker entities

GamerGuppy

AlexMCool

(Unassigned)

Confirmed

Platform

Low

Commands

Marker, argument, armor_stand, radius, selector

Minecraft 1.8.8, Minecraft 15w36d, Minecraft 15w37a, Minecraft 15w42a, Minecraft 15w51b, ..., 1.16.3, 1.17.1, 1.18.1, 1.19, 1.21.3

Minecraft 16w38a

Retrieved