1use std::collections::HashMap;
2
3use binrw::BinRead;
4
5#[derive(Debug, Clone, BinRead)]
7#[br(little)]
8pub struct MomtEntry {
9 pub flags: u32,
10 pub shader: u32,
11 pub blend_mode: u32,
12 pub texture_1: u32,
13 pub emissive_color: [u8; 4],
14 pub frame_emissive_color: [u8; 4],
15 pub texture_2: u32,
16 pub diff_color: [u8; 4],
17 pub ground_type: u32,
18 pub texture_3: u32,
19 pub color_2: u32,
20 pub flags_2: u32,
21 #[br(count = 16)]
22 pub runtime_data: Vec<u8>,
23}
24
25impl MomtEntry {
26 pub fn get_texture1_index(&self, texture_offset_index_map: &HashMap<u32, u32>) -> u32 {
27 texture_offset_index_map
28 .get(&self.texture_1)
29 .copied()
30 .unwrap()
31 }
32
33 pub fn get_texture2_index(&self, texture_offset_index_map: &HashMap<u32, u32>) -> u32 {
34 texture_offset_index_map
35 .get(&self.texture_2)
36 .copied()
37 .unwrap()
38 }
39
40 pub fn get_texture3_index(&self, texture_offset_index_map: &HashMap<u32, u32>) -> u32 {
41 texture_offset_index_map
42 .get(&self.texture_3)
43 .copied()
44 .unwrap()
45 }
46}
47
48#[derive(Debug, Clone)]
50pub struct Mogn {
51 pub names: Vec<String>,
52}
53
54impl Mogn {
55 pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
56 let mut names = Vec::new();
57 let mut start = 0;
58
59 for i in 0..data.len() {
60 if data[i] == 0 {
61 if i > start {
62 let name = String::from_utf8(data[start..i].to_vec())?;
63 names.push(name);
64 }
65 start = i + 1;
66 }
67 }
68
69 Ok(Self { names })
70 }
71}
72
73#[derive(Debug, Clone, BinRead)]
75#[br(little)]
76pub struct MogiEntry {
77 pub flags: u32,
78 pub bounding_box_min: [f32; 3],
79 pub bounding_box_max: [f32; 3],
80 pub name_offset: i32,
81}
82
83#[derive(Debug, Clone, BinRead)]
85#[br(little)]
86pub struct MoltEntry {
87 pub light_type: u8,
88 pub use_attenuation: u8,
89 pub padding: [u8; 2],
90 pub color: [u8; 4],
91 pub position: [f32; 3],
92 pub intensity: f32,
93 pub attenuation_start: f32,
94 pub attenuation_end: f32,
95}
96
97#[derive(Debug, Clone, BinRead)]
99#[br(little)]
100pub struct ModsEntry {
101 pub name: [u8; 20],
102 pub start_index: u32,
103 pub count: u32,
104 pub padding: u32,
105}
106
107#[derive(Debug, Clone, BinRead)]
109#[br(little)]
110pub struct ModdEntry {
111 pub name_index_and_flags: u32, pub position: [f32; 3], pub orientation: [f32; 4], pub scale: f32,
115 pub color: [u8; 4], }
117
118impl ModdEntry {
119 pub fn name_index(&self) -> u32 {
121 self.name_index_and_flags & 0x00FFFFFF
122 }
123
124 pub fn accepts_proj_tex(&self) -> bool {
126 (self.name_index_and_flags & 0x01000000) != 0
127 }
128
129 pub fn uses_interior_lighting(&self) -> bool {
131 (self.name_index_and_flags & 0x02000000) != 0
132 }
133}
134
135#[derive(Debug, Clone, BinRead)]
137#[br(little)]
138pub struct MfogEntry {
139 pub flags: u32,
140 pub position: [f32; 3],
141 pub smaller_radius: f32,
142 pub larger_radius: f32,
143 pub fog_end: f32,
144 pub fog_start_multiplier: f32,
145 pub color_1: [u8; 4],
146 pub color_2: [u8; 4],
147}
148
149#[derive(Debug, Clone, BinRead)]
151#[br(little)]
152pub struct McvpEntry {
153 pub plane: [f32; 4], }
155
156#[derive(Debug, Clone, BinRead)]
160#[br(little)]
161pub struct MopyEntry {
162 pub flags: u8,
163 pub material_id: u8,
164}
165
166pub type MoviEntry = u16; #[derive(Debug, Clone, BinRead)]
171#[br(little)]
172pub struct MovtEntry {
173 pub x: f32,
174 pub y: f32,
175 pub z: f32,
176}
177
178#[derive(Debug, Clone, BinRead)]
180#[br(little)]
181pub struct MonrEntry {
182 pub x: f32,
183 pub y: f32,
184 pub z: f32,
185}
186
187#[derive(Debug, Clone, BinRead)]
189#[br(little)]
190pub struct MotvEntry {
191 pub u: f32,
192 pub v: f32,
193}
194
195#[derive(Debug, Clone, BinRead)]
198#[br(little)]
199pub struct MobaEntry {
200 pub bounding_box_min: [i16; 3],
202 pub bounding_box_max: [i16; 3],
204 pub start_index: u32,
206 pub count: u16,
208 pub min_index: u16,
210 pub max_index: u16,
212 pub flags: u8,
214 pub material_id: u8,
216}
217
218pub type MolrEntry = u16; pub type ModrEntry = u16; #[derive(Debug, Clone, BinRead)]
226#[br(little)]
227pub struct MobnEntry {
228 pub flags: u16,
229 pub neg_child: i16,
230 pub pos_child: i16,
231 pub n_faces: u16,
232 pub face_start: u32,
233 pub plane_distance: f32,
234}
235
236pub type MobrEntry = u16; #[derive(Debug, Clone, BinRead)]
241#[br(little)]
242pub struct MocvEntry {
243 pub b: u8,
244 pub g: u8,
245 pub r: u8,
246 pub a: u8,
247}
248
249#[derive(Debug, Clone, BinRead)]
251#[br(little)]
252pub struct MliqHeader {
253 pub x_tiles: u32,
254 pub y_tiles: u32,
255 pub x_corner: f32,
256 pub y_corner: f32,
257 pub liquid_type: u32,
258 pub material_id: u32,
259}
260
261#[derive(Debug, Clone, BinRead)]
263#[br(little)]
264pub struct MliqVertex {
265 pub position: [f32; 3],
266 pub texture_coord: [f32; 2],
267}
268
269#[derive(Debug, Clone)]
271pub struct Motx {
272 pub textures: Vec<String>,
273 pub texture_offset_index_map: HashMap<u32, u32>,
274}
275
276impl Motx {
277 pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
278 let mut textures = Vec::new();
279 let mut start = 0;
280 let mut texture_offset_index_map = HashMap::new();
281
282 for i in 0..data.len() {
283 if data[i] == 0 {
284 if i > start {
285 let texture = String::from_utf8(data[start..i].to_vec())?;
286 textures.push(texture);
287 texture_offset_index_map.insert(start as u32, textures.len() as u32 - 1);
288 }
289 start = i + 1;
290 }
291 }
292
293 Ok(Self {
294 textures,
295 texture_offset_index_map,
296 })
297 }
298}
299
300#[derive(Debug, Clone)]
302pub struct Mosb {
303 pub skybox: Option<String>,
304}
305
306impl Mosb {
307 pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
308 if data.is_empty() {
309 return Ok(Self { skybox: None });
310 }
311
312 let end = data.iter().position(|&b| b == 0).unwrap_or(data.len());
314 if end > 0 {
315 let skybox = String::from_utf8(data[..end].to_vec())?;
316 Ok(Self {
317 skybox: Some(skybox),
318 })
319 } else {
320 Ok(Self { skybox: None })
321 }
322 }
323}
324
325#[derive(Debug, Clone, BinRead)]
327#[br(little)]
328pub struct MopvEntry {
329 pub x: f32,
330 pub y: f32,
331 pub z: f32,
332}
333
334#[derive(Debug, Clone, BinRead)]
336#[br(little)]
337pub struct MoptEntry {
338 pub start_vertex: u16,
339 pub n_vertices: u16,
340 pub normal: MopvEntry, pub distance: f32,
342}
343
344#[derive(Debug, Clone, BinRead)]
346#[br(little)]
347pub struct MoprEntry {
348 pub portal_index: u16,
349 pub group_index: u16,
350 pub side: i16,
351 pub padding: u16,
352}
353
354#[derive(Debug, Clone, BinRead)]
356#[br(little)]
357pub struct MovvEntry {
358 pub x: f32,
359 pub y: f32,
360 pub z: f32,
361}
362
363#[derive(Debug, Clone, BinRead)]
365#[br(little)]
366pub struct MovbEntry {
367 pub start_vertex: u16,
368 pub vertex_count: u16,
369}
370
371#[derive(Debug, Clone)]
373pub struct Modn {
374 pub names: Vec<String>,
375}
376
377#[derive(Debug, Clone)]
380pub struct MomoEntry {
381 }
383
384#[derive(Debug, Clone)]
386pub struct Mom3Entry {
387 pub data: Vec<u8>,
390}
391
392#[derive(Debug, Clone, BinRead)]
394#[br(little)]
395pub struct MouvEntry {
396 pub translation_speed: [[f32; 2]; 2], }
398
399#[derive(Debug, Clone, BinRead)]
401#[br(little)]
402pub struct MopeEntry {
403 pub portal_index: u32, pub unk1: u32,
405 pub unk2: u32,
406 pub unk3: u32,
407}
408
409#[derive(Debug, Clone, BinRead)]
411#[br(little)]
412pub struct MolvEntry {
413 pub directions: [[f32; 4]; 6], pub unknown: [u8; 3],
415 pub molt_index: u8,
416}
417
418pub type ModiEntry = u32; pub type MogxEntry = u32; #[derive(Debug, Clone, BinRead)]
426#[br(little)]
427pub struct Mpy2Entry {
428 pub flags: u16,
429 pub material_id: u16,
430}
431
432pub type MovxEntry = u32; pub type MoqgEntry = u32; pub type GfidEntry = u32; pub type MoriEntry = u16; #[derive(Debug, Clone, BinRead)]
447#[br(little)]
448pub struct MorbEntry {
449 pub start_index: u16,
450 pub index_count: u16,
451 pub min_index: u16,
452 pub max_index: u16,
453 pub flags: u8,
454 pub material_id: u8,
455}
456
457#[derive(Debug, Clone, BinRead)]
459#[br(little)]
460pub struct MotaEntry {
461 pub tangent: [i16; 4], }
463
464impl MotaEntry {
465 pub fn to_float_tangent(&self) -> [f32; 4] {
467 [
468 self.tangent[0] as f32 / 32767.0,
469 self.tangent[1] as f32 / 32767.0,
470 self.tangent[2] as f32 / 32767.0,
471 self.tangent[3] as f32 / 32767.0,
472 ]
473 }
474}
475
476#[derive(Debug, Clone, BinRead)]
479#[br(little)]
480pub struct MobsEntry {
481 pub start_index: u16,
482 pub index_count: i16, pub min_index: u16,
484 pub max_index: u16,
485 pub flags: u8,
486 pub material_id: u8,
487}
488
489impl Modn {
490 pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
491 let mut names = Vec::new();
492 let mut start = 0;
493
494 for i in 0..data.len() {
495 if data[i] == 0 {
496 if i > start {
497 let name = String::from_utf8(data[start..i].to_vec())?;
498 names.push(name);
499 }
500 start = i + 1;
501 }
502 }
503
504 Ok(Self { names })
505 }
506}