osrscache/definition/osrs/
map_def.rs1use 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#[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}