1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use bytes::{Buf, Bytes};
use ndarray::{Array, ArrayBase, Dim, OwnedRepr};
#[cfg(feature = "pyo3")]
use pyo3::prelude::*;
use rs3cache_backend::buf::BufExtra;
#[cfg(any(feature = "osrs", feature = "legacy"))]
use rs3cache_backend::buf::ReadError;
use serde::Serialize;
pub type TileArray = ArrayBase<OwnedRepr<Tile>, Dim<[usize; 3]>>;
#[cfg_attr(feature = "pyo3", pyclass(frozen, get_all))]
#[derive(Default, Debug, Copy, Clone, Serialize)]
pub struct Tile {
pub shape: Option<u8>,
pub overlay_id: Option<u16>,
pub settings: Option<u8>,
pub underlay_id: Option<u16>,
pub height: Option<u8>,
}
impl Tile {
#[cfg(any(feature = "rs3", feature = "2013_shim"))]
pub fn dump(buffer: &mut Bytes) -> TileArray {
Array::from_shape_simple_fn((4, 64, 64), || {
let mut tile = Tile::default();
let [flag_1, flag_2, flag_3, flag_4, ..] = buffer.get_bitflags();
if flag_1 {
tile.shape = Some(buffer.get_u8());
tile.overlay_id = Some(buffer.get_unsigned_smart());
}
if flag_2 {
tile.settings = Some(buffer.get_u8());
}
if flag_3 {
tile.underlay_id = Some(buffer.get_unsigned_smart());
}
if flag_4 {
tile.height = Some(buffer.get_u8());
}
tile
})
}
#[cfg(feature = "legacy")]
pub fn dump(buffer: &mut Bytes) -> TileArray {
let shape = Self::try_dump(buffer.clone(), false).unwrap();
Array::from_shape_vec((4, 64, 64), shape).unwrap()
}
#[cfg(all(feature = "osrs", not(feature = "2013_shim")))]
pub fn dump(buffer: &mut Bytes) -> TileArray {
let shape = match Self::try_dump(buffer.clone(), true) {
Ok(shape) => shape,
Err(_) => Self::try_dump(buffer.clone(), false).unwrap(),
};
Array::from_shape_vec((4, 64, 64), shape).unwrap()
}
#[cfg(any(feature = "osrs", feature = "legacy"))]
fn try_dump(mut buffer: Bytes, use_post_oct_2022: bool) -> Result<Vec<Tile>, ReadError> {
let producer = || try {
let mut tile = Tile::default();
loop {
let opcode = if use_post_oct_2022 {
buffer.try_get_u16()?
} else {
buffer.try_get_u8()? as u16
};
match opcode {
0 => break tile,
1 => {
tile.height = Some(buffer.try_get_u8()?);
break tile;
}
opcode @ 2..=49 => {
tile.shape = Some(opcode as u8 - 2);
let id = if use_post_oct_2022 {
buffer.try_get_u16()?
} else {
buffer.try_get_u8()? as u16
};
tile.overlay_id = Some(id);
}
opcode @ 50..=81 => tile.settings = Some(opcode as u8 - 49),
opcode @ 82.. => tile.underlay_id = Some(opcode - 81),
}
}
};
let ret = std::iter::repeat_with(producer).take(4 * 64 * 64).collect();
if buffer.is_empty() {
ret
} else {
Err(rs3cache_backend::buf::NotExhausted::new(buffer.remaining()))
}
}
}