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)]
91#[br(little)]
92pub struct MoltEntry {
93 pub light_type: u8,
94 pub use_attenuation: u8,
95 pub padding: [u8; 2],
96 pub color: [u8; 4],
97 pub position: [f32; 3],
98 pub intensity: f32,
99 pub rotation: [f32; 4],
100 pub attenuation_start: f32,
101 pub attenuation_end: f32,
102}
103
104#[derive(Debug, Clone, BinRead)]
106#[br(little)]
107pub struct ModsEntry {
108 pub name: [u8; 20],
109 pub start_index: u32,
110 pub count: u32,
111 pub padding: u32,
112}
113
114#[derive(Debug, Clone, BinRead)]
116#[br(little)]
117pub struct ModdEntry {
118 pub name_index_and_flags: u32, pub position: [f32; 3], pub orientation: [f32; 4], pub scale: f32,
122 pub color: [u8; 4], }
124
125impl ModdEntry {
126 pub fn name_index(&self) -> u32 {
128 self.name_index_and_flags & 0x00FFFFFF
129 }
130
131 pub fn accepts_proj_tex(&self) -> bool {
133 (self.name_index_and_flags & 0x01000000) != 0
134 }
135
136 pub fn uses_interior_lighting(&self) -> bool {
138 (self.name_index_and_flags & 0x02000000) != 0
139 }
140}
141
142#[derive(Debug, Clone, BinRead)]
144#[br(little)]
145pub struct MfogEntry {
146 pub flags: u32,
147 pub position: [f32; 3],
148 pub smaller_radius: f32,
149 pub larger_radius: f32,
150 pub fog_end: f32,
151 pub fog_start_multiplier: f32,
152 pub color_1: [u8; 4],
153 pub color_2: [u8; 4],
154}
155
156#[derive(Debug, Clone, BinRead)]
158#[br(little)]
159pub struct McvpEntry {
160 pub plane: [f32; 4], }
162
163#[derive(Debug, Clone, BinRead)]
167#[br(little)]
168pub struct MopyEntry {
169 pub flags: u8,
170 pub material_id: u8,
171}
172
173pub type MoviEntry = u16; #[derive(Debug, Clone, BinRead)]
178#[br(little)]
179pub struct MovtEntry {
180 pub x: f32,
181 pub y: f32,
182 pub z: f32,
183}
184
185#[derive(Debug, Clone, BinRead)]
187#[br(little)]
188pub struct MonrEntry {
189 pub x: f32,
190 pub y: f32,
191 pub z: f32,
192}
193
194#[derive(Debug, Clone, BinRead)]
196#[br(little)]
197pub struct MotvEntry {
198 pub u: f32,
199 pub v: f32,
200}
201
202#[derive(Debug, Clone, BinRead)]
205#[br(little)]
206pub struct MobaEntry {
207 pub bounding_box_min: [i16; 3],
209 pub bounding_box_max: [i16; 3],
211 pub start_index: u32,
213 pub count: u16,
215 pub min_index: u16,
217 pub max_index: u16,
219 pub flags: u8,
221 pub material_id: u8,
223}
224
225pub type MolrEntry = u16; pub type ModrEntry = u16; #[derive(Debug, Clone, BinRead)]
233#[br(little)]
234pub struct MobnEntry {
235 pub flags: u16,
236 pub neg_child: i16,
237 pub pos_child: i16,
238 pub n_faces: u16,
239 pub face_start: u32,
240 pub plane_distance: f32,
241}
242
243pub type MobrEntry = u16; #[derive(Debug, Clone, BinRead)]
248#[br(little)]
249pub struct MocvEntry {
250 pub b: u8,
251 pub g: u8,
252 pub r: u8,
253 pub a: u8,
254}
255
256#[derive(Debug, Clone, BinRead)]
258#[br(little)]
259pub struct MliqHeader {
260 pub x_tiles: u32,
261 pub y_tiles: u32,
262 pub x_corner: f32,
263 pub y_corner: f32,
264 pub liquid_type: u32,
265 pub material_id: u32,
266}
267
268#[derive(Debug, Clone, BinRead)]
270#[br(little)]
271pub struct MliqVertex {
272 pub position: [f32; 3],
273 pub texture_coord: [f32; 2],
274}
275
276#[derive(Debug, Clone)]
278pub struct Motx {
279 pub textures: Vec<String>,
280 pub texture_offset_index_map: HashMap<u32, u32>,
281}
282
283impl Motx {
284 pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
285 let mut textures = Vec::new();
286 let mut start = 0;
287 let mut texture_offset_index_map = HashMap::new();
288
289 for i in 0..data.len() {
290 if data[i] == 0 {
291 if i > start {
292 let texture = String::from_utf8(data[start..i].to_vec())?;
293 textures.push(texture);
294 texture_offset_index_map.insert(start as u32, textures.len() as u32 - 1);
295 }
296 start = i + 1;
297 }
298 }
299
300 Ok(Self {
301 textures,
302 texture_offset_index_map,
303 })
304 }
305}
306
307#[derive(Debug, Clone)]
309pub struct Mosb {
310 pub skybox: Option<String>,
311}
312
313impl Mosb {
314 pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
315 if data.is_empty() {
316 return Ok(Self { skybox: None });
317 }
318
319 let end = data.iter().position(|&b| b == 0).unwrap_or(data.len());
321 if end > 0 {
322 let skybox = String::from_utf8(data[..end].to_vec())?;
323 Ok(Self {
324 skybox: Some(skybox),
325 })
326 } else {
327 Ok(Self { skybox: None })
328 }
329 }
330}
331
332#[derive(Debug, Clone, BinRead)]
334#[br(little)]
335pub struct MopvEntry {
336 pub x: f32,
337 pub y: f32,
338 pub z: f32,
339}
340
341#[derive(Debug, Clone, BinRead)]
343#[br(little)]
344pub struct MoptEntry {
345 pub start_vertex: u16,
346 pub n_vertices: u16,
347 pub normal: MopvEntry, pub distance: f32,
349}
350
351#[derive(Debug, Clone, BinRead)]
353#[br(little)]
354pub struct MoprEntry {
355 pub portal_index: u16,
356 pub group_index: u16,
357 pub side: i16,
358 pub padding: u16,
359}
360
361#[derive(Debug, Clone, BinRead)]
363#[br(little)]
364pub struct MovvEntry {
365 pub x: f32,
366 pub y: f32,
367 pub z: f32,
368}
369
370#[derive(Debug, Clone, BinRead)]
372#[br(little)]
373pub struct MovbEntry {
374 pub start_vertex: u16,
375 pub vertex_count: u16,
376}
377
378#[derive(Debug, Clone)]
380pub struct Modn {
381 pub names: Vec<String>,
382}
383
384#[derive(Debug, Clone)]
387pub struct MomoEntry {
388 }
390
391#[derive(Debug, Clone)]
393pub struct Mom3Entry {
394 pub data: Vec<u8>,
397}
398
399#[derive(Debug, Clone, BinRead)]
401#[br(little)]
402pub struct MouvEntry {
403 pub translation_speed: [[f32; 2]; 2], }
405
406#[derive(Debug, Clone, BinRead)]
408#[br(little)]
409pub struct MopeEntry {
410 pub portal_index: u32, pub unk1: u32,
412 pub unk2: u32,
413 pub unk3: u32,
414}
415
416#[derive(Debug, Clone, BinRead)]
418#[br(little)]
419pub struct MolvEntry {
420 pub directions: [[f32; 4]; 6], pub unknown: [u8; 3],
422 pub molt_index: u8,
423}
424
425pub type ModiEntry = u32; pub type MogxEntry = u32; #[derive(Debug, Clone, BinRead)]
433#[br(little)]
434pub struct Mpy2Entry {
435 pub flags: u16,
436 pub material_id: u16,
437}
438
439pub type MovxEntry = u32; pub type MoqgEntry = u32; pub type GfidEntry = u32; pub type MoriEntry = u16; #[derive(Debug, Clone, BinRead)]
454#[br(little)]
455pub struct MorbEntry {
456 pub start_index: u16,
457 pub index_count: u16,
458 pub min_index: u16,
459 pub max_index: u16,
460 pub flags: u8,
461 pub material_id: u8,
462}
463
464#[derive(Debug, Clone, BinRead)]
466#[br(little)]
467pub struct MotaEntry {
468 pub tangent: [i16; 4], }
470
471impl MotaEntry {
472 pub fn to_float_tangent(&self) -> [f32; 4] {
474 [
475 self.tangent[0] as f32 / 32767.0,
476 self.tangent[1] as f32 / 32767.0,
477 self.tangent[2] as f32 / 32767.0,
478 self.tangent[3] as f32 / 32767.0,
479 ]
480 }
481}
482
483#[derive(Debug, Clone, BinRead)]
486#[br(little)]
487pub struct MobsEntry {
488 pub start_index: u16,
489 pub index_count: i16, pub min_index: u16,
491 pub max_index: u16,
492 pub flags: u8,
493 pub material_id: u8,
494}
495
496impl Modn {
497 pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
498 let mut names = Vec::new();
499 let mut start = 0;
500
501 for i in 0..data.len() {
502 if data[i] == 0 {
503 if i > start {
504 let name = String::from_utf8(data[start..i].to_vec())?;
505 names.push(name);
506 }
507 start = i + 1;
508 }
509 }
510
511 Ok(Self { names })
512 }
513}