diff --git a/src/main.rs b/src/main.rs index 7504300..192f599 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ -use std::{io::{Read, Seek}, path::PathBuf}; -use clap::{Args, Parser, Subcommand}; +use std::{collections::HashSet,io::{Read,Seek},path::PathBuf}; +use clap::{Args,Parser,Subcommand}; use anyhow::Result as AResult; +use rbx_dom_weak::Instance; #[derive(Parser)] #[command(author, version, about, long_about = None)] @@ -62,28 +63,6 @@ fn main() -> AResult<()> { } } -fn class_is_a(class: &str, superclass: &str) -> bool { - if class==superclass { - return true - } - let class_descriptor=rbx_reflection_database::get().classes.get(class); - if let Some(descriptor) = &class_descriptor { - if let Some(class_super) = &descriptor.superclass { - return class_is_a(&class_super, superclass) - } - } - false -} -fn recursive_collect_superclass(objects: &mut std::vec::Vec,dom: &rbx_dom_weak::WeakDom, instance: &rbx_dom_weak::Instance, superclass: &str){ - for &referent in instance.children() { - if let Some(c) = dom.get_by_ref(referent) { - if class_is_a(c.class.as_str(), superclass) { - objects.push(c.referent());//copy ref - } - recursive_collect_superclass(objects,dom,c,superclass); - } - } -} fn recursive_collect_regex(objects: &mut std::vec::Vec,dom: &rbx_dom_weak::WeakDom, instance: &rbx_dom_weak::Instance, regex: &lazy_regex::Lazy){ for &referent in instance.children() { if let Some(c) = dom.get_by_ref(referent) { @@ -100,23 +79,6 @@ fn get_button_refs(dom:&rbx_dom_weak::WeakDom) -> Vec{ recursive_collect_regex(&mut buttons, dom, dom.root(),lazy_regex::regex!(r"Button(\d+)$")); buttons } -fn get_texture_refs(dom:&rbx_dom_weak::WeakDom) -> Vec{ - let mut objects = std::vec::Vec::new(); - recursive_collect_superclass(&mut objects, dom, dom.root(),"Decal"); - //get ids - //clear vec - //next class - objects -} -fn get_mesh_refs(dom:&rbx_dom_weak::WeakDom) -> Vec{ - let mut objects = std::vec::Vec::new(); - recursive_collect_superclass(&mut objects, dom, dom.root(),"FileMesh"); - recursive_collect_superclass(&mut objects, dom, dom.root(),"MeshPart"); - //get ids - //clear vec - //next class - objects -} enum ReaderType<'a, R:Read+Seek>{ GZip(flate2::read::GzDecoder<&'a mut R>), @@ -208,94 +170,99 @@ SurfaceAppearance.NormalMap SurfaceAppearance.RoughnessMap SurfaceAppearance.TexturePack */ -fn download_textures(paths: Vec) -> AResult<()>{ - println!("download_textures paths:{:?}",paths); - let header=format!("Cookie: .ROBLOSECURITY={}",std::env::var("RBXCOOKIE")?); - let shared_args=&[ - "-q", - "--header", - header.as_str(), - "-O", - ]; - let mut texture_list=std::collections::HashSet::new(); - for path in paths { - let mut input = std::io::BufReader::new(std::fs::File::open(path.clone())?); - +fn accumulate_content_id(content_list:&mut HashSet,object:&Instance,property:&str){ + if let Some(rbx_dom_weak::types::Variant::Content(content))=object.properties.get(property){ + if let Ok(asset_id)=AsRef::::as_ref(content).parse::(){ + content_list.insert(asset_id.0); + }else{ + println!("Content failed to parse into AssetID: {:?}",content); + } + }else{ + println!("property={} does not exist for class={}",object.class.as_str(),property); + } +} +fn download_textures(paths:Vec)->AResult<()>{ + println!("Reading files, this could take a hot minute..."); + let mut texture_list=HashSet::new(); + for path in paths{ + let file=match std::fs::File::open(path.as_path()){ + Ok(file)=>file, + Err(e)=>{ + println!("file error {e}"); + continue; + } + }; + let mut input=std::io::BufReader::new(file); match get_dom(&mut input){ Ok(dom)=>{ - let object_refs = get_texture_refs(&dom); - for &object_ref in object_refs.iter() { - if let Some(object)=dom.get_by_ref(object_ref){ - if let Some(rbx_dom_weak::types::Variant::Content(content)) = object.properties.get("Texture") { - println!("Texture content:{:?}",content); - if let Ok(asset_id)=content.clone().into_string().parse::(){ - texture_list.insert(asset_id.0); - } - } + for object in dom.into_raw().1.into_values(){ + match object.class.as_str(){ + "Beam"=>accumulate_content_id(&mut texture_list,&object,"Texture"), + "Decal"=>accumulate_content_id(&mut texture_list,&object,"Texture"), + "Texture"=>accumulate_content_id(&mut texture_list,&object,"Texture"), + "FileMesh"=>accumulate_content_id(&mut texture_list,&object,"TextureId"), + "MeshPart"=>accumulate_content_id(&mut texture_list,&object,"TextureID"), + "ParticleEmitter"=>accumulate_content_id(&mut texture_list,&object,"Texture"), + "Sky"=>{ + accumulate_content_id(&mut texture_list,&object,"MoonTextureId"); + accumulate_content_id(&mut texture_list,&object,"SkyboxBk"); + accumulate_content_id(&mut texture_list,&object,"SkyboxDn"); + accumulate_content_id(&mut texture_list,&object,"SkyboxFt"); + accumulate_content_id(&mut texture_list,&object,"SkyboxLf"); + accumulate_content_id(&mut texture_list,&object,"SkyboxRt"); + accumulate_content_id(&mut texture_list,&object,"SkyboxUp"); + accumulate_content_id(&mut texture_list,&object,"SunTextureId"); + }, + _=>(), } } }, Err(e)=>println!("error loading map {:?}: {:?}",path.file_name(),e), } } - println!("Texture list:{:?}",texture_list); - let processes_result:Result, _>=texture_list.iter().map(|asset_id|{ - std::process::Command::new("wget") - .args(shared_args) - .arg(format!("textures/unprocessed/{}",asset_id)) - .arg(format!("https://assetdelivery.roblox.com/v1/asset/?ID={}",asset_id)) - .spawn() - }).collect(); - //naively wait for all because idk how to make an async progress bar lmao - for child in processes_result?{ - let output=child.wait_with_output()?; - println!("texture exit_success:{}",output.status.success()); - } + let texture_list_string=texture_list.into_iter().map(|id|id.to_string()).collect::>(); + println!("Texture list:{:?}",texture_list_string.join(" ")); + let output=std::process::Command::new("asset-tool") + .args(["download","environment","RBXCOOKIE","textures/unprocessed/"]) + .args(texture_list_string) + .spawn()? + .wait_with_output()?; + println!("Asset tool exit_success:{}",output.status.success()); Ok(()) } -fn download_meshes(paths: Vec) -> AResult<()>{ - println!("download_meshes paths:{:?}",paths); - let header=format!("Cookie: .ROBLOSECURITY={}",std::env::var("RBXCOOKIE")?); - let shared_args=&[ - "-q", - "--header", - header.as_str(), - "-O", - ]; - let mut mesh_list=std::collections::HashSet::new(); - for path in paths { - let mut input = std::io::BufReader::new(std::fs::File::open(path.clone())?); - +fn download_meshes(paths:Vec)->AResult<()>{ + println!("Reading files, this could take a hot minute..."); + let mut mesh_list=HashSet::new(); + for path in paths{ + let file=match std::fs::File::open(path.as_path()){ + Ok(file)=>file, + Err(e)=>{ + println!("file error {e}"); + continue; + } + }; + let mut input=std::io::BufReader::new(file); match get_dom(&mut input){ Ok(dom)=>{ - let object_refs = get_mesh_refs(&dom); - for &object_ref in object_refs.iter() { - if let Some(object)=dom.get_by_ref(object_ref){ - if let Some(rbx_dom_weak::types::Variant::Content(content)) = object.properties.get("MeshId") { - println!("Mesh content:{:?}",content); - if let Ok(asset_id)=content.clone().into_string().parse::(){ - mesh_list.insert(asset_id.0); - } - } + for object in dom.into_raw().1.into_values(){ + match object.class.as_str(){ + "MeshPart"=>accumulate_content_id(&mut mesh_list,&object,"MeshId"), + "SpecialMesh"=>accumulate_content_id(&mut mesh_list,&object,"MeshId"), + _=>(), } } }, Err(e)=>println!("error loading map {:?}: {:?}",path.file_name(),e), } } - println!("Mesh list:{:?}",mesh_list); - let processes_result:Result, _>=mesh_list.iter().map(|asset_id|{ - std::process::Command::new("wget") - .args(shared_args) - .arg(format!("meshes/unprocessed/{}",asset_id)) - .arg(format!("https://assetdelivery.roblox.com/v1/asset/?ID={}",asset_id)) - .spawn() - }).collect(); - //naively wait for all because idk how to make an async progress bar lmao - for child in processes_result?{ - let output=child.wait_with_output()?; - println!("Mesh exit_success:{}",output.status.success()); - } + let mesh_list_string=mesh_list.into_iter().map(|id|id.to_string()).collect::>(); + println!("Mesh list:{:?}",mesh_list_string.join(" ")); + let output=std::process::Command::new("asset-tool") + .args(["download","environment","RBXCOOKIE","meshes/"]) + .args(mesh_list_string) + .spawn()? + .wait_with_output()?; + println!("Asset tool exit_success:{}",output.status.success()); Ok(()) }