use std::{fs::File, io::Read, path::Path}; use super::header::Header; use crate::lumps::{LinedefLump, Lump, LumpType, VertexLump}; use crate::types::{Linedef, Vertex}; use crate::utils::{read_ascii, read_i16_le, read_u32_le, validate_wad}; pub struct WADFile { pub path: String, pub wad_id: String, pub num_lumps: u32, pub dir_offset: u32, pub directory: Vec, pub data: Vec, } impl WADFile { pub fn new(path: String) -> Self { if !(validate_wad(path.as_str()).unwrap()) { panic!(); } let file_path = Path::new(path.as_str()); let mut wad_file = File::open(file_path).unwrap(); let file_size = wad_file.metadata().unwrap().len() as usize; let mut file_buffer: Vec = Vec::with_capacity(file_size); wad_file.read_to_end(&mut file_buffer).unwrap(); let wad_header = Header::read_data(&file_buffer[0..12]); let mut lump_dir: Vec = Vec::with_capacity(wad_header.num_lumps as usize); let offset = wad_header.dir_offset; for entry in 0..wad_header.num_lumps { let startpos = (offset + 16 * entry) as usize; let lump_offset = read_u32_le(&file_buffer[startpos..startpos + 4]); let size = read_u32_le(&file_buffer[startpos + 4..startpos + 8]); let name = read_ascii(&file_buffer[startpos + 8..startpos + 16]); let lump_type = match name.as_str() { "VERTEXES" => LumpType::Vertex, "LINEDEFS" => LumpType::Linedef, _ => LumpType::Unknown, }; lump_dir.push(Lump { name, offset: lump_offset, lump_type, size, }); } Self { path, wad_id: wad_header.wad_id, num_lumps: wad_header.num_lumps, dir_offset: wad_header.dir_offset, directory: lump_dir, data: file_buffer, } } pub fn get_vertex_lump(&self, lump: &Lump) -> VertexLump { let lump_offset = lump.offset as usize; let lump_size = lump.size as usize; let lump_data = &self.data[lump_offset..lump_offset + lump_size]; let lump_entries: usize = lump_size / 4; let mut vertexes: Vec = Vec::with_capacity(lump_entries); for entry in 0..lump_entries { let startpos = entry * 4; let vertex_x = read_i16_le(&lump_data[startpos..startpos + 2]); let vertex_y = read_i16_le(&lump_data[startpos + 2..startpos + 4]); vertexes.push(Vertex { x: vertex_x, y: vertex_y, }); } VertexLump { vertexes } } pub fn get_linedef_lump(&self, lump: &Lump) -> LinedefLump { let lump_offset = lump.offset as usize; let lump_size = lump.size as usize; let lump_data = &self.data[lump_offset..lump_offset + lump_size]; let lump_entries = lump_size / 14; let mut linedefs: Vec = Vec::with_capacity(lump_entries); for entry in 0..lump_entries { let startpos = entry * 14; let vertex1 = read_i16_le(&lump_data[startpos..startpos + 2]); let vertex2 = read_i16_le(&lump_data[startpos + 2..startpos + 4]); let flags = read_i16_le(&lump_data[startpos + 4..startpos + 6]); let special = read_i16_le(&lump_data[startpos + 6..startpos + 8]); let tag = read_i16_le(&lump_data[startpos + 8..startpos + 10]); let front_sidedef = read_i16_le(&lump_data[startpos + 10..startpos + 12]); let back_sidedef = read_i16_le(&lump_data[startpos + 12..startpos + 14]); linedefs.push(Linedef { vertex1, vertex2, flags, special, tag, front_sidedef, back_sidedef, }); } LinedefLump { linedefs } } }