wow_dbc/wrath_tables/
world_map_continent.rs

1use crate::{
2    DbcTable, Indexable,
3};
4use crate::header::{
5    DbcHeader, HEADER_SIZE, parse_header,
6};
7use crate::wrath_tables::map::MapKey;
8use crate::wrath_tables::world_map_area::WorldMapAreaKey;
9use std::io::Write;
10
11#[derive(Debug, Clone, PartialEq, PartialOrd)]
12pub struct WorldMapContinent {
13    pub rows: Vec<WorldMapContinentRow>,
14}
15
16impl DbcTable for WorldMapContinent {
17    type Row = WorldMapContinentRow;
18
19    const FILENAME: &'static str = "WorldMapContinent.dbc";
20
21    fn rows(&self) -> &[Self::Row] { &self.rows }
22    fn rows_mut(&mut self) -> &mut [Self::Row] { &mut self.rows }
23
24    fn read(b: &mut impl std::io::Read) -> Result<Self, crate::DbcError> {
25        let mut header = [0_u8; HEADER_SIZE];
26        b.read_exact(&mut header)?;
27        let header = parse_header(&header)?;
28
29        if header.record_size != 56 {
30            return Err(crate::DbcError::InvalidHeader(
31                crate::InvalidHeaderError::RecordSize {
32                    expected: 56,
33                    actual: header.record_size,
34                },
35            ));
36        }
37
38        if header.field_count != 14 {
39            return Err(crate::DbcError::InvalidHeader(
40                crate::InvalidHeaderError::FieldCount {
41                    expected: 14,
42                    actual: header.field_count,
43                },
44            ));
45        }
46
47        let mut r = vec![0_u8; (header.record_count * header.record_size) as usize];
48        b.read_exact(&mut r)?;
49
50        let mut rows = Vec::with_capacity(header.record_count as usize);
51
52        for mut chunk in r.chunks(header.record_size as usize) {
53            let chunk = &mut chunk;
54
55            // id: primary_key (WorldMapContinent) int32
56            let id = WorldMapContinentKey::new(crate::util::read_i32_le(chunk)?);
57
58            // map_id: foreign_key (Map) int32
59            let map_id = MapKey::new(crate::util::read_i32_le(chunk)?.into());
60
61            // left_boundary: int32
62            let left_boundary = crate::util::read_i32_le(chunk)?;
63
64            // right_boundary: int32
65            let right_boundary = crate::util::read_i32_le(chunk)?;
66
67            // top_boundary: int32
68            let top_boundary = crate::util::read_i32_le(chunk)?;
69
70            // bottom_boundary: int32
71            let bottom_boundary = crate::util::read_i32_le(chunk)?;
72
73            // continent_offset: float[2]
74            let continent_offset = crate::util::read_array_f32::<2>(chunk)?;
75
76            // scale: float
77            let scale = crate::util::read_f32_le(chunk)?;
78
79            // taxi_min: float[2]
80            let taxi_min = crate::util::read_array_f32::<2>(chunk)?;
81
82            // taxi_max: float[2]
83            let taxi_max = crate::util::read_array_f32::<2>(chunk)?;
84
85            // world_map_id: foreign_key (WorldMapArea) int32
86            let world_map_id = WorldMapAreaKey::new(crate::util::read_i32_le(chunk)?.into());
87
88
89            rows.push(WorldMapContinentRow {
90                id,
91                map_id,
92                left_boundary,
93                right_boundary,
94                top_boundary,
95                bottom_boundary,
96                continent_offset,
97                scale,
98                taxi_min,
99                taxi_max,
100                world_map_id,
101            });
102        }
103
104        Ok(WorldMapContinent { rows, })
105    }
106
107    fn write(&self, b: &mut impl Write) -> Result<(), std::io::Error> {
108        let header = DbcHeader {
109            record_count: self.rows.len() as u32,
110            field_count: 14,
111            record_size: 56,
112            string_block_size: 1,
113        };
114
115        b.write_all(&header.write_header())?;
116
117        for row in &self.rows {
118            // id: primary_key (WorldMapContinent) int32
119            b.write_all(&row.id.id.to_le_bytes())?;
120
121            // map_id: foreign_key (Map) int32
122            b.write_all(&(row.map_id.id as i32).to_le_bytes())?;
123
124            // left_boundary: int32
125            b.write_all(&row.left_boundary.to_le_bytes())?;
126
127            // right_boundary: int32
128            b.write_all(&row.right_boundary.to_le_bytes())?;
129
130            // top_boundary: int32
131            b.write_all(&row.top_boundary.to_le_bytes())?;
132
133            // bottom_boundary: int32
134            b.write_all(&row.bottom_boundary.to_le_bytes())?;
135
136            // continent_offset: float[2]
137            for i in row.continent_offset {
138                b.write_all(&i.to_le_bytes())?;
139            }
140
141
142            // scale: float
143            b.write_all(&row.scale.to_le_bytes())?;
144
145            // taxi_min: float[2]
146            for i in row.taxi_min {
147                b.write_all(&i.to_le_bytes())?;
148            }
149
150
151            // taxi_max: float[2]
152            for i in row.taxi_max {
153                b.write_all(&i.to_le_bytes())?;
154            }
155
156
157            // world_map_id: foreign_key (WorldMapArea) int32
158            b.write_all(&(row.world_map_id.id as i32).to_le_bytes())?;
159
160        }
161
162        b.write_all(&[0_u8])?;
163
164        Ok(())
165    }
166
167}
168
169impl Indexable for WorldMapContinent {
170    type PrimaryKey = WorldMapContinentKey;
171    fn get(&self, key: impl TryInto<Self::PrimaryKey>) -> Option<&Self::Row> {
172        let key = key.try_into().ok()?;
173        self.rows.iter().find(|a| a.id.id == key.id)
174    }
175
176    fn get_mut(&mut self, key: impl TryInto<Self::PrimaryKey>) -> Option<&mut Self::Row> {
177        let key = key.try_into().ok()?;
178        self.rows.iter_mut().find(|a| a.id.id == key.id)
179    }
180}
181
182#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
183pub struct WorldMapContinentKey {
184    pub id: i32
185}
186
187impl WorldMapContinentKey {
188    pub const fn new(id: i32) -> Self {
189        Self { id }
190    }
191
192}
193
194impl From<u8> for WorldMapContinentKey {
195    fn from(v: u8) -> Self {
196        Self::new(v.into())
197    }
198}
199
200impl From<u16> for WorldMapContinentKey {
201    fn from(v: u16) -> Self {
202        Self::new(v.into())
203    }
204}
205
206impl From<i8> for WorldMapContinentKey {
207    fn from(v: i8) -> Self {
208        Self::new(v.into())
209    }
210}
211
212impl From<i16> for WorldMapContinentKey {
213    fn from(v: i16) -> Self {
214        Self::new(v.into())
215    }
216}
217
218impl From<i32> for WorldMapContinentKey {
219    fn from(v: i32) -> Self {
220        Self::new(v)
221    }
222}
223
224impl TryFrom<u32> for WorldMapContinentKey {
225    type Error = u32;
226    fn try_from(v: u32) -> Result<Self, Self::Error> {
227        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
228    }
229}
230
231impl TryFrom<usize> for WorldMapContinentKey {
232    type Error = usize;
233    fn try_from(v: usize) -> Result<Self, Self::Error> {
234        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
235    }
236}
237
238impl TryFrom<u64> for WorldMapContinentKey {
239    type Error = u64;
240    fn try_from(v: u64) -> Result<Self, Self::Error> {
241        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
242    }
243}
244
245impl TryFrom<i64> for WorldMapContinentKey {
246    type Error = i64;
247    fn try_from(v: i64) -> Result<Self, Self::Error> {
248        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
249    }
250}
251
252impl TryFrom<isize> for WorldMapContinentKey {
253    type Error = isize;
254    fn try_from(v: isize) -> Result<Self, Self::Error> {
255        Ok(TryInto::<i32>::try_into(v).ok().ok_or(v)?.into())
256    }
257}
258
259#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
260pub struct WorldMapContinentRow {
261    pub id: WorldMapContinentKey,
262    pub map_id: MapKey,
263    pub left_boundary: i32,
264    pub right_boundary: i32,
265    pub top_boundary: i32,
266    pub bottom_boundary: i32,
267    pub continent_offset: [f32; 2],
268    pub scale: f32,
269    pub taxi_min: [f32; 2],
270    pub taxi_max: [f32; 2],
271    pub world_map_id: WorldMapAreaKey,
272}
273