forked from StrafesNET/asset-tool
write colossal code
This commit is contained in:
parent
1ea68d96ef
commit
4fd7795457
113
src/main.rs
113
src/main.rs
@ -168,6 +168,7 @@ async fn main()->AResult<()>{
|
|||||||
input_folder:cli.input.unwrap(),
|
input_folder:cli.input.unwrap(),
|
||||||
output_file:cli.output.unwrap(),
|
output_file:cli.output.unwrap(),
|
||||||
template:None,
|
template:None,
|
||||||
|
style:None,
|
||||||
}).await,
|
}).await,
|
||||||
Commands::Decompile=>decompile(DecompileConfig{
|
Commands::Decompile=>decompile(DecompileConfig{
|
||||||
style:decompile_style.unwrap(),
|
style:decompile_style.unwrap(),
|
||||||
@ -1275,11 +1276,12 @@ fn extract_script_overrides(mut source:String)->AResult<ScriptWithOverrides>{
|
|||||||
Ok(ScriptWithOverrides{overrides,source:source.split_off(count)})
|
Ok(ScriptWithOverrides{overrides,source:source.split_off(count)})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn discern_node(search_path:&std::path::PathBuf,search_name:&str,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{
|
async fn discern_node(entry:&tokio::fs::DirEntry,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{
|
||||||
let mut contents_folder=search_path.clone();
|
let contents_folder=entry.path();
|
||||||
contents_folder.push(search_name);
|
let file_name=entry.file_name();
|
||||||
//folder
|
//folder
|
||||||
Ok(if let Ok(dir)=tokio::fs::read_dir(contents_folder.as_path()).await{
|
Ok(if let Ok(dir)=tokio::fs::read_dir(contents_folder.as_path()).await{
|
||||||
|
let search_name=file_name.to_str().unwrap();
|
||||||
//scan inside the folder for an object to define the class of the folder
|
//scan inside the folder for an object to define the class of the folder
|
||||||
let script_query=async {match style{
|
let script_query=async {match style{
|
||||||
Some(DecompileStyle::Rox)=>QuerySingle::rox(&contents_folder,search_name).resolve().await,
|
Some(DecompileStyle::Rox)=>QuerySingle::rox(&contents_folder,search_name).resolve().await,
|
||||||
@ -1345,6 +1347,12 @@ async fn discern_node(search_path:&std::path::PathBuf,search_name:&str,style:Opt
|
|||||||
None
|
None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn discern_file(entry:&tokio::fs::DirEntry,style:Option<DecompileStyle>)->AResult<Option<CompileNode>>{
|
||||||
|
todo!();
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum ScriptHint{
|
enum ScriptHint{
|
||||||
Script,
|
Script,
|
||||||
@ -1357,6 +1365,11 @@ struct FileHint{
|
|||||||
hint:ScriptHint,
|
hint:ScriptHint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PreparedData{
|
||||||
|
Model(rbx_dom_weak::WeakDom),
|
||||||
|
Builder(rbx_dom_weak::InstanceBuilder),
|
||||||
|
}
|
||||||
|
|
||||||
enum CompileClass{
|
enum CompileClass{
|
||||||
Folder,
|
Folder,
|
||||||
Script(String),
|
Script(String),
|
||||||
@ -1372,8 +1385,7 @@ struct CompileNode{
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum CompileStackInstruction{
|
enum CompileStackInstruction{
|
||||||
Referent(rbx_dom_weak::types::Ref),
|
TraverseReferent(rbx_dom_weak::types::Ref),
|
||||||
PushFolder(String),
|
|
||||||
PopFolder,
|
PopFolder,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1381,6 +1393,14 @@ struct CompileConfig{
|
|||||||
input_folder:std::path::PathBuf,
|
input_folder:std::path::PathBuf,
|
||||||
output_file:std::path::PathBuf,
|
output_file:std::path::PathBuf,
|
||||||
template:Option<std::path::PathBuf>,
|
template:Option<std::path::PathBuf>,
|
||||||
|
style:Option<DecompileStyle>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn script_builder(class:&str,name:&str,source:String)->rbx_dom_weak::InstanceBuilder{
|
||||||
|
let mut builder=rbx_dom_weak::InstanceBuilder::new(class);
|
||||||
|
builder.set_name(name);
|
||||||
|
builder.add_property("Source",rbx_dom_weak::types::Variant::String(source));
|
||||||
|
builder
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn compile(config:CompileConfig)->AResult<()>{
|
async fn compile(config:CompileConfig)->AResult<()>{
|
||||||
@ -1400,28 +1420,81 @@ async fn compile(config:CompileConfig)->AResult<()>{
|
|||||||
//add in scripts and models
|
//add in scripts and models
|
||||||
let mut folder=config.input_folder.clone();
|
let mut folder=config.input_folder.clone();
|
||||||
folder.push("src");
|
folder.push("src");
|
||||||
let mut stack:Vec<CompileStackInstruction>=dom.root().children().into_iter().map(|&referent|CompileStackInstruction::Referent(referent)).collect();
|
let mut stack:Vec<CompileStackInstruction>=dom.root().children().into_iter().map(|&referent|CompileStackInstruction::TraverseReferent(referent)).collect();
|
||||||
while let Some(instruction)=stack.pop(){
|
while let Some(instruction)=stack.pop(){
|
||||||
match instruction{
|
match instruction{
|
||||||
CompileStackInstruction::Referent(item_ref)=>{
|
CompileStackInstruction::TraverseReferent(item_ref)=>{
|
||||||
|
let sans={
|
||||||
let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?;
|
let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?;
|
||||||
//check if item exists in folder or subfolder of same name
|
sanitize(item.name.as_str()).to_string()
|
||||||
todo!("this is totally unnecessary,
|
};
|
||||||
only the folder needs to exist to determine if traversal should continue");
|
folder.push(sans.as_str());
|
||||||
if let Some(obj)=discern_node(&folder,item.name.as_str(),None).await?{
|
|
||||||
//cool
|
|
||||||
}else{
|
|
||||||
//determine if this is ok
|
|
||||||
}
|
|
||||||
//push child objects onto dom
|
|
||||||
//push dom children objects onto stack
|
|
||||||
stack.push(CompileStackInstruction::PopFolder);
|
stack.push(CompileStackInstruction::PopFolder);
|
||||||
stack.extend(item.children().into_iter().map(|&referent|CompileStackInstruction::Referent(referent)));
|
//check if a folder exists with item.name
|
||||||
stack.push(CompileStackInstruction::PushFolder(sanitize(item.name.as_str()).to_string()));
|
if let Ok(mut dir)=tokio::fs::read_dir(folder.as_path()).await{
|
||||||
|
let mut exist_names=std::collections::HashSet::new();
|
||||||
|
{
|
||||||
|
let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?;
|
||||||
|
for &child_ref in item.children(){
|
||||||
|
let child=dom.get_by_ref(child_ref).ok_or(anyhow::Error::msg("null child ref"))?;
|
||||||
|
let child_sans=sanitize(child.name.as_str()).to_string();
|
||||||
|
exist_names.insert(child_sans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//generate children from folder contents UNLESS! item already has a child of the same name
|
||||||
|
let mut join_set=tokio::task::JoinSet::new();
|
||||||
|
//I wish I could make the join_next() loop begin processing immediately,
|
||||||
|
//but I don't know an ergonomic way to do that.
|
||||||
|
//this will probably be fine considering there won't be millions of files in the directories
|
||||||
|
while let Some(entry)=dir.next_entry().await?{
|
||||||
|
//cull early even if supporting things with identical names is possible
|
||||||
|
if !exist_names.contains(entry.file_name().to_str().unwrap()){
|
||||||
|
let style=config.style;
|
||||||
|
join_set.spawn(async move{
|
||||||
|
//discern that bad boy
|
||||||
|
match tokio::join!(discern_node(&entry,style),discern_file(&entry,style)){
|
||||||
|
(Ok(Some(compile_class)),Ok(None))
|
||||||
|
|(Ok(None),Ok(Some(compile_class)))=>{
|
||||||
|
//prepare data structure
|
||||||
|
match compile_class.class{
|
||||||
|
CompileClass::Folder=>Ok(Some(PreparedData::Builder(rbx_dom_weak::InstanceBuilder::new("Folder").with_name(compile_class.name.as_str())))),
|
||||||
|
CompileClass::Script(source)=>Ok(Some(PreparedData::Builder(script_builder("Script",compile_class.name.as_str(),source)))),
|
||||||
|
CompileClass::LocalScript(source)=>Ok(Some(PreparedData::Builder(script_builder("LocalScript",compile_class.name.as_str(),source)))),
|
||||||
|
CompileClass::ModuleScript(source)=>Ok(Some(PreparedData::Builder(script_builder("ModuleScript",compile_class.name.as_str(),source)))),
|
||||||
|
CompileClass::Model(buf)=>Ok(Some(PreparedData::Model(rbx_xml::from_reader_default(std::io::Cursor::new(buf))?))),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(Ok(Some(_)),Ok(Some(_)))=>panic!("File and folder have the same name!"),
|
||||||
|
(Ok(None),Ok(None))=>Ok(None),
|
||||||
|
(Err(e),_)
|
||||||
|
|(_,Err(e))=>Err(e),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//this is only able to begin after dir iterator is exhausted
|
||||||
|
//push child objects onto dom
|
||||||
|
while let Some(goober)=join_set.join_next().await{
|
||||||
|
match goober??{
|
||||||
|
Some(PreparedData::Model(mut model_dom))=>model_dom.transfer(model_dom.root().children()[0],&mut dom,item_ref),
|
||||||
|
Some(PreparedData::Builder(script))=>{dom.insert(item_ref,script);},
|
||||||
|
None=>print!("There was a None"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//push dom children objects onto stack
|
||||||
|
let item=dom.get_by_ref(item_ref).ok_or(anyhow::Error::msg("null child ref"))?;
|
||||||
|
stack.extend(item.children().into_iter().map(|&referent|CompileStackInstruction::TraverseReferent(referent)));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
CompileStackInstruction::PushFolder(component)=>folder.push(component),
|
|
||||||
CompileStackInstruction::PopFolder=>assert!(folder.pop(),"pop folder bad"),
|
CompileStackInstruction::PopFolder=>assert!(folder.pop(),"pop folder bad"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut output_place=config.output_file.clone();
|
||||||
|
if output_place.extension().is_none(){
|
||||||
|
output_place.push("place.rbxl");
|
||||||
|
}
|
||||||
|
let output=std::io::BufWriter::new(std::fs::File::open(output_place)?);
|
||||||
|
rbx_binary::to_writer(output,&dom,&[dom.root_ref()])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user