diff --git a/lib/bsp_loader/src/lib.rs b/lib/bsp_loader/src/lib.rs index 1021b03..9258df7 100644 --- a/lib/bsp_loader/src/lib.rs +++ b/lib/bsp_loader/src/lib.rs @@ -45,6 +45,7 @@ impl From<loader::MeshError> for LoadError{ } pub struct Bsp{ bsp:vbsp::Bsp, + case_folded_file_names:std::collections::HashMap<String,String>, } impl AsRef<vbsp::Bsp> for Bsp{ fn as_ref(&self)->&vbsp::Bsp{ @@ -62,11 +63,21 @@ pub fn read<R:std::io::Read>(mut input:R)->Result<Bsp,ReadError>{ } impl Bsp{ pub fn new(bsp:vbsp::Bsp)->Self{ + let case_folded_file_names=bsp.pack.clone().into_zip().lock().unwrap().file_names().map(|s|{ + (s.to_lowercase(),s.to_owned()) + }).collect(); Self{ bsp, + case_folded_file_names, } } - pub fn to_snf(&self,failure_mode:LoadFailureMode,vpk_list:&[vpk::VPK])->Result<strafesnet_common::map::CompleteMap,LoadError>{ + pub fn pack_get(&self,name_lowercase:&str)->Result<Option<Vec<u8>>,vbsp::BspError>{ + match self.case_folded_file_names.get(name_lowercase){ + Some(name_folded)=>self.bsp.pack.get(name_folded), + None=>Ok(None), + } + } + pub fn to_snf(&self,failure_mode:LoadFailureMode,vpk_list:&[Vpk])->Result<strafesnet_common::map::CompleteMap,LoadError>{ let mut texture_deferred_loader=RenderConfigDeferredLoader::new(); let mut mesh_deferred_loader=MeshDeferredLoader::new(); @@ -89,3 +100,27 @@ impl Bsp{ Ok(map) } } +pub struct Vpk{ + vpk:vpk::VPK, + case_folded_file_names:std::collections::HashMap<String,String>, +} +impl AsRef<vpk::VPK> for Vpk{ + fn as_ref(&self)->&vpk::VPK{ + &self.vpk + } +} +impl Vpk{ + pub fn new(vpk:vpk::VPK)->Vpk{ + let case_folded_file_names=vpk.tree.keys().map(|s|{ + (s.to_lowercase(),s.to_owned()) + }).collect(); + Vpk{ + vpk, + case_folded_file_names, + } + } + pub fn tree_get(&self,name_lowercase:&str)->Option<&vpk::entry::VPKEntry>{ + let name_folded=self.case_folded_file_names.get(name_lowercase)?; + self.vpk.tree.get(name_folded) + } +} diff --git a/lib/bsp_loader/src/loader.rs b/lib/bsp_loader/src/loader.rs index 9117bd4..2a83a64 100644 --- a/lib/bsp_loader/src/loader.rs +++ b/lib/bsp_loader/src/loader.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, io::Read}; use strafesnet_common::model::Mesh; use strafesnet_deferred_loader::{loader::Loader,texture::Texture}; -use crate::Bsp; +use crate::{Bsp,Vpk}; #[allow(dead_code)] #[derive(Debug)] @@ -76,7 +76,7 @@ impl From<vbsp::BspError> for MeshError{ #[derive(Clone,Copy)] pub struct BspFinder<'bsp,'vpk>{ pub bsp:&'bsp Bsp, - pub vpks:&'vpk [vpk::VPK], + pub vpks:&'vpk [Vpk], } impl<'bsp,'vpk> BspFinder<'bsp,'vpk>{ pub fn find<'a>(&self,path:&str)->Result<Option<Cow<'a,[u8]>>,vbsp::BspError> @@ -85,13 +85,13 @@ impl<'bsp,'vpk> BspFinder<'bsp,'vpk>{ 'vpk:'a, { // search bsp - if let Some(data)=self.bsp.as_ref().pack.get(path)?{ + if let Some(data)=self.bsp.pack_get(path)?{ return Ok(Some(Cow::Owned(data))); } //search each vpk for vpk in self.vpks{ - if let Some(vpk_entry)=vpk.tree.get(path){ + if let Some(vpk_entry)=vpk.tree_get(path){ return Ok(Some(vpk_entry.get()?)); } } diff --git a/map-tool/src/source.rs b/map-tool/src/source.rs index fa481ec..736804b 100644 --- a/map-tool/src/source.rs +++ b/map-tool/src/source.rs @@ -228,7 +228,7 @@ enum ExtractTextureError{ #[error("Load VMT error {0:?}")] LoadVMT(#[from]LoadVMTError), } -async fn gimme_them_textures(path:&Path,vpk_list:&[vpk::VPK],send_texture:tokio::sync::mpsc::Sender<(Vec<u8>,String)>)->Result<(),ExtractTextureError>{ +async fn gimme_them_textures(path:&Path,vpk_list:&[strafesnet_bsp_loader::Vpk],send_texture:tokio::sync::mpsc::Sender<(Vec<u8>,String)>)->Result<(),ExtractTextureError>{ let bsp=vbsp::Bsp::read(tokio::fs::read(path).await?.as_ref())?; let loader_bsp=strafesnet_bsp_loader::Bsp::new(bsp); let bsp=loader_bsp.as_ref(); @@ -323,10 +323,10 @@ async fn convert_texture(texture:Vec<u8>,write_file_name:impl AsRef<Path>)->Resu Ok(()) } -async fn read_vpks(vpk_paths:Vec<PathBuf>,thread_limit:usize)->Vec<vpk::VPK>{ +async fn read_vpks(vpk_paths:Vec<PathBuf>,thread_limit:usize)->Vec<strafesnet_bsp_loader::Vpk>{ futures::stream::iter(vpk_paths).map(|vpk_path|async{ // idk why it doesn't want to pass out the errors but this is fatal anyways - tokio::task::spawn_blocking(move||vpk::VPK::read(&vpk_path)).await.unwrap().unwrap() + tokio::task::spawn_blocking(move||Ok::<_,vpk::Error>(strafesnet_bsp_loader::Vpk::new(vpk::VPK::read(&vpk_path)?))).await.unwrap().unwrap() }) .buffer_unordered(thread_limit) .collect().await @@ -340,11 +340,8 @@ async fn extract_textures(paths:Vec<PathBuf>,vpk_paths:Vec<PathBuf>)->AResult<() )?; let thread_limit=std::thread::available_parallelism()?.get(); - // load vpk list - let vpk_list=read_vpks(vpk_paths,thread_limit).await; - - // leak vpk_list for static lifetime? - let vpk_list:&[vpk::VPK]=vpk_list.leak(); + // load vpk list and leak for static lifetime + let vpk_list:&[strafesnet_bsp_loader::Vpk]=read_vpks(vpk_paths,thread_limit).await.leak(); let (send_texture,mut recv_texture)=tokio::sync::mpsc::channel(thread_limit); let mut it=paths.into_iter(); @@ -414,7 +411,7 @@ impl std::fmt::Display for ConvertError{ } impl std::error::Error for ConvertError{} -async fn convert_to_snf(path:&Path,vpk_list:&[vpk::VPK],output_folder:PathBuf)->AResult<()>{ +async fn convert_to_snf(path:&Path,vpk_list:&[strafesnet_bsp_loader::Vpk],output_folder:PathBuf)->AResult<()>{ let entire_file=tokio::fs::read(path).await?; let bsp=strafesnet_bsp_loader::read( @@ -437,11 +434,8 @@ async fn source_to_snf(paths:Vec<std::path::PathBuf>,output_folder:PathBuf,vpk_p let thread_limit=std::thread::available_parallelism()?.get(); - // load vpk list - let vpk_list=read_vpks(vpk_paths,thread_limit).await; - - // leak vpk_list for static lifetime? - let vpk_list:&[vpk::VPK]=vpk_list.leak(); + // load vpk list and leak for static lifetime + let vpk_list:&[strafesnet_bsp_loader::Vpk]=read_vpks(vpk_paths,thread_limit).await.leak(); let mut it=paths.into_iter(); static SEM:tokio::sync::Semaphore=tokio::sync::Semaphore::const_new(0);