wow_dbc/wrath_tables/
attack_anim_types.rs

1use crate::DbcTable;
2use crate::header::{
3    DbcHeader, HEADER_SIZE, parse_header,
4};
5use std::io::Write;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct AttackAnimTypes {
9    pub rows: Vec<AttackAnimTypesRow>,
10}
11
12impl DbcTable for AttackAnimTypes {
13    type Row = AttackAnimTypesRow;
14
15    const FILENAME: &'static str = "AttackAnimTypes.dbc";
16
17    fn rows(&self) -> &[Self::Row] { &self.rows }
18    fn rows_mut(&mut self) -> &mut [Self::Row] { &mut self.rows }
19
20    fn read(b: &mut impl std::io::Read) -> Result<Self, crate::DbcError> {
21        let mut header = [0_u8; HEADER_SIZE];
22        b.read_exact(&mut header)?;
23        let header = parse_header(&header)?;
24
25        if header.record_size != 8 {
26            return Err(crate::DbcError::InvalidHeader(
27                crate::InvalidHeaderError::RecordSize {
28                    expected: 8,
29                    actual: header.record_size,
30                },
31            ));
32        }
33
34        if header.field_count != 2 {
35            return Err(crate::DbcError::InvalidHeader(
36                crate::InvalidHeaderError::FieldCount {
37                    expected: 2,
38                    actual: header.field_count,
39                },
40            ));
41        }
42
43        let mut r = vec![0_u8; (header.record_count * header.record_size) as usize];
44        b.read_exact(&mut r)?;
45        let mut string_block = vec![0_u8; header.string_block_size as usize];
46        b.read_exact(&mut string_block)?;
47
48        let mut rows = Vec::with_capacity(header.record_count as usize);
49
50        for mut chunk in r.chunks(header.record_size as usize) {
51            let chunk = &mut chunk;
52
53            // anim_id: int32
54            let anim_id = crate::util::read_i32_le(chunk)?;
55
56            // anim_name: string_ref
57            let anim_name = {
58                let s = crate::util::get_string_as_vec(chunk, &string_block)?;
59                String::from_utf8(s)?
60            };
61
62
63            rows.push(AttackAnimTypesRow {
64                anim_id,
65                anim_name,
66            });
67        }
68
69        Ok(AttackAnimTypes { rows, })
70    }
71
72    fn write(&self, b: &mut impl Write) -> Result<(), std::io::Error> {
73        let header = DbcHeader {
74            record_count: self.rows.len() as u32,
75            field_count: 2,
76            record_size: 8,
77            string_block_size: self.string_block_size(),
78        };
79
80        b.write_all(&header.write_header())?;
81
82        let mut string_index = 1;
83        for row in &self.rows {
84            // anim_id: int32
85            b.write_all(&row.anim_id.to_le_bytes())?;
86
87            // anim_name: string_ref
88            if !row.anim_name.is_empty() {
89                b.write_all(&(string_index as u32).to_le_bytes())?;
90                string_index += row.anim_name.len() + 1;
91            }
92            else {
93                b.write_all(&(0_u32).to_le_bytes())?;
94            }
95
96        }
97
98        self.write_string_block(b)?;
99
100        Ok(())
101    }
102
103}
104
105impl AttackAnimTypes {
106    fn write_string_block(&self, b: &mut impl Write) -> Result<(), std::io::Error> {
107        b.write_all(&[0])?;
108
109        for row in &self.rows {
110            if !row.anim_name.is_empty() { b.write_all(row.anim_name.as_bytes())?; b.write_all(&[0])?; };
111        }
112
113        Ok(())
114    }
115
116    fn string_block_size(&self) -> u32 {
117        let mut sum = 1;
118        for row in &self.rows {
119            if !row.anim_name.is_empty() { sum += row.anim_name.len() + 1; };
120        }
121
122        sum as u32
123    }
124
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
128pub struct AttackAnimTypesRow {
129    pub anim_id: i32,
130    pub anim_name: String,
131}
132