rscache/definition/osrs/
item_def.rs

1use std::{collections::HashMap, io, io::BufReader};
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use super::Definition;
7use crate::{extension::ReadExt, util};
8
9/// Contains all the information about a certain item fetched from the cache through
10/// the [ItemLoader](../../loader/osrs/struct.ItemLoader.html).
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[derive(Clone, Eq, PartialEq, Debug, Default)]
13pub struct ItemDefinition {
14    pub id: u16,
15    pub name: String,
16    pub stackable: bool,
17    pub cost: i32,
18    pub members_only: bool,
19    pub options: [String; 5],
20    pub interface_options: [String; 5],
21    pub tradable: bool,
22    pub noted_id: Option<u16>,
23    pub noted_template: Option<u16>,
24    pub stack_ids: Option<[u16; 10]>,
25    pub stack_count: Option<[u16; 10]>,
26    pub team: u8,
27    pub bought_link: Option<u16>,
28    pub bought_tempalte: Option<u16>,
29    pub shift_click_drop_index: Option<u8>,
30    pub params: HashMap<u32, String>,
31    pub inventory_model_data: InventoryModelData,
32    pub character_model_data: CharacterModelData,
33}
34
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
37pub struct InventoryModelData {
38    pub inventory_model: u16,
39    pub zoom2d: u16,
40    pub x_an2d: u16,
41    pub y_an2d: u16,
42    pub z_an2d: u16,
43    pub x_offset2d: u16,
44    pub y_offset2d: u16,
45    pub resize_x: u16,
46    pub resize_y: u16,
47    pub resize_z: u16,
48    pub color_find: Vec<u16>,
49    pub color_replace: Vec<u16>,
50    pub texture_find: Vec<u16>,
51    pub texture_replace: Vec<u16>,
52    pub ambient: i8,
53    pub contrast: i8,
54}
55
56#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
57#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
58pub struct CharacterModelData {
59    pub male_model10: Option<u16>,
60    pub male_model_offset: u8,
61    pub male_model1: Option<u16>,
62    pub female_model10: Option<u16>,
63    pub female_model_offset: u8,
64    pub female_model1: Option<u16>,
65    pub male_model12: Option<u16>,
66    pub female_model12: Option<u16>,
67    pub male_head_model1: Option<u16>,
68    pub female_head_model1: Option<u16>,
69    pub male_head_model2: Option<u16>,
70    pub female_head_model2: Option<u16>,
71}
72
73impl Definition for ItemDefinition {
74    fn new(id: u16, buffer: &[u8]) -> crate::Result<Self> {
75        let mut reader = BufReader::new(buffer);
76        let item_def = decode_buffer(id, &mut reader)?;
77
78        Ok(item_def)
79    }
80}
81
82fn decode_buffer(id: u16, reader: &mut BufReader<&[u8]>) -> io::Result<ItemDefinition> {
83    let mut item_def = ItemDefinition {
84        id,
85        inventory_model_data: InventoryModelData {
86            resize_x: 128,
87            resize_y: 128,
88            resize_z: 128,
89            zoom2d: 2000,
90            ..InventoryModelData::default()
91        },
92        options: [
93            "".to_string(),
94            "".to_string(),
95            "Take".to_string(),
96            "".to_string(),
97            "".to_string(),
98        ],
99        interface_options: [
100            "".to_string(),
101            "".to_string(),
102            "".to_string(),
103            "".to_string(),
104            "Drop".to_string(),
105        ],
106        ..ItemDefinition::default()
107    };
108
109    loop {
110        let opcode = reader.read_u8()?;
111
112        match opcode {
113            0 => break,
114            1 => {
115                item_def.inventory_model_data.inventory_model = reader.read_u16()?;
116            }
117            2 => {
118                item_def.name = reader.read_string()?;
119            }
120            4 => {
121                item_def.inventory_model_data.zoom2d = reader.read_u16()?;
122            }
123            5 => {
124                item_def.inventory_model_data.x_an2d = reader.read_u16()?;
125            }
126            6 => {
127                item_def.inventory_model_data.y_an2d = reader.read_u16()?;
128            }
129            7 => {
130                item_def.inventory_model_data.x_offset2d = reader.read_u16()?;
131            }
132            8 => {
133                item_def.inventory_model_data.y_offset2d = reader.read_u16()?;
134            }
135            11 => {
136                item_def.stackable = true;
137            }
138            12 => {
139                item_def.cost = reader.read_i32()?;
140            }
141            16 => item_def.members_only = true,
142            23 => {
143                item_def.character_model_data.male_model10 = Some(reader.read_u16()?);
144                item_def.character_model_data.male_model_offset = reader.read_u8()?;
145            }
146            24 => {
147                item_def.character_model_data.male_model1 = Some(reader.read_u16()?);
148            }
149            25 => {
150                item_def.character_model_data.female_model10 = Some(reader.read_u16()?);
151                item_def.character_model_data.female_model_offset = reader.read_u8()?;
152            }
153            26 => {
154                item_def.character_model_data.female_model1 = Some(reader.read_u16()?);
155            }
156            30..=34 => {
157                item_def.options[opcode as usize - 30] = reader.read_string()?;
158            }
159            35..=39 => {
160                item_def.interface_options[opcode as usize - 35] = reader.read_string()?;
161            }
162            40 => {
163                let len = reader.read_u8()? as usize;
164                item_def.inventory_model_data.color_find = Vec::with_capacity(len);
165                item_def.inventory_model_data.color_replace = Vec::with_capacity(len);
166                for _ in 0..len {
167                    item_def
168                        .inventory_model_data
169                        .color_find
170                        .push(reader.read_u16()?);
171                    item_def
172                        .inventory_model_data
173                        .color_replace
174                        .push(reader.read_u16()?);
175                }
176            }
177            41 => {
178                let len = reader.read_u8()? as usize;
179                item_def.inventory_model_data.texture_find = Vec::with_capacity(len);
180                item_def.inventory_model_data.texture_replace = Vec::with_capacity(len);
181                for _ in 0..len {
182                    item_def
183                        .inventory_model_data
184                        .texture_find
185                        .push(reader.read_u16()?);
186                    item_def
187                        .inventory_model_data
188                        .texture_replace
189                        .push(reader.read_u16()?);
190                }
191            }
192            42 => {
193                item_def.shift_click_drop_index = Some(reader.read_u8()?);
194            }
195            65 => {
196                item_def.tradable = true;
197            }
198            78 => {
199                item_def.character_model_data.male_model12 = Some(reader.read_u16()?);
200            }
201            79 => {
202                item_def.character_model_data.female_model12 = Some(reader.read_u16()?);
203            }
204            90 => {
205                item_def.character_model_data.male_head_model1 = Some(reader.read_u16()?);
206            }
207            91 => {
208                item_def.character_model_data.female_head_model1 = Some(reader.read_u16()?);
209            }
210            92 => {
211                item_def.character_model_data.male_head_model2 = Some(reader.read_u16()?);
212            }
213            93 => {
214                item_def.character_model_data.female_head_model2 = Some(reader.read_u16()?);
215            }
216            95 => {
217                item_def.inventory_model_data.z_an2d = reader.read_u16()?;
218            }
219            97 => {
220                item_def.noted_id = Some(reader.read_u16()?);
221            }
222            98 => {
223                item_def.noted_template = Some(reader.read_u16()?);
224                item_def.stackable = true;
225            }
226            100..=109 => {
227                item_def.stack_ids = Some([0; 10]);
228                item_def.stack_count = Some([0; 10]);
229                match item_def.stack_ids {
230                    Some(mut stack_ids) => {
231                        stack_ids[opcode as usize - 100] = reader.read_u16()?;
232                    }
233                    _ => unreachable!(),
234                }
235                match item_def.stack_count {
236                    Some(mut stack_count) => {
237                        stack_count[opcode as usize - 100] = reader.read_u16()?;
238                    }
239                    _ => unreachable!(),
240                }
241            }
242            110 => {
243                item_def.inventory_model_data.resize_x = reader.read_u16()?;
244            }
245            111 => {
246                item_def.inventory_model_data.resize_y = reader.read_u16()?;
247            }
248            112 => {
249                item_def.inventory_model_data.resize_z = reader.read_u16()?;
250            }
251            113 => {
252                item_def.inventory_model_data.ambient = reader.read_i8()?;
253            }
254            114 => {
255                item_def.inventory_model_data.contrast = reader.read_i8()?;
256            }
257            115 => {
258                item_def.team = reader.read_u8()?;
259            }
260            139 => {
261                item_def.bought_link = Some(reader.read_u16()?);
262            }
263            140 => {
264                item_def.bought_tempalte = Some(reader.read_u16()?);
265            }
266            148 | 149 => {
267                reader.read_u16()?;
268            }
269            249 => {
270                item_def.params = util::read_parameters(reader)?;
271            }
272            _ => unreachable!(),
273        }
274    }
275
276    Ok(item_def)
277}