osrscache/definition/osrs/
map_def.rs

1use std::{io, io::BufReader};
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use super::Definition;
7use crate::extension::ReadExt;
8
9const X: usize = 64;
10const Y: usize = 64;
11const Z: usize = 4;
12
13/// Contains all the information about a certain map fetched from the cache through
14/// the [MapLoader](../../loader/osrs/struct.MapLoader.html).
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
17pub struct MapDefinition {
18    pub region_x: u16,
19    pub region_y: u16,
20    pub data: Vec<Vec<Vec<MapData>>>,
21}
22
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
25pub struct MapData {
26    pub height: u8,
27    pub attr_opcode: u8,
28    pub settings: u8,
29    pub overlay_id: i8,
30    pub overlay_path: u8,
31    pub overlay_rotation: u8,
32    pub underlay_id: u8,
33}
34
35impl Definition for MapDefinition {
36    fn new(id: u16, buffer: &[u8]) -> crate::Result<Self> {
37        let x = id >> 8;
38        let y = id & 0xFF;
39
40        let mut reader = BufReader::new(buffer);
41        let map_def = decode_buffer(x, y, &mut reader)?;
42
43        Ok(map_def)
44    }
45}
46
47impl MapDefinition {
48    pub fn map_data(&self, x: usize, y: usize, z: usize) -> &MapData {
49        &self.data[z][x][y]
50    }
51
52    #[inline]
53    pub const fn region_base_coords(&self) -> (u16, u16) {
54        (self.region_x << 6, self.region_y << 6)
55    }
56
57    pub fn blocked_tiles(&self) -> Vec<(u16, u16, u16)> {
58        let region_base_x = self.region_x << 6;
59        let region_base_y = self.region_y << 6;
60        let mut blocked_tiles = Vec::new();
61
62        for z in 0..Z {
63            for x in 0..X {
64                for y in 0..Y {
65                    let map_data = &self.data[z][x][y];
66
67                    if map_data.settings & 1 == 1 {
68                        blocked_tiles.push((
69                            region_base_x + x as u16,
70                            region_base_y + y as u16,
71                            z as u16,
72                        ));
73                    }
74                }
75            }
76        }
77
78        blocked_tiles
79    }
80}
81
82fn decode_buffer(x: u16, y: u16, reader: &mut BufReader<&[u8]>) -> io::Result<MapDefinition> {
83    let mut map_def = MapDefinition {
84        region_x: x,
85        region_y: y,
86        data: vec![vec![vec![MapData::default(); X]; Y]; Z],
87    };
88
89    for z in 0..Z {
90        for x in 0..X {
91            for y in 0..Y {
92                let map_data = &mut map_def.data[z][x][y];
93
94                loop {
95                    let attribute = reader.read_u8()?;
96
97                    match attribute {
98                        0 => break,
99                        1 => {
100                            map_data.height = reader.read_u8()?;
101                            break;
102                        }
103                        2..=49 => {
104                            map_data.attr_opcode = attribute;
105                            map_data.overlay_id = reader.read_i8()?;
106                            map_data.overlay_path = (attribute - 2) / 4;
107                            map_data.overlay_rotation = (attribute - 2) & 3;
108                        }
109                        50..=81 => {
110                            map_data.settings = attribute - 49;
111                        }
112                        _ => map_data.underlay_id = attribute - 81,
113                    }
114                }
115            }
116        }
117    }
118
119    Ok(map_def)
120}