From fc90a986e536f40f34c40321f99845de5d5a704c Mon Sep 17 00:00:00 2001
From: Quaternions <krakow20@gmail.com>
Date: Mon, 3 Feb 2025 14:05:39 -0800
Subject: [PATCH] fin

---
 src/source.rs | 37 +++++++++++++++++++++++++------------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/src/source.rs b/src/source.rs
index 95c11e7..60a3464 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -21,13 +21,15 @@ pub struct SourceToSNFSubcommand {
 	output_folder:PathBuf,
 	#[arg(required=true)]
 	input_files:Vec<PathBuf>,
+	#[arg(long)]
+	vpk_dir_files:Vec<PathBuf>,
 }
 #[derive(Args)]
 pub struct ExtractTexturesSubcommand{
 	#[arg(required=true)]
 	bsp_files:Vec<PathBuf>,
 	#[arg(long)]
-	vpk_dir_file:Vec<PathBuf>,
+	vpk_dir_files:Vec<PathBuf>,
 }
 #[derive(Args)]
 pub struct VPKContentsSubcommand {
@@ -43,8 +45,8 @@ pub struct BSPContentsSubcommand {
 impl Commands{
 	pub async fn run(self)->AResult<()>{
 		match self{
-			Commands::SourceToSNF(subcommand)=>source_to_snf(subcommand.input_files,subcommand.output_folder).await,
-			Commands::ExtractTextures(subcommand)=>extract_textures(subcommand.bsp_files,subcommand.vpk_dir_file).await,
+			Commands::SourceToSNF(subcommand)=>source_to_snf(subcommand.input_files,subcommand.output_folder,subcommand.vpk_dir_files).await,
+			Commands::ExtractTextures(subcommand)=>extract_textures(subcommand.bsp_files,subcommand.vpk_dir_files).await,
 			Commands::VPKContents(subcommand)=>vpk_contents(subcommand.input_file),
 			Commands::BSPContents(subcommand)=>bsp_contents(subcommand.input_file),
 		}
@@ -280,6 +282,15 @@ 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>{
+	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()
+	})
+	.buffer_unordered(thread_limit)
+	.collect().await
+}
+
 async fn extract_textures(paths:Vec<PathBuf>,vpk_paths:Vec<PathBuf>)->AResult<()>{
 	tokio::try_join!(
 		tokio::fs::create_dir_all("extracted_textures"),
@@ -289,15 +300,10 @@ 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=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()
-	})
-	.buffer_unordered(thread_limit)
-	.collect::<Vec<vpk::VPK>>().await;
+	let vpk_list=read_vpks(vpk_paths,thread_limit).await;
 
 	// leak vpk_list for static lifetime?
-	let vpk_list=vpk_list.leak();
+	let vpk_list:&[vpk::VPK]=vpk_list.leak();
 
 	let (send_texture,mut recv_texture)=tokio::sync::mpsc::channel(thread_limit);
 	let mut it=paths.into_iter();
@@ -378,10 +384,17 @@ async fn convert_to_snf(path:&Path,vpk_list:&[vpk::VPK],output_folder:PathBuf)->
 
 	Ok(())
 }
-async fn source_to_snf(paths:Vec<std::path::PathBuf>,output_folder:PathBuf)->AResult<()>{
+async fn source_to_snf(paths:Vec<std::path::PathBuf>,output_folder:PathBuf,vpk_paths:Vec<PathBuf>)->AResult<()>{
 	let start=std::time::Instant::now();
 
 	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();
+
 	let mut it=paths.into_iter();
 	static SEM:tokio::sync::Semaphore=tokio::sync::Semaphore::const_new(0);
 	SEM.add_permits(thread_limit);
@@ -389,7 +402,7 @@ async fn source_to_snf(paths:Vec<std::path::PathBuf>,output_folder:PathBuf)->ARe
 	while let (Ok(permit),Some(path))=(SEM.acquire().await,it.next()){
 		let output_folder=output_folder.clone();
 		tokio::spawn(async move{
-			let result=convert_to_snf(path.as_path(),output_folder).await;
+			let result=convert_to_snf(path.as_path(),vpk_list,output_folder).await;
 			drop(permit);
 			match result{
 				Ok(())=>(),