Can confirm in 1.17
Did some digging on this. Turns out Striders set their NoGravity flag to true when they're in lava and to false when they aren't; that's how they float. Certain things can make the flag get stuck on true. A consistent and easy one is just saving and quitting while the Strider is standing in lava. After you reopen the world, the Strider is stuck floating at their current height forever. The flag being stuck like this also prevents them from walking up blocks, which they can normally do.
This also relates to MC-176203, as the NoGravity flag prevents levitation. Striders probably shouldn't be using that flag; it's mostly intended for command use only.
@violine1101 I actually don't think that's a duplicate. That bug is about how, when the lodestone is broken, the compass is still a Lodestone Compass, just a Lodestone Compass that points to nothing. This bug is about how, when the lodestone is broken, compasses in containers won't notice at all, and will continue to point to the lodestone's old location until they are placed back into the player's inventory.
Confirmed for both 1.15.2 and 20w07a.
I was unable to reproduce in 1.15.2. Seems to be resolved.
Confirmed for 1.14.4 and 19w41a.
I suspect that this is happening because villagers have a much smaller hitbox while sleeping.
Confirmed for 19w04b.
Confirmed for 18w32a, with the upper limit of distance= in place of r=. Setting only the lower limit has no effect, so
distance=1000000..will not trigger the bug, but any of
distance=1000000
distance=..1000000will.
And for 18w32a.
Confirmed for 1.13.
Confirmed for 1.12.2 and 1.13-pre5.
Confirmed for 18w16a.
Confirmed for 1.12-pre5.
So does that mean that there's now a maximum chain length? If so, what is it?
@unknown Thanks for the correction.
I did a code analysis with a suggested solution on the related bug MC-73916. The problem and solution are the same for this bug; please link in the description.
Time for some code analysis! This is based on MCP for 1.10.2. Please link this in the description.
So the reason for both this and MC-54932 is the same. As @unknown said, this does not affect Player-only selectors in most cases; if the players make up 1/16 or more of the loaded entities, the bug will occur.
The bottleneck is the method getEntitiesWithinAABB, which is used for both radius- and region-based selection of entities (and players in the 1/16 case mentioned above). It loops through all chunks within the bounding box and, if they are loaded, adds any of their entities that fall within the bounding box.
public <T extends Entity> List<T> getEntitiesWithinAABB(Class <? extends T > clazz, AxisAlignedBB aabb, @Nullable Predicate <? super T > filter)
{
int i = MathHelper.floor_double((aabb.minX - MAX_ENTITY_RADIUS) / 16.0D);
int j = MathHelper.ceiling_double_int((aabb.maxX + MAX_ENTITY_RADIUS) / 16.0D);
int k = MathHelper.floor_double((aabb.minZ - MAX_ENTITY_RADIUS) / 16.0D);
int l = MathHelper.ceiling_double_int((aabb.maxZ + MAX_ENTITY_RADIUS) / 16.0D);
List<T> list = Lists.<T>newArrayList();
for (int i1 = i; i1 < j; ++i1)
{
for (int j1 = k; j1 < l; ++j1)
{
if (this.isChunkLoaded(i1, j1, true))
{
this.getChunkFromChunkCoords(i1, j1).getEntitiesOfTypeWithinAAAB(clazz, aabb, list, filter);
}
}
}
return list;
}To solve the bug, the method must be able to quickly determine whether it will be more efficient to loop through all possible chunks in the area (and then check if they are loaded) or through all loaded chunks (and then check if they are in the area), and then to loop through the loaded chunks if that is the decision. Therefore I suggest adding two methods to IChunkProvider: getNumLoadedChunks() and iterLoadedChunks(), both of which should be trivial to implement.
The new method:
public <T extends Entity> List<T> getEntitiesWithinAABB(Class <? extends T > clazz, AxisAlignedBB aabb, @Nullable Predicate <? super T > filter)
{
int i = MathHelper.floor_double((aabb.minX - MAX_ENTITY_RADIUS) / 16.0D);
int j = MathHelper.ceiling_double_int((aabb.maxX + MAX_ENTITY_RADIUS) / 16.0D);
int k = MathHelper.floor_double((aabb.minZ - MAX_ENTITY_RADIUS) / 16.0D);
int l = MathHelper.ceiling_double_int((aabb.maxZ + MAX_ENTITY_RADIUS) / 16.0D);
List<T> list = Lists.<T>newArrayList();
int chunksInAABB = (j - i) * (l - k);
if (chunksInAABB > this.chunkProvider.getNumLoadedChunks())
{
for (Chunk chunk : this.chunkProvider.iterLoadedChunks())
{
if (chunk.xPosition >= i && chunk.xPosition < j && chunk.zPosition >= k && chunk.zPosition < l)
{
chunk.getEntitiesOfTypeWithinAAAB(clazz, aabb, list, filter);
}
}
}
else
{
for (int i1 = i; i1 < j; ++i1)
{
for (int j1 = k; j1 < l; ++j1)
{
if (this.isChunkLoaded(i1, j1, true))
{
this.getChunkFromChunkCoords(i1, j1).getEntitiesOfTypeWithinAAAB(clazz, aabb, list, filter);
}
}
}
}
return list;
}This way the function will have exactly the same input and output, but will never check more chunks than are actually loaded.
Can confirm in 24w06a.
@@unknown Eight-year-old comment, but it seems to me that the "correct" solution would be to do attribute application in two passes. First, go over all the slots as you described, but only process item removals. Then go over all the slots a second time and process all the item additions.