use std::{io, io::BufReader};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use super::Definition;
use crate::{extension::ReadExt, util};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct ItemDefinition {
pub id: u32,
pub model_data: ModelData,
pub name: String,
pub stackable: bool,
pub cost: i32,
pub members_only: bool,
pub options: [String; 5],
pub interface_options: [String; 5],
pub unnoted: bool,
pub equip_slot: u8,
pub equip_hide_slot1: u8,
pub equip_hide_slot2: u8,
pub noted_id: Option<u16>,
pub noted_template: Option<u16>,
pub stack_ids: Option<[u16; 10]>,
pub stack_count: Option<[u16; 10]>,
pub team: u8,
pub lend_id: Option<u16>,
pub lend_tempalte: Option<u16>,
pub lent: bool,
pub bind_link: Option<u16>,
pub bind_tempalte: Option<u16>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct ModelData {
pub id: u32,
pub zoom: u16,
pub rotation1: u16,
pub rotation2: u16,
pub offset1: u16,
pub offset2: u16,
pub male_equip_id: u32,
pub female_equip_id: u32,
pub male_equip1: u32,
pub male_equip2: u32,
pub female_equip1: u32,
pub female_equip2: u32,
pub original_colors: Vec<u16>,
pub modified_colors: Vec<u16>,
pub original_texture_colors: Vec<u16>,
pub modified_texture_colors: Vec<u16>,
}
impl Definition for ItemDefinition {
fn new(id: u32, buffer: &[u8]) -> crate::Result<Self> {
let mut reader = BufReader::new(buffer);
let item_def = decode_buffer(id, &mut reader)?;
Ok(item_def)
}
}
fn decode_buffer(id: u32, reader: &mut BufReader<&[u8]>) -> io::Result<ItemDefinition> {
let mut item_def = ItemDefinition {
id,
options: [
"".to_string(),
"".to_string(),
"Take".to_string(),
"".to_string(),
"".to_string(),
],
interface_options: [
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
"Drop".to_string(),
],
..ItemDefinition::default()
};
loop {
let opcode = reader.read_u8()?;
match opcode {
0 => break,
1 => {
item_def.model_data.id = reader.read_smart()?;
}
2 => {
item_def.name = reader.read_string()?;
}
4 => {
item_def.model_data.zoom = reader.read_u16()?;
}
5 => {
item_def.model_data.rotation1 = reader.read_u16()?;
}
6 => {
item_def.model_data.rotation2 = reader.read_u16()?;
}
7 => {
item_def.model_data.offset1 = reader.read_u16()?;
}
8 => {
item_def.model_data.offset2 = reader.read_u16()?;
}
11 => item_def.stackable = true,
12 => {
item_def.cost = reader.read_i32()?;
}
13 => {
item_def.equip_slot = reader.read_u8()?;
}
14 => {
item_def.equip_hide_slot1 = reader.read_u8()?;
}
16 => item_def.members_only = true,
23 => {
item_def.model_data.male_equip1 = reader.read_smart()?;
}
24 => {
item_def.model_data.male_equip2 = reader.read_smart()?;
}
25 => {
item_def.model_data.female_equip1 = reader.read_smart()?;
}
26 => {
item_def.model_data.female_equip2 = reader.read_smart()?;
}
27 => {
item_def.equip_hide_slot2 = reader.read_u8()?;
}
30..=34 => {
item_def.options[opcode as usize - 30] = reader.read_string()?;
}
35..=39 => {
item_def.interface_options[opcode as usize - 35] = reader.read_string()?;
}
40 => {
let len = reader.read_u8()? as usize;
item_def.model_data.original_colors = Vec::with_capacity(len);
item_def.model_data.modified_colors = Vec::with_capacity(len);
for _ in 0..len {
item_def.model_data.original_colors.push(reader.read_u16()?);
item_def.model_data.modified_colors.push(reader.read_u16()?);
}
}
41 => {
let len = reader.read_u8()? as usize;
item_def.model_data.original_texture_colors = Vec::with_capacity(len);
item_def.model_data.original_texture_colors = Vec::with_capacity(len);
for _ in 0..len {
item_def
.model_data
.original_texture_colors
.push(reader.read_u16()?);
item_def
.model_data
.original_texture_colors
.push(reader.read_u16()?);
}
}
42 => {
let len = reader.read_u8()?;
for _ in 0..len {
reader.read_u8()?;
}
}
65 => {
item_def.unnoted = true;
}
78 => {
item_def.model_data.male_equip_id = reader.read_smart()?;
}
79 => {
item_def.model_data.female_equip_id = reader.read_smart()?;
}
97 => {
item_def.noted_id = Some(reader.read_u16()?);
}
98 => {
item_def.noted_template = Some(reader.read_u16()?);
item_def.stackable = true;
}
100..=109 => {
item_def.stack_ids = Some([0; 10]);
item_def.stack_count = Some([0; 10]);
match item_def.stack_ids {
Some(mut stack_ids) => {
stack_ids[opcode as usize - 100] = reader.read_u16()?;
}
_ => unreachable!(),
}
match item_def.stack_count {
Some(mut stack_count) => {
stack_count[opcode as usize - 100] = reader.read_u16()?;
}
_ => unreachable!(),
}
}
115 => {
item_def.team = reader.read_u8()?;
}
121 => {
item_def.lend_id = Some(reader.read_u16()?);
item_def.interface_options[4] = "Discard".to_owned();
item_def.lent = true;
}
122 => {
item_def.lend_tempalte = Some(reader.read_u16()?);
}
125 | 126 => {
reader.read_u8()?;
reader.read_u8()?;
reader.read_u8()?;
}
127..=130 => {
reader.read_u8()?;
reader.read_u16()?;
}
132 => {
let len = reader.read_u8()?;
for _ in 0..len {
reader.read_u16()?;
}
}
139 => {
item_def.bind_link = Some(reader.read_u16()?);
item_def.interface_options[4] = "Destroy".to_owned();
}
140 => {
item_def.bind_tempalte = Some(reader.read_u16()?);
}
164 => {
reader.read_string()?;
}
251 | 252 => {
let len = reader.read_u8()?;
for _ in 0..len {
reader.read_u16()?;
reader.read_u16()?;
}
}
249 => {
util::read_parameters(reader)?;
}
15 | 156 | 157 | 165 | 167 => {}
96 | 113 | 114 | 134 => {
reader.read_u8()?;
}
18 | 44 | 45 | 94 | 95 | 110..=112 | 142..=146 | 150..=154 | 161..=163 => {
reader.read_u16()?;
}
90..=93 | 242..=248 => {
reader.read_smart()?;
}
_ => {
println!("{} {}", id, opcode);
unreachable!()
}
}
}
Ok(item_def)
}