forked from StrafesNET/map-tool
more texture sources + use asset tool to download meshes & textures
This commit is contained in:
parent
0172675b04
commit
95b6272b18
179
src/main.rs
179
src/main.rs
@ -1,6 +1,7 @@
|
|||||||
use std::{io::{Read, Seek}, path::PathBuf};
|
use std::{collections::HashSet,io::{Read,Seek},path::PathBuf};
|
||||||
use clap::{Args,Parser,Subcommand};
|
use clap::{Args,Parser,Subcommand};
|
||||||
use anyhow::Result as AResult;
|
use anyhow::Result as AResult;
|
||||||
|
use rbx_dom_weak::Instance;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[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<rbx_dom_weak::types::Ref>,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<rbx_dom_weak::types::Ref>,dom: &rbx_dom_weak::WeakDom, instance: &rbx_dom_weak::Instance, regex: &lazy_regex::Lazy<lazy_regex::Regex>){
|
fn recursive_collect_regex(objects: &mut std::vec::Vec<rbx_dom_weak::types::Ref>,dom: &rbx_dom_weak::WeakDom, instance: &rbx_dom_weak::Instance, regex: &lazy_regex::Lazy<lazy_regex::Regex>){
|
||||||
for &referent in instance.children() {
|
for &referent in instance.children() {
|
||||||
if let Some(c) = dom.get_by_ref(referent) {
|
if let Some(c) = dom.get_by_ref(referent) {
|
||||||
@ -100,23 +79,6 @@ fn get_button_refs(dom:&rbx_dom_weak::WeakDom) -> Vec<rbx_dom_weak::types::Ref>{
|
|||||||
recursive_collect_regex(&mut buttons, dom, dom.root(),lazy_regex::regex!(r"Button(\d+)$"));
|
recursive_collect_regex(&mut buttons, dom, dom.root(),lazy_regex::regex!(r"Button(\d+)$"));
|
||||||
buttons
|
buttons
|
||||||
}
|
}
|
||||||
fn get_texture_refs(dom:&rbx_dom_weak::WeakDom) -> Vec<rbx_dom_weak::types::Ref>{
|
|
||||||
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<rbx_dom_weak::types::Ref>{
|
|
||||||
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>{
|
enum ReaderType<'a, R:Read+Seek>{
|
||||||
GZip(flate2::read::GzDecoder<&'a mut R>),
|
GZip(flate2::read::GzDecoder<&'a mut R>),
|
||||||
@ -208,94 +170,99 @@ SurfaceAppearance.NormalMap
|
|||||||
SurfaceAppearance.RoughnessMap
|
SurfaceAppearance.RoughnessMap
|
||||||
SurfaceAppearance.TexturePack
|
SurfaceAppearance.TexturePack
|
||||||
*/
|
*/
|
||||||
|
fn accumulate_content_id(content_list:&mut HashSet<u64>,object:&Instance,property:&str){
|
||||||
|
if let Some(rbx_dom_weak::types::Variant::Content(content))=object.properties.get(property){
|
||||||
|
if let Ok(asset_id)=AsRef::<str>::as_ref(content).parse::<RobloxAssetId>(){
|
||||||
|
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<PathBuf>)->AResult<()>{
|
fn download_textures(paths:Vec<PathBuf>)->AResult<()>{
|
||||||
println!("download_textures paths:{:?}",paths);
|
println!("Reading files, this could take a hot minute...");
|
||||||
let header=format!("Cookie: .ROBLOSECURITY={}",std::env::var("RBXCOOKIE")?);
|
let mut texture_list=HashSet::new();
|
||||||
let shared_args=&[
|
|
||||||
"-q",
|
|
||||||
"--header",
|
|
||||||
header.as_str(),
|
|
||||||
"-O",
|
|
||||||
];
|
|
||||||
let mut texture_list=std::collections::HashSet::new();
|
|
||||||
for path in paths{
|
for path in paths{
|
||||||
let mut input = std::io::BufReader::new(std::fs::File::open(path.clone())?);
|
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){
|
match get_dom(&mut input){
|
||||||
Ok(dom)=>{
|
Ok(dom)=>{
|
||||||
let object_refs = get_texture_refs(&dom);
|
for object in dom.into_raw().1.into_values(){
|
||||||
for &object_ref in object_refs.iter() {
|
match object.class.as_str(){
|
||||||
if let Some(object)=dom.get_by_ref(object_ref){
|
"Beam"=>accumulate_content_id(&mut texture_list,&object,"Texture"),
|
||||||
if let Some(rbx_dom_weak::types::Variant::Content(content)) = object.properties.get("Texture") {
|
"Decal"=>accumulate_content_id(&mut texture_list,&object,"Texture"),
|
||||||
println!("Texture content:{:?}",content);
|
"Texture"=>accumulate_content_id(&mut texture_list,&object,"Texture"),
|
||||||
if let Ok(asset_id)=content.clone().into_string().parse::<RobloxAssetId>(){
|
"FileMesh"=>accumulate_content_id(&mut texture_list,&object,"TextureId"),
|
||||||
texture_list.insert(asset_id.0);
|
"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),
|
Err(e)=>println!("error loading map {:?}: {:?}",path.file_name(),e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("Texture list:{:?}",texture_list);
|
let texture_list_string=texture_list.into_iter().map(|id|id.to_string()).collect::<Vec<String>>();
|
||||||
let processes_result:Result<Vec<_>, _>=texture_list.iter().map(|asset_id|{
|
println!("Texture list:{:?}",texture_list_string.join(" "));
|
||||||
std::process::Command::new("wget")
|
let output=std::process::Command::new("asset-tool")
|
||||||
.args(shared_args)
|
.args(["download","environment","RBXCOOKIE","textures/unprocessed/"])
|
||||||
.arg(format!("textures/unprocessed/{}",asset_id))
|
.args(texture_list_string)
|
||||||
.arg(format!("https://assetdelivery.roblox.com/v1/asset/?ID={}",asset_id))
|
.spawn()?
|
||||||
.spawn()
|
.wait_with_output()?;
|
||||||
}).collect();
|
println!("Asset tool exit_success:{}",output.status.success());
|
||||||
//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());
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn download_meshes(paths:Vec<PathBuf>)->AResult<()>{
|
fn download_meshes(paths:Vec<PathBuf>)->AResult<()>{
|
||||||
println!("download_meshes paths:{:?}",paths);
|
println!("Reading files, this could take a hot minute...");
|
||||||
let header=format!("Cookie: .ROBLOSECURITY={}",std::env::var("RBXCOOKIE")?);
|
let mut mesh_list=HashSet::new();
|
||||||
let shared_args=&[
|
|
||||||
"-q",
|
|
||||||
"--header",
|
|
||||||
header.as_str(),
|
|
||||||
"-O",
|
|
||||||
];
|
|
||||||
let mut mesh_list=std::collections::HashSet::new();
|
|
||||||
for path in paths{
|
for path in paths{
|
||||||
let mut input = std::io::BufReader::new(std::fs::File::open(path.clone())?);
|
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){
|
match get_dom(&mut input){
|
||||||
Ok(dom)=>{
|
Ok(dom)=>{
|
||||||
let object_refs = get_mesh_refs(&dom);
|
for object in dom.into_raw().1.into_values(){
|
||||||
for &object_ref in object_refs.iter() {
|
match object.class.as_str(){
|
||||||
if let Some(object)=dom.get_by_ref(object_ref){
|
"MeshPart"=>accumulate_content_id(&mut mesh_list,&object,"MeshId"),
|
||||||
if let Some(rbx_dom_weak::types::Variant::Content(content)) = object.properties.get("MeshId") {
|
"SpecialMesh"=>accumulate_content_id(&mut mesh_list,&object,"MeshId"),
|
||||||
println!("Mesh content:{:?}",content);
|
_=>(),
|
||||||
if let Ok(asset_id)=content.clone().into_string().parse::<RobloxAssetId>(){
|
|
||||||
mesh_list.insert(asset_id.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e)=>println!("error loading map {:?}: {:?}",path.file_name(),e),
|
Err(e)=>println!("error loading map {:?}: {:?}",path.file_name(),e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("Mesh list:{:?}",mesh_list);
|
let mesh_list_string=mesh_list.into_iter().map(|id|id.to_string()).collect::<Vec<String>>();
|
||||||
let processes_result:Result<Vec<_>, _>=mesh_list.iter().map(|asset_id|{
|
println!("Mesh list:{:?}",mesh_list_string.join(" "));
|
||||||
std::process::Command::new("wget")
|
let output=std::process::Command::new("asset-tool")
|
||||||
.args(shared_args)
|
.args(["download","environment","RBXCOOKIE","meshes/"])
|
||||||
.arg(format!("meshes/unprocessed/{}",asset_id))
|
.args(mesh_list_string)
|
||||||
.arg(format!("https://assetdelivery.roblox.com/v1/asset/?ID={}",asset_id))
|
.spawn()?
|
||||||
.spawn()
|
.wait_with_output()?;
|
||||||
}).collect();
|
println!("Asset tool exit_success:{}",output.status.success());
|
||||||
//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());
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user