use std::io::Read; #[derive(Debug)] pub enum ReadError{ #[cfg(feature="roblox")] Roblox(strafesnet_rbx_loader::ReadError), #[cfg(feature="source")] Source(strafesnet_bsp_loader::ReadError), #[cfg(feature="snf")] StrafesNET(strafesnet_snf::Error), #[cfg(feature="snf")] StrafesNETMap(strafesnet_snf::map::Error), Io(std::io::Error), UnknownFileFormat, } impl std::fmt::Display for ReadError{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ write!(f,"{self:?}") } } impl std::error::Error for ReadError{} pub enum DataStructure{ #[cfg(feature="roblox")] Roblox(strafesnet_rbx_loader::Dom), #[cfg(feature="source")] Source(strafesnet_bsp_loader::Bsp), #[cfg(feature="snf")] StrafesNET(strafesnet_common::map::CompleteMap), } pub fn read(input:R)->Result{ let mut buf=std::io::BufReader::new(input); let peek=std::io::BufRead::fill_buf(&mut buf).map_err(ReadError::Io)?; match &peek[0..4]{ #[cfg(feature="roblox")] b"Ok(DataStructure::Roblox(strafesnet_rbx_loader::read(buf).map_err(ReadError::Roblox)?)), #[cfg(feature="source")] b"VBSP"=>Ok(DataStructure::Source(strafesnet_bsp_loader::read(buf).map_err(ReadError::Source)?)), #[cfg(feature="snf")] b"SNFM"=>Ok(DataStructure::StrafesNET( strafesnet_snf::read_map(buf).map_err(ReadError::StrafesNET)? .into_complete_map().map_err(ReadError::StrafesNETMap)? )), _=>Err(ReadError::UnknownFileFormat), } } #[derive(Debug)] pub enum LoadError{ ReadError(ReadError), File(std::io::Error), Io(std::io::Error), } impl std::fmt::Display for LoadError{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ write!(f,"{self:?}") } } impl std::error::Error for LoadError{} pub fn load>(path:P)->Result{ //blocking because it's simpler... let file=std::fs::File::open(path).map_err(LoadError::File)?; match read(file).map_err(LoadError::ReadError)?{ #[cfg(feature="snf")] DataStructure::StrafesNET(map)=>Ok(map), #[cfg(feature="roblox")] DataStructure::Roblox(mut dom)=>{ dom.run_scripts(); let mut loader=strafesnet_deferred_loader::roblox_legacy(); let (texture_loader,mesh_loader)=loader.get_inner_mut(); let map_step1=strafesnet_rbx_loader::convert( &dom, |name|texture_loader.acquire_render_config_id(name), |name|mesh_loader.acquire_mesh_id(name), ); let meshpart_meshes=mesh_loader.load_meshes().map_err(LoadError::Io)?; let map_step2=map_step1.add_meshpart_meshes_and_calculate_attributes( meshpart_meshes.into_iter().map(|(mesh_id,loader_model)| (mesh_id,strafesnet_rbx_loader::data::RobloxMeshBytes::new(loader_model.get())) ) ); let (textures,render_configs)=loader.into_render_configs().map_err(LoadError::Io)?.consume(); let map=map_step2.add_render_configs_and_textures( render_configs.into_iter(), textures.into_iter().map(|(texture_id,texture)| (texture_id,match texture{ strafesnet_deferred_loader::texture::Texture::ImageDDS(data)=>data, }) ) ); Ok(map) }, #[cfg(feature="source")] DataStructure::Source(bsp)=>{ let mut loader=strafesnet_deferred_loader::source_legacy(); let (texture_loader,mesh_loader)=loader.get_inner_mut(); let map_step1=strafesnet_bsp_loader::convert( &bsp, |name|texture_loader.acquire_render_config_id(name), |name|mesh_loader.acquire_mesh_id(name), ); let prop_meshes=mesh_loader.load_meshes(bsp.as_ref()); let map_step2=map_step1.add_prop_meshes( //the type conflagulator 9000 prop_meshes.into_iter().map(|(mesh_id,loader_model)| (mesh_id,strafesnet_bsp_loader::data::ModelData{ mdl:strafesnet_bsp_loader::data::MdlData::new(loader_model.mdl.get()), vtx:strafesnet_bsp_loader::data::VtxData::new(loader_model.vtx.get()), vvd:strafesnet_bsp_loader::data::VvdData::new(loader_model.vvd.get()), }) ), |name|texture_loader.acquire_render_config_id(name), ); let (textures,render_configs)=loader.into_render_configs().map_err(LoadError::Io)?.consume(); let map=map_step2.add_render_configs_and_textures( render_configs.into_iter(), textures.into_iter().map(|(texture_id,texture)| (texture_id,match texture{ strafesnet_deferred_loader::texture::Texture::ImageDDS(data)=>data, }) ), ); Ok(map) }, } }