Compare commits

...

3 Commits

Author SHA1 Message Date
c7c57c1527 naive multithread 2024-07-26 18:21:56 -07:00
7cc018e61e map converter 2024-07-25 17:48:44 -07:00
fdc5cccc6d prototype snf code 2024-07-25 16:13:15 -07:00
3 changed files with 98 additions and 1 deletions

9
Cargo.lock generated
View File

@ -790,6 +790,7 @@ dependencies = [
"rbx_dom_weak",
"rbx_reflection_database",
"rbx_xml",
"strafesnet_snf",
"vbsp",
"vmdl",
"vmt-parser",
@ -1334,6 +1335,14 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strafesnet_snf"
version = "0.1.0"
source = "git+https://git.itzana.me/StrafesNET/snf?rev=dea408daeef576cff8ffa61356c89a9d03d95f6b#dea408daeef576cff8ffa61356c89a9d03d95f6b"
dependencies = [
"binrw",
]
[[package]]
name = "strsim"
version = "0.10.0"

View File

@ -16,6 +16,9 @@ rbx_binary = "0.7.1"
rbx_dom_weak = "2.5.0"
rbx_reflection_database = "0.2.7"
rbx_xml = "0.13.1"
strafesnet_bsp_loader = { git = "https://git.itzana.me/StrafesNET/bsp_loader", rev = "79b8120106e63de237b8ed59c3d3e30db51e7146" }
strafesnet_rbx_loader = { git = "https://git.itzana.me/StrafesNET/rbx_loader", rev = "0d2c27f60f4a448063edc57d9a23766775fb2cc5" }
strafesnet_snf = { git = "https://git.itzana.me/StrafesNET/snf", rev = "dea408daeef576cff8ffa61356c89a9d03d95f6b" }
vbsp = "0.5.0"
vmdl = "0.1.1"
vmt-parser = "0.1.1"

View File

@ -13,6 +13,7 @@ struct Cli {
#[derive(Subcommand)]
enum Commands {
RobloxToSNF(RobloxToSNFSubcommand),
DownloadTextures(DownloadTexturesSubcommand),
ExtractTextures(ExtractTexturesSubcommand),
ConvertTextures(ConvertTexturesSubcommand),
@ -22,6 +23,13 @@ enum Commands {
WriteAttributes(WriteAttributesSubcommand),
}
#[derive(Args)]
struct RobloxToSNFSubcommand {
#[arg(long)]
output_folder:PathBuf,
#[arg(required=true)]
input_files:Vec<PathBuf>,
}
#[derive(Args)]
struct DownloadTexturesSubcommand {
#[arg(long,required=true)]
@ -59,6 +67,7 @@ struct WriteAttributesSubcommand {
fn main() -> AResult<()> {
let cli = Cli::parse();
match cli.command {
Commands::RobloxToSNF(subcommand)=>convert_to_snf(subcommand.input_files,subcommand.output_folder),
Commands::DownloadTextures(subcommand)=>download_textures(subcommand.roblox_files),
Commands::ExtractTextures(subcommand)=>extract_textures(vec![subcommand.bsp_file],subcommand.vpk_dir_files),
Commands::VPKContents(subcommand)=>vpk_contents(subcommand.input_file),
@ -630,4 +639,80 @@ fn bsp_contents(path:PathBuf)->AResult<()>{
println!("file_name={:?}",file_name);
}
Ok(())
}
}
#[derive(Debug)]
enum ConvertError{
IO(std::io::Error),
SNFMap(strafesnet_snf::map::Error),
RbxLoader(strafesnet_rbx_loader::ReadError),
}
impl std::fmt::Display for ConvertError{
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
write!(f,"{self:?}")
}
}
impl std::error::Error for ConvertError{}
fn convert_to_snf(pathlist:Vec<std::path::PathBuf>,output_folder:PathBuf)->AResult<()>{
let start = std::time::Instant::now();
let mut threads:Vec<std::thread::JoinHandle<Result<(),ConvertError>>>=Vec::new();
for path in pathlist{
let output_folder=output_folder.clone();
threads.push(std::thread::spawn(move ||{
let dom=strafesnet_rbx_loader::read(
std::fs::File::open(path.as_path())
.map_err(ConvertError::IO)?
).map_err(ConvertError::RbxLoader)?;
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(ConvertError::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(ConvertError::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,
})
)
);
let mut dest=output_folder.clone();
dest.push(path.file_stem().unwrap());
dest.set_extension("snfm");
let file=std::fs::File::create(dest).map_err(ConvertError::IO)?;
strafesnet_snf::map::write_map(file,map).map_err(ConvertError::SNFMap)?;
Ok(())
}));
}
let mut i=0;
let n_threads=threads.len();
for thread in threads{
i+=1;
if let Err(e)=thread.join(){
println!("thread error: {:?}",e);
}else{
println!("{}/{}",i,n_threads);
}
}
println!("{:?}", start.elapsed());
Ok(())
}