rscache/definition/rs3/
item_def.rs

1use std::{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/rs3/struct.ItemLoader.html).
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
13pub struct ItemDefinition {
14    pub id: u32,
15    pub model_data: ModelData,
16    pub name: String,
17    pub stackable: bool,
18    pub cost: i32,
19    pub members_only: bool,
20    pub options: [String; 5],
21    pub interface_options: [String; 5],
22    pub unnoted: bool,
23    // might give this an enum
24    pub equip_slot: u8,
25    pub equip_hide_slot1: u8,
26    pub equip_hide_slot2: u8,
27    pub noted_id: Option<u16>,
28    pub noted_template: Option<u16>,
29    pub stack_ids: Option<[u16; 10]>,
30    pub stack_count: Option<[u16; 10]>,
31    pub team: u8,
32    pub lend_id: Option<u16>,
33    pub lend_tempalte: Option<u16>,
34    pub lent: bool,
35    pub bind_link: Option<u16>,
36    pub bind_tempalte: Option<u16>,
37}
38
39#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
40#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
41pub struct ModelData {
42    pub id: u32,
43    pub zoom: u16,
44    pub rotation1: u16,
45    pub rotation2: u16,
46    pub offset1: u16,
47    pub offset2: u16,
48    pub male_equip_id: u32,
49    pub female_equip_id: u32,
50    pub male_equip1: u32,
51    pub male_equip2: u32,
52    pub female_equip1: u32,
53    pub female_equip2: u32,
54    pub original_colors: Vec<u16>,
55    pub modified_colors: Vec<u16>,
56    pub original_texture_colors: Vec<u16>,
57    pub modified_texture_colors: Vec<u16>,
58}
59
60impl Definition for ItemDefinition {
61    fn new(id: u32, buffer: &[u8]) -> crate::Result<Self> {
62        let mut reader = BufReader::new(buffer);
63        let item_def = decode_buffer(id, &mut reader)?;
64
65        Ok(item_def)
66    }
67}
68
69fn decode_buffer(id: u32, reader: &mut BufReader<&[u8]>) -> io::Result<ItemDefinition> {
70    let mut item_def = ItemDefinition {
71        id,
72        options: [
73            "".to_string(),
74            "".to_string(),
75            "Take".to_string(),
76            "".to_string(),
77            "".to_string(),
78        ],
79        interface_options: [
80            "".to_string(),
81            "".to_string(),
82            "".to_string(),
83            "".to_string(),
84            "Drop".to_string(),
85        ],
86        ..ItemDefinition::default()
87    };
88
89    loop {
90        let opcode = reader.read_u8()?;
91
92        match opcode {
93            0 => break,
94            1 => {
95                item_def.model_data.id = reader.read_smart()?;
96            }
97            2 => {
98                item_def.name = reader.read_string()?;
99            }
100            4 => {
101                item_def.model_data.zoom = reader.read_u16()?;
102            }
103            5 => {
104                item_def.model_data.rotation1 = reader.read_u16()?;
105            }
106            6 => {
107                item_def.model_data.rotation2 = reader.read_u16()?;
108            }
109            7 => {
110                item_def.model_data.offset1 = reader.read_u16()?;
111            }
112            8 => {
113                item_def.model_data.offset2 = reader.read_u16()?;
114            }
115            11 => item_def.stackable = true,
116            12 => {
117                item_def.cost = reader.read_i32()?;
118            }
119            13 => {
120                item_def.equip_slot = reader.read_u8()?;
121            }
122            14 => {
123                item_def.equip_hide_slot1 = reader.read_u8()?;
124            }
125            16 => item_def.members_only = true,
126            23 => {
127                item_def.model_data.male_equip1 = reader.read_smart()?;
128            }
129            24 => {
130                item_def.model_data.male_equip2 = reader.read_smart()?;
131            }
132            25 => {
133                item_def.model_data.female_equip1 = reader.read_smart()?;
134            }
135            26 => {
136                item_def.model_data.female_equip2 = reader.read_smart()?;
137            }
138            27 => {
139                item_def.equip_hide_slot2 = reader.read_u8()?;
140            }
141            30..=34 => {
142                item_def.options[opcode as usize - 30] = reader.read_string()?;
143            }
144            35..=39 => {
145                item_def.interface_options[opcode as usize - 35] = reader.read_string()?;
146            }
147            40 => {
148                let len = reader.read_u8()? as usize;
149                item_def.model_data.original_colors = Vec::with_capacity(len);
150                item_def.model_data.modified_colors = Vec::with_capacity(len);
151                for _ in 0..len {
152                    item_def.model_data.original_colors.push(reader.read_u16()?);
153                    item_def.model_data.modified_colors.push(reader.read_u16()?);
154                }
155            }
156            41 => {
157                let len = reader.read_u8()? as usize;
158                item_def.model_data.original_texture_colors = Vec::with_capacity(len);
159                item_def.model_data.original_texture_colors = Vec::with_capacity(len);
160                for _ in 0..len {
161                    item_def
162                        .model_data
163                        .original_texture_colors
164                        .push(reader.read_u16()?);
165                    item_def
166                        .model_data
167                        .original_texture_colors
168                        .push(reader.read_u16()?);
169                }
170            }
171            42 => {
172                let len = reader.read_u8()?;
173                for _ in 0..len {
174                    reader.read_u8()?;
175                }
176            }
177            65 => {
178                item_def.unnoted = true;
179            }
180            78 => {
181                item_def.model_data.male_equip_id = reader.read_smart()?;
182            }
183            79 => {
184                item_def.model_data.female_equip_id = reader.read_smart()?;
185            }
186            97 => {
187                item_def.noted_id = Some(reader.read_u16()?);
188            }
189            98 => {
190                item_def.noted_template = Some(reader.read_u16()?);
191                item_def.stackable = true;
192            }
193            100..=109 => {
194                item_def.stack_ids = Some([0; 10]);
195                item_def.stack_count = Some([0; 10]);
196                match item_def.stack_ids {
197                    Some(mut stack_ids) => {
198                        stack_ids[opcode as usize - 100] = reader.read_u16()?;
199                    }
200                    _ => unreachable!(),
201                }
202                match item_def.stack_count {
203                    Some(mut stack_count) => {
204                        stack_count[opcode as usize - 100] = reader.read_u16()?;
205                    }
206                    _ => unreachable!(),
207                }
208            }
209            115 => {
210                item_def.team = reader.read_u8()?;
211            }
212            121 => {
213                item_def.lend_id = Some(reader.read_u16()?);
214                item_def.interface_options[4] = "Discard".to_owned();
215                item_def.lent = true;
216            }
217            122 => {
218                item_def.lend_tempalte = Some(reader.read_u16()?);
219            }
220            125 | 126 => {
221                reader.read_u8()?;
222                reader.read_u8()?;
223                reader.read_u8()?;
224            }
225            127..=130 => {
226                reader.read_u8()?;
227                reader.read_u16()?;
228            }
229            132 => {
230                let len = reader.read_u8()?;
231                for _ in 0..len {
232                    reader.read_u16()?;
233                }
234            }
235            139 => {
236                item_def.bind_link = Some(reader.read_u16()?);
237                item_def.interface_options[4] = "Destroy".to_owned();
238            }
239            140 => {
240                item_def.bind_tempalte = Some(reader.read_u16()?);
241            }
242            164 => {
243                reader.read_string()?;
244            }
245            251 | 252 => {
246                let len = reader.read_u8()?;
247                for _ in 0..len {
248                    reader.read_u16()?;
249                    reader.read_u16()?;
250                }
251            }
252            249 => {
253                util::read_parameters(reader)?;
254            }
255            15 | 156 | 157 | 165 | 167 => {}
256            96 | 113 | 114 | 134 => {
257                reader.read_u8()?;
258            }
259            18 | 44 | 45 | 94 | 95 | 110..=112 | 142..=146 | 150..=154 | 161..=163 => {
260                reader.read_u16()?;
261            }
262            90..=93 | 242..=248 => {
263                reader.read_smart()?;
264            }
265            _ => {
266                println!("{} {}", id, opcode);
267                unreachable!()
268            }
269        }
270    }
271
272    Ok(item_def)
273}