diff --git a/src/main.rs b/src/main.rs index c67fb8a..e3aa21b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -164,7 +164,7 @@ impl eframe::App for RustDoomLauncher { self.add_stuff_window_displayed = true; } }); - ui.horizontal_wrapped(|ui| { + ui.horizontal(|ui| { ui.vertical(|ui| { ui.set_max_width(100.0); ui.label("Launchers"); @@ -265,6 +265,9 @@ impl eframe::App for RustDoomLauncher { .add_pwads(&self.pwad_manager.get_current()) } }); + let mut text = "Placeholder for WAD info stuffs"; + let window_size = frame.info().window_info.size; + ui.add(egui::TextEdit::multiline(&mut text).desired_width(window_size[0]/1.6).desired_rows(20)); }); ui.separator(); ui.horizontal_wrapped(|ui| { @@ -322,8 +325,6 @@ impl eframe::App for RustDoomLauncher { } else { ui.label("Select an iwad plz"); } - // This feels ver much more C-like, but I think it works? - // Probably should have a little bit more checking around the unwrap calls let mut remove: Option = None; for (pos, pwad) in self.pwad_manager.get_current().iter().enumerate() { if ui diff --git a/src/wad.rs b/src/wad.rs index 2809427..29af2b6 100644 --- a/src/wad.rs +++ b/src/wad.rs @@ -3,6 +3,7 @@ use serde::Deserialize; use std::fs::File; use std::io::{BufReader, Seek, SeekFrom}; use std::path::PathBuf; +use std::collections::HashMap; /* A great document I've used as a reference is The Unofficial Doom Specs v1.666 @@ -32,6 +33,21 @@ pub struct NiceWadLumpEntry { pub name: String, } +pub struct LevelSummary { + pub name: String, + pub num_enemies: u32, + pub num_health_pickups: u32, +} +// Chapter 4-2 +#[derive(Deserialize, Debug)] +pub struct WadThingLump { + pub x: i16, + pub y: i16, + pub angle: i16, + pub thing_type: u16, + pub options: u16, +} + pub fn open_wad(path: &PathBuf) -> WadHeader { let mut file = BufReader::new(File::open(path).unwrap()); let header: WadHeader = bincode::deserialize_from(&mut file).unwrap(); @@ -39,7 +55,7 @@ pub fn open_wad(path: &PathBuf) -> WadHeader { .unwrap(); let mut lumps: Vec = Vec::new(); let mut nice_lumps: Vec = Vec::new(); - let mut levels = Vec::new(); + let mut levels_indicies = Vec::new(); for lump_num in 0..header.num_lumps { let lump: WadLumpDirectoryEntry = bincode::deserialize_from(&mut file).unwrap(); let nice_lump = NiceWadLumpEntry { @@ -48,23 +64,100 @@ pub fn open_wad(path: &PathBuf) -> WadHeader { name: std::str::from_utf8(&lump.name).unwrap().to_string(), }; // I stole this from rust-doom. I looked up idSoftware Linux Doom, but they searched - // for the strings "map%d" or ExMy - I'm not 100% sure, but I bet many PWADs don't + // for the strings "mapXY" or ExMy - I'm not 100% sure, but I bet many PWADs don't // neccesarily use this... I do think that probably PWADs provide different THINGS // for their maps - I don't know how you wouldn't - what I'm not 100% sure about is // whether the map reference is _always_ before the THINGS. Might have to try // with some WADs to check if &lump.name == b"THINGS\0\0" { - levels.push((lump_num - 1) as usize); + assert!(lump_num > 0); + levels_indicies.push((lump_num - 1) as usize); } lumps.push(lump); nice_lumps.push(nice_lump); } - for lump in nice_lumps { - println!("{}", lump.name); + let mut _level_summaries: Vec = Vec::new(); + let mut enemy_maps: Vec> = Vec::new(); + for level_i in levels_indicies { + let name = nice_lumps.get(level_i).unwrap().name.clone(); + // Presume the THINGS is offset by 1 for the minute + let level_things_wad_lump = nice_lumps.get(level_i + 1).unwrap(); + file.seek(SeekFrom::Start(level_things_wad_lump.offset as u64)) + .unwrap(); + let mut enemy_map: HashMap = HashMap::new(); + for _ in 0..level_things_wad_lump.size { + let map_thing: WadThingLump = bincode::deserialize_from(&mut file).unwrap(); + // Just checking UV + if map_thing.options & (1 << 2) > 0 { + if let Some(n) = enemy_map.get(&map_thing.thing_type.into()) { + enemy_map.insert(map_thing.thing_type.into(), n + 1); + } else { + enemy_map.insert(map_thing.thing_type.into(), 1); + } + } + + } + enemy_maps.push(enemy_map); + break; } + println!("{:#?}", enemy_maps); header } +#[derive(Eq, Hash, PartialEq, Debug)] +enum Enemy { + FormerHuman, + WolfensteinSs, + FormerHumanSergeant, + HeavyWeaponDude, + Imp, + Demon, + Spectre, + LostSoul, + Cacodemon, + HellKnight, + BaronOfHell, + Arachnotron, + PainElemental, + Revenant, + Mancubus, + ArchVile, + SpiderMastermind, + CyberDemon, + BossBrain, + Unknown, +} + +impl std::convert::From for Enemy { + fn from(ttype: u16) -> Self { + match ttype { + 3004 => Self::FormerHuman, + 84 => Self::WolfensteinSs, + 9 => Self::FormerHumanSergeant, + 65 => Self::HeavyWeaponDude, + 3001 => Self::Imp, + 3002 => Self:: Demon, + 58 => Self::Spectre, + 3006 => Self::LostSoul, + 3005 => Self::Cacodemon, + 69 => Self::HellKnight, + 3003 => Self::BaronOfHell, + 68 => Self::Arachnotron, + 71 => Self::PainElemental, + 66 => Self::Revenant, + 67 => Self::Mancubus, + 64 => Self::ArchVile, + 7 => Self::SpiderMastermind, + 16 => Self::CyberDemon, + 88 => Self::BossBrain, + _ => Self::Unknown + } + } +} + + + + #[cfg(test)] mod tests { use super::*; @@ -98,5 +191,6 @@ mod tests { // These shouldn't compile if the size is incorrect (I think) const _HS: [u8; 12] = [0; std::mem::size_of::()]; const _LDS: [u8; 16] = [0; std::mem::size_of::()]; + const _WTL: [u8; 10] = [0; std::mem::size_of::()]; } }