Okay, that seems to work. Shame there's not a more efficient way to do it. For reference, here's the working code:
private static final UUID saplingSlowUUID = UUID.fromString("83BD3C05-50EB-460B-8961-615633A6D813");
// -0.2D with operation 1 corresponds to a 0.8x speed multiplier.
private static final AttributeModifier saplingSlow = new AttributeModifier(saplingSlowUUID, "SAPLING_SLOW", -0.2D, 1);
@SubscribeEvent
public static void onPlayerTick(TickEvent.PlayerTickEvent playerTickEvent) {
if (playerTickEvent.side == LogicalSide.SERVER) {
EntityPlayer player = playerTickEvent.player;
World world = player.getEntityWorld();
// Get all blocks that any part of the player model is colliding with.
Iterable<BlockPos.MutableBlockPos> playerColliding = BlockPos.getAllInBoxMutable(
(int) Math.floor(player.posX - (player.width / 2)),
(int) Math.floor(player.posY - (player.height / 2)),
(int) Math.floor(player.posZ - (player.width / 2)),
(int) Math.floor(player.posX + (player.width / 2)),
(int) Math.floor(player.posY + (player.height / 2)),
(int) Math.floor(player.posZ + (player.width / 2))
);
boolean shouldSlow = false;
for (BlockPos bp : playerColliding) {
shouldSlow |= world.getBlockState(bp).getBlock() instanceof BlockSapling;
}
IAttributeInstance movement = playerTickEvent.player.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED);
if (shouldSlow) {
// Add modifier, if it's not already applied
if (!movement.hasModifier(saplingSlow)) {
movement.applyModifier(saplingSlow);
}
} else {
// Remove modifier, if it exists
if (movement.hasModifier(saplingSlow)) {
movement.removeModifier(saplingSlow);
}
}
}
}
// [Elsewhere, in some register event]
MinecraftForge.EVENT_BUS.register(BlockSapling.class);
Thanks for the help. If anyone has a better way to do this, please let me know.