rsmod-pathfinder 5.0.4

A breadth-first search path finder.
Documentation
use crate::rsmod::block_flag::BlockAccessFlag;
use crate::rsmod::collision::collision::CollisionFlagMap;
use crate::rsmod::collision_flag::CollisionFlag;

#[inline(always)]
pub fn collides(
    src_x: i32,
    src_z: i32,
    dest_x: i32,
    dest_z: i32,
    src_width: u8,
    src_height: u8,
    dest_width: u8,
    dest_height: u8,
) -> bool {
    return if src_x >= dest_x + dest_width as i32 || src_x + src_width as i32 <= dest_x {
        false
    } else {
        src_z < dest_z + dest_height as i32 && dest_z < src_height as i32 + src_z
    };
}

#[inline(always)]
pub unsafe fn reach_rectangle_1(
    flags: &CollisionFlagMap,
    y: i32,
    src_x: i32,
    src_z: i32,
    dest_x: i32,
    dest_z: i32,
    dest_width: u8,
    dest_height: u8,
    block_access_flags: u8,
) -> bool {
    let east: i32 = dest_x + dest_width as i32 - 1;
    let north: i32 = dest_z + dest_height as i32 - 1;

    if src_x == dest_x - 1
        && src_z >= dest_z
        && src_z <= north
        && (flags.get(src_x, src_z, y) & CollisionFlag::WALL_EAST as u32)
            == CollisionFlag::OPEN as u32
        && (block_access_flags & BlockAccessFlag::BLOCK_WEST) == 0
    {
        return true;
    }

    if src_x == east + 1
        && src_z >= dest_z
        && src_z <= north
        && (flags.get(src_x, src_z, y) & CollisionFlag::WALL_WEST as u32)
            == CollisionFlag::OPEN as u32
        && (block_access_flags & BlockAccessFlag::BLOCK_EAST) == 0
    {
        return true;
    }

    if src_z + 1 == dest_z
        && src_x >= dest_x
        && src_x <= east
        && (flags.get(src_x, src_z, y) & CollisionFlag::WALL_NORTH as u32)
            == CollisionFlag::OPEN as u32
        && (block_access_flags & BlockAccessFlag::BLOCK_SOUTH) == 0
    {
        return true;
    }

    return src_z == north + 1
        && src_x >= dest_x
        && src_x <= east
        && (flags.get(src_x, src_z, y) & CollisionFlag::WALL_SOUTH as u32)
            == CollisionFlag::OPEN as u32
        && (block_access_flags & BlockAccessFlag::BLOCK_NORTH) == 0;
}

#[inline(always)]
pub unsafe fn reach_rectangle_n(
    flags: &CollisionFlagMap,
    y: i32,
    src_x: i32,
    src_z: i32,
    dest_x: i32,
    dest_z: i32,
    src_width: u8,
    src_height: u8,
    dest_width: u8,
    dest_height: u8,
    block_access_flags: u8,
) -> bool {
    let src_east: i32 = src_x + src_width as i32;
    let src_north: i32 = src_height as i32 + src_z;
    let dest_east: i32 = dest_width as i32 + dest_x;
    let dest_north: i32 = dest_height as i32 + dest_z;

    if dest_east == src_x && (block_access_flags & BlockAccessFlag::BLOCK_EAST) == 0 {
        let from_z: i32 = src_z.max(dest_z);
        let to_z: i32 = src_north.min(dest_north);
        for side_z in from_z..to_z {
            if (flags.get(dest_east - 1, side_z, y) & CollisionFlag::WALL_EAST as u32)
                == CollisionFlag::OPEN as u32
            {
                return true;
            }
        }
    } else if src_east == dest_x && (block_access_flags & BlockAccessFlag::BLOCK_WEST) == 0 {
        let from_z: i32 = src_z.max(dest_z);
        let to_z: i32 = src_north.min(dest_north);
        for side_z in from_z..to_z {
            if (flags.get(dest_x, side_z, y) & CollisionFlag::WALL_WEST as u32)
                == CollisionFlag::OPEN as u32
            {
                return true;
            }
        }
    } else if src_z == dest_north && (block_access_flags & BlockAccessFlag::BLOCK_NORTH) == 0 {
        let from_x: i32 = src_x.max(dest_x);
        let to_x: i32 = src_east.min(dest_east);
        for side_x in from_x..to_x {
            if (flags.get(side_x, dest_north - 1, y) & CollisionFlag::WALL_NORTH as u32)
                == CollisionFlag::OPEN as u32
            {
                return true;
            }
        }
    } else if dest_z == src_north && (block_access_flags & BlockAccessFlag::BLOCK_SOUTH) == 0 {
        let from_x: i32 = src_x.max(dest_x);
        let to_x: i32 = src_east.min(dest_east);
        for side_x in from_x..to_x {
            if (flags.get(side_x, dest_z, y) & CollisionFlag::WALL_SOUTH as u32)
                == CollisionFlag::OPEN as u32
            {
                return true;
            }
        }
    }
    return false;
}