mojira.dev
MC-250027

Allays ignore the dimension when checking for liked note blocks

The bug

Allays do not check the dimension of the liked note block. If multiple dimensions have note blocks at the same coordinates, allays will deliver items to any of these.

Steps to Reproduce

  1. Place note blocks in multiple dimensions at the same coordinates

  2. Spawn an allay

  3. Have it hold an item

  4. (Optionally) run /data modify entity @e[type=minecraft:allay,limit=1] Brain.memories.minecraft:liked_noteblock_cooldown_ticks.value set value 100000 to increase cooldown for easier testing

  5. Play the note block in one dimension

  6. Teleport the allay to the other dimension e.g. via nether portals

  7. Drop items and have the allay pick it up

  8. Check whether the allay drops the items at the note block or the player

Expected Result

The allay will bring the item to the player, because the allay is linked to the note block in a different dimension.

Actual Result

The allay will drop the item at the note block.

Code Analysis

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

Comments 1

Can Confirm

Code Analysis: (MojMap - 22w14a)

So this is actually quite funny. The Allay is using a GlobalPos for the position of the Noteblock, a global pos holds both a dimension & a blockpos. Although in the code, the allay never checks the dimension.

net/minecraft/world/entity/animal/allay/AllayAi.java

private static Optional<PositionTracker> getItemDepositPosition(LivingEntity entity) {
    Brain<?> brain = entity.getBrain();
    Optional<GlobalPos> optGlobalPos = brain.getMemory(LIKED_NOTEBLOCK_POSITION);
    if (optGlobalPos.isPresent()) {
        BlockPos blockPos = optGlobalPos.get().pos(); //Dimension not used
        if (shouldDepositItemsAtLikedNoteblock(entity, brain, blockPos)) {
            return Optional.of(new BlockPosTracker(blockPos.above()));
        }
        lvt1.eraseMemory(MemoryModuleType.LIKED_NOTEBLOCK_POSITION);
    }
    return getLikedPlayerPositionTracker(entity);
}
private static boolean shouldDepositItemsAtLikedNoteblock(LivingEntity entity, Brain<?> brain, BlockPos pos) {
    Optional<Integer> optCooldown = brain.getMemory(LIKED_NOTEBLOCK_COOLDOWN_TICKS);
    return entity.getLevel().getBlockState(pos).is(Blocks.NOTE_BLOCK) && optCooldown .isPresent();
}

To fix this is pretty easy, pass the globalPos into `shouldDepositItemsAtLikedNoteblock`

Possible Fix:

net/minecraft/world/entity/animal/allay/AllayAi.java

private static Optional<PositionTracker> getItemDepositPosition(LivingEntity entity) {
    Brain<?> brain = entity.getBrain();
    Optional<GlobalPos> optGlobalPos = brain.getMemory(LIKED_NOTEBLOCK_POSITION);
    if (optGlobalPos.isPresent()) {
        GlobalPos globalPos = optGlobalPos.get();
        if (shouldDepositItemsAtLikedNoteblock(entity, brain, globalPos)) {
            return Optional.of(new BlockPosTracker(globalPos.pos().above()));
        }
        lvt1.eraseMemory(MemoryModuleType.LIKED_NOTEBLOCK_POSITION);
    }
    return getLikedPlayerPositionTracker(entity);
}
private static boolean shouldDepositItemsAtLikedNoteblock(LivingEntity entity, Brain<?> brain, GlobalPos pos) {
    if (!Objects.equals(entity.getLevel().dimension(), pos.dimension())) {
        return false;
    }
    Optional<Integer> optCooldown = brain.getMemory(LIKED_NOTEBLOCK_COOLDOWN_TICKS);
    return entity.getLevel().getBlockState(pos.pos()).is(Blocks.NOTE_BLOCK) && optCooldown.isPresent();
}

Here we just make sure that the allay is in the same dimension as the noteblock

apple502j

elvendorke

Community Consensus

Normal

Mob behaviour

allay

22w14a

22w17a

Retrieved