forked from StrafesNET/asset-tool
DecompileStyle
This commit is contained in:
parent
2260d9a565
commit
10f1ac313c
129
src/main.rs
129
src/main.rs
@ -33,6 +33,8 @@ struct Cli{
|
|||||||
no_scripts:Option<bool>,
|
no_scripts:Option<bool>,
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
no_template:Option<bool>,
|
no_template:Option<bool>,
|
||||||
|
#[arg(long)]
|
||||||
|
style:Option<String>,
|
||||||
|
|
||||||
//git options
|
//git options
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
@ -61,6 +63,13 @@ enum Commands{
|
|||||||
DownloadAndDecompileHistoryIntoGit,
|
DownloadAndDecompileHistoryIntoGit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Copy)]
|
||||||
|
enum DecompileStyle{
|
||||||
|
Rox,
|
||||||
|
Rojo,
|
||||||
|
RoxRojo,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
struct PathBufList{
|
struct PathBufList{
|
||||||
paths:Vec<std::path::PathBuf>
|
paths:Vec<std::path::PathBuf>
|
||||||
@ -108,6 +117,21 @@ async fn main()->AResult<()>{
|
|||||||
None=>None,
|
None=>None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let decompile_style=match cli.style.as_deref(){
|
||||||
|
Some("rox")
|
||||||
|
|Some("Rox")=>Some(DecompileStyle::Rox),
|
||||||
|
Some("rojo")
|
||||||
|
|Some("Rojo")=>Some(DecompileStyle::Rojo),
|
||||||
|
Some("rox-rojo")
|
||||||
|
|Some("rojo-rox")
|
||||||
|
|Some("roxrojo")
|
||||||
|
|Some("rojorox")
|
||||||
|
|Some("RoxRojo")
|
||||||
|
|Some("RojoRox")=>Some(DecompileStyle::RoxRojo),
|
||||||
|
None=>None,
|
||||||
|
_=>return Err(anyhow::Error::msg("Invalid style")),
|
||||||
|
};
|
||||||
|
|
||||||
match cli.command{
|
match cli.command{
|
||||||
Commands::DownloadHistory=>download_history(DownloadHistoryConfig{
|
Commands::DownloadHistory=>download_history(DownloadHistoryConfig{
|
||||||
output_folder:cli.output.unwrap(),
|
output_folder:cli.output.unwrap(),
|
||||||
@ -118,6 +142,7 @@ async fn main()->AResult<()>{
|
|||||||
Commands::Upload=>upload_list(cookie.unwrap(),cli.group,vec![(cli.asset_id.unwrap(),cli.output.unwrap())]).await,
|
Commands::Upload=>upload_list(cookie.unwrap(),cli.group,vec![(cli.asset_id.unwrap(),cli.output.unwrap())]).await,
|
||||||
Commands::Compile=>compile(cli.input.unwrap(),cli.output.unwrap()),
|
Commands::Compile=>compile(cli.input.unwrap(),cli.output.unwrap()),
|
||||||
Commands::Decompile=>decompile(DecompileConfig{
|
Commands::Decompile=>decompile(DecompileConfig{
|
||||||
|
style:decompile_style.unwrap(),
|
||||||
input_file:cli.input.unwrap(),
|
input_file:cli.input.unwrap(),
|
||||||
output_folder:cli.output.unwrap(),
|
output_folder:cli.output.unwrap(),
|
||||||
write_template:!cli.no_template.unwrap_or(false),
|
write_template:!cli.no_template.unwrap_or(false),
|
||||||
@ -129,6 +154,7 @@ async fn main()->AResult<()>{
|
|||||||
git_committer_email:cli.git_committer_email.unwrap(),
|
git_committer_email:cli.git_committer_email.unwrap(),
|
||||||
input_folder:cli.input.unwrap(),
|
input_folder:cli.input.unwrap(),
|
||||||
output_folder:cli.output.unwrap(),
|
output_folder:cli.output.unwrap(),
|
||||||
|
style:decompile_style.unwrap(),
|
||||||
write_template:!cli.no_template.unwrap_or(false),
|
write_template:!cli.no_template.unwrap_or(false),
|
||||||
write_models:!cli.no_models.unwrap_or(false),
|
write_models:!cli.no_models.unwrap_or(false),
|
||||||
write_scripts:!cli.no_scripts.unwrap_or(false),
|
write_scripts:!cli.no_scripts.unwrap_or(false),
|
||||||
@ -139,6 +165,7 @@ async fn main()->AResult<()>{
|
|||||||
cookie:cookie.unwrap(),
|
cookie:cookie.unwrap(),
|
||||||
asset_id:cli.asset_id.unwrap(),
|
asset_id:cli.asset_id.unwrap(),
|
||||||
output_folder:cli.output.unwrap(),
|
output_folder:cli.output.unwrap(),
|
||||||
|
style:decompile_style.unwrap(),
|
||||||
write_template:!cli.no_template.unwrap_or(false),
|
write_template:!cli.no_template.unwrap_or(false),
|
||||||
write_models:!cli.no_models.unwrap_or(false),
|
write_models:!cli.no_models.unwrap_or(false),
|
||||||
write_scripts:!cli.no_scripts.unwrap_or(false),
|
write_scripts:!cli.no_scripts.unwrap_or(false),
|
||||||
@ -427,15 +454,26 @@ enum WriteStackInstruction<'a>{
|
|||||||
Destroy(Ref),
|
Destroy(Ref),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default,serde::Deserialize,serde::Serialize)]
|
#[derive(Default)]
|
||||||
#[allow(nonstandard_style,dead_code)]
|
|
||||||
struct PropertiesOverride{
|
struct PropertiesOverride{
|
||||||
//Name:Option<String>,
|
name:Option<String>,
|
||||||
ClassName:Option<String>,
|
class_name:Option<String>,
|
||||||
}
|
}
|
||||||
impl PropertiesOverride{
|
impl PropertiesOverride{
|
||||||
fn is_some(&self)->bool{
|
fn is_some(&self)->bool{
|
||||||
self.ClassName.is_some()
|
self.name.is_some()
|
||||||
|
||self.class_name.is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for PropertiesOverride{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
if let Some(name)=self.name.as_deref(){
|
||||||
|
writeln!(f,"--! Properties.Name=\"{}\"",name)?;
|
||||||
|
}
|
||||||
|
if let Some(class_name)=self.class_name.as_deref(){
|
||||||
|
writeln!(f,"--! Properties.ClassName=\"{}\"",class_name)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +481,7 @@ fn sanitize<'a>(s:&'a str)->std::borrow::Cow<'a,str>{
|
|||||||
lazy_regex::regex!(r"[^a-zA-Z0-9._-]").replace_all(s,"_")
|
lazy_regex::regex!(r"[^a-zA-Z0-9._-]").replace_all(s,"_")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_item(dom:&rbx_dom_weak::WeakDom,mut file:std::path::PathBuf,node:&TreeNode,node_name_override:String,write_models:bool,write_scripts:bool)->AResult<()>{
|
fn write_item(dom:&rbx_dom_weak::WeakDom,mut file:std::path::PathBuf,node:&TreeNode,node_name_override:String,mut properties:PropertiesOverride,style:DecompileStyle,write_models:bool,write_scripts:bool)->AResult<()>{
|
||||||
file.push(sanitize(node_name_override.as_str()).as_ref());
|
file.push(sanitize(node_name_override.as_str()).as_ref());
|
||||||
match node.class{
|
match node.class{
|
||||||
Class::Folder=>(),
|
Class::Folder=>(),
|
||||||
@ -451,11 +489,40 @@ fn write_item(dom:&rbx_dom_weak::WeakDom,mut file:std::path::PathBuf,node:&TreeN
|
|||||||
if !write_scripts{
|
if !write_scripts{
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
assert!(file.set_extension("lua"),"could not set extension");
|
|
||||||
|
//set extension
|
||||||
|
match style{
|
||||||
|
DecompileStyle::Rox=>assert!(file.set_extension("lua"),"could not set extension"),
|
||||||
|
DecompileStyle::RoxRojo|DecompileStyle::Rojo=>{
|
||||||
|
match properties.class_name.as_deref(){
|
||||||
|
Some("LocalScript")=>{
|
||||||
|
file.set_extension("client.lua");
|
||||||
|
properties.class_name=None;
|
||||||
|
},
|
||||||
|
Some("Script")=>{
|
||||||
|
file.set_extension("server.lua");
|
||||||
|
properties.class_name=None;
|
||||||
|
},
|
||||||
|
// Some("ModuleScript")=>{
|
||||||
|
// file.set_extension("module");
|
||||||
|
// properties.class_name=None;
|
||||||
|
// },
|
||||||
|
None=>assert!(file.set_extension("lua"),"could not set extension"),
|
||||||
|
Some(other)=>return Err(anyhow::Error::msg(format!("Attempt to write a {} as a script",other))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(item)=dom.get_by_ref(node.referent){
|
if let Some(item)=dom.get_by_ref(node.referent){
|
||||||
//TODO: delete disabled scripts
|
//TODO: delete disabled scripts
|
||||||
if let Some(rbx_dom_weak::types::Variant::String(source))=item.properties.get("Source"){
|
if let Some(rbx_dom_weak::types::Variant::String(source))=item.properties.get("Source"){
|
||||||
|
if properties.is_some(){
|
||||||
|
//rox style
|
||||||
|
let source=properties.to_string()+source.as_str();
|
||||||
std::fs::write(file,source)?;
|
std::fs::write(file,source)?;
|
||||||
|
}else{
|
||||||
|
std::fs::write(file,source)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -574,6 +641,7 @@ fn generate_decompiled_context<R:Read>(input:R)->AResult<DecompiledContext>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct WriteConfig{
|
struct WriteConfig{
|
||||||
|
style:DecompileStyle,
|
||||||
output_folder:std::path::PathBuf,
|
output_folder:std::path::PathBuf,
|
||||||
write_template:bool,
|
write_template:bool,
|
||||||
write_models:bool,
|
write_models:bool,
|
||||||
@ -593,44 +661,41 @@ async fn write_files(config:WriteConfig,mut context:DecompiledContext)->AResult<
|
|||||||
WriteStackInstruction::PopFolder=>assert!(folder.pop(),"weirdness"),
|
WriteStackInstruction::PopFolder=>assert!(folder.pop(),"weirdness"),
|
||||||
WriteStackInstruction::Destroy(referent)=>destroy_queue.push(referent),
|
WriteStackInstruction::Destroy(referent)=>destroy_queue.push(referent),
|
||||||
WriteStackInstruction::Node(node,name_count)=>{
|
WriteStackInstruction::Node(node,name_count)=>{
|
||||||
//properties.json to override class or other simple properties
|
//track properties that must be overriden to compile folder structure back into a place file
|
||||||
let mut properties=PropertiesOverride::default();
|
let mut properties=PropertiesOverride::default();
|
||||||
let has_children=node.children.len()!=0;
|
let has_children=node.children.len()!=0;
|
||||||
match node.class{
|
match node.class{
|
||||||
Class::Folder=>(),
|
Class::Folder=>(),
|
||||||
Class::ModuleScript=>{
|
Class::ModuleScript=>(),//.lua files are ModuleScript by default
|
||||||
//.lua files are ModuleScript by default
|
Class::LocalScript=>properties.class_name=Some("LocalScript".to_string()),
|
||||||
if has_children{
|
Class::Script=>properties.class_name=Some("Script".to_string()),
|
||||||
properties.ClassName=Some("ModuleScript".to_string())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Class::LocalScript=>properties.ClassName=Some("LocalScript".to_string()),
|
|
||||||
Class::Script=>properties.ClassName=Some("Script".to_string()),
|
|
||||||
Class::Model=>(),
|
Class::Model=>(),
|
||||||
}
|
}
|
||||||
let name_override=if 0<name_count{
|
let name_override=if 0<name_count{
|
||||||
|
properties.name=Some(node.name.clone());
|
||||||
format!("{}_{}",node.name,name_count)
|
format!("{}_{}",node.name,name_count)
|
||||||
}else{
|
}else{
|
||||||
node.name.clone()
|
node.name.clone()
|
||||||
};
|
};
|
||||||
if has_children||properties.is_some(){
|
|
||||||
|
if has_children{
|
||||||
//push temp subfolder
|
//push temp subfolder
|
||||||
let mut subfolder=folder.clone();
|
let mut subfolder=folder.clone();
|
||||||
subfolder.push(sanitize(name_override.as_str()).as_ref());
|
subfolder.push(sanitize(name_override.as_str()).as_ref());
|
||||||
//make folder
|
//make folder
|
||||||
tokio::fs::create_dir(subfolder.clone()).await?;
|
tokio::fs::create_dir(subfolder.clone()).await?;
|
||||||
//write properties
|
|
||||||
if properties.is_some(){
|
let name_final=match config.style{
|
||||||
let mut file=subfolder.clone();
|
DecompileStyle::Rox
|
||||||
file.push("properties");
|
|DecompileStyle::RoxRojo=>name_override.clone(),
|
||||||
assert!(file.set_extension("json"),"could not set extension");
|
DecompileStyle::Rojo=>"init".to_owned(),
|
||||||
tokio::fs::write(file,serde_json::to_string(&properties)?).await?;
|
};
|
||||||
}
|
|
||||||
//write item in subfolder
|
//write item in subfolder
|
||||||
write_queue.push((subfolder,node,name_override.clone()));
|
write_queue.push((subfolder,node,name_final,properties,config.style));
|
||||||
}else{
|
}else{
|
||||||
//write item
|
//write item
|
||||||
write_queue.push((folder.clone(),node,name_override.clone()));
|
write_queue.push((folder.clone(),node,name_override.clone(),properties,config.style));
|
||||||
}
|
}
|
||||||
//queue item to be deleted from dom after child objects are handled (stack is popped from the back)
|
//queue item to be deleted from dom after child objects are handled (stack is popped from the back)
|
||||||
match node.class{
|
match node.class{
|
||||||
@ -657,8 +722,8 @@ async fn write_files(config:WriteConfig,mut context:DecompiledContext)->AResult<
|
|||||||
let dom=&context.dom;
|
let dom=&context.dom;
|
||||||
let write_models=config.write_models;
|
let write_models=config.write_models;
|
||||||
let write_scripts=config.write_scripts;
|
let write_scripts=config.write_scripts;
|
||||||
let results:Vec<AResult<()>>=rayon::iter::ParallelIterator::collect(rayon::iter::ParallelIterator::map(rayon::iter::IntoParallelIterator::into_par_iter(write_queue),|(write_path,node,node_name_override)|{
|
let results:Vec<AResult<()>>=rayon::iter::ParallelIterator::collect(rayon::iter::ParallelIterator::map(rayon::iter::IntoParallelIterator::into_par_iter(write_queue),|(write_path,node,node_name_override,properties,style)|{
|
||||||
write_item(&dom,write_path,node,node_name_override,write_models,write_scripts)
|
write_item(&dom,write_path,node,node_name_override,properties,style,write_models,write_scripts)
|
||||||
}));
|
}));
|
||||||
for result in results{
|
for result in results{
|
||||||
result?;
|
result?;
|
||||||
@ -683,6 +748,7 @@ async fn write_files(config:WriteConfig,mut context:DecompiledContext)->AResult<
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct DecompileConfig{
|
struct DecompileConfig{
|
||||||
|
style:DecompileStyle,
|
||||||
input_file:std::path::PathBuf,
|
input_file:std::path::PathBuf,
|
||||||
output_folder:std::path::PathBuf,
|
output_folder:std::path::PathBuf,
|
||||||
write_template:bool,
|
write_template:bool,
|
||||||
@ -703,6 +769,7 @@ async fn decompile(config:DecompileConfig)->AResult<()>{
|
|||||||
//generate folders, models, and scripts
|
//generate folders, models, and scripts
|
||||||
//delete models and scripts from dom
|
//delete models and scripts from dom
|
||||||
write_files(WriteConfig{
|
write_files(WriteConfig{
|
||||||
|
style:config.style,
|
||||||
output_folder:config.output_folder,
|
output_folder:config.output_folder,
|
||||||
write_template:config.write_template,
|
write_template:config.write_template,
|
||||||
write_models:config.write_models,
|
write_models:config.write_models,
|
||||||
@ -716,6 +783,7 @@ struct WriteCommitConfig{
|
|||||||
git_committer_name:String,
|
git_committer_name:String,
|
||||||
git_committer_email:String,
|
git_committer_email:String,
|
||||||
output_folder:std::path::PathBuf,
|
output_folder:std::path::PathBuf,
|
||||||
|
style:DecompileStyle,
|
||||||
write_template:bool,
|
write_template:bool,
|
||||||
write_models:bool,
|
write_models:bool,
|
||||||
write_scripts:bool,
|
write_scripts:bool,
|
||||||
@ -745,6 +813,7 @@ async fn write_commit(config:WriteCommitConfig,b:Result<AResult<(AssetVersion,De
|
|||||||
|
|
||||||
//write files
|
//write files
|
||||||
write_files(WriteConfig{
|
write_files(WriteConfig{
|
||||||
|
style:config.style,
|
||||||
output_folder:config.output_folder.clone(),
|
output_folder:config.output_folder.clone(),
|
||||||
write_template:config.write_template,
|
write_template:config.write_template,
|
||||||
write_models:config.write_models,
|
write_models:config.write_models,
|
||||||
@ -804,6 +873,7 @@ struct DecompileHistoryConfig{
|
|||||||
git_committer_name:String,
|
git_committer_name:String,
|
||||||
git_committer_email:String,
|
git_committer_email:String,
|
||||||
input_folder:std::path::PathBuf,
|
input_folder:std::path::PathBuf,
|
||||||
|
style:DecompileStyle,
|
||||||
output_folder:std::path::PathBuf,
|
output_folder:std::path::PathBuf,
|
||||||
write_template:bool,
|
write_template:bool,
|
||||||
write_models:bool,
|
write_models:bool,
|
||||||
@ -834,6 +904,7 @@ async fn decompile_history_into_git(config:DecompileHistoryConfig)->AResult<()>{
|
|||||||
match write_commit(WriteCommitConfig{
|
match write_commit(WriteCommitConfig{
|
||||||
git_committer_name:config.git_committer_name.clone(),
|
git_committer_name:config.git_committer_name.clone(),
|
||||||
git_committer_email:config.git_committer_email.clone(),
|
git_committer_email:config.git_committer_email.clone(),
|
||||||
|
style:config.style,
|
||||||
output_folder:config.output_folder.clone(),
|
output_folder:config.output_folder.clone(),
|
||||||
write_template:config.write_template,
|
write_template:config.write_template,
|
||||||
write_models:config.write_models,
|
write_models:config.write_models,
|
||||||
@ -851,6 +922,7 @@ struct DownloadAndDecompileHistoryConfig{
|
|||||||
asset_id:AssetID,
|
asset_id:AssetID,
|
||||||
git_committer_name:String,
|
git_committer_name:String,
|
||||||
git_committer_email:String,
|
git_committer_email:String,
|
||||||
|
style:DecompileStyle,
|
||||||
output_folder:std::path::PathBuf,
|
output_folder:std::path::PathBuf,
|
||||||
write_template:bool,
|
write_template:bool,
|
||||||
write_models:bool,
|
write_models:bool,
|
||||||
@ -884,6 +956,7 @@ async fn download_and_decompile_history_into_git(config:DownloadAndDecompileHist
|
|||||||
.buffered(CONCURRENT_DECODE)
|
.buffered(CONCURRENT_DECODE)
|
||||||
.for_each(|join_handle_result|async{
|
.for_each(|join_handle_result|async{
|
||||||
match write_commit(WriteCommitConfig{
|
match write_commit(WriteCommitConfig{
|
||||||
|
style:config.style,
|
||||||
git_committer_name:config.git_committer_name.clone(),
|
git_committer_name:config.git_committer_name.clone(),
|
||||||
git_committer_email:config.git_committer_email.clone(),
|
git_committer_email:config.git_committer_email.clone(),
|
||||||
output_folder:config.output_folder.clone(),
|
output_folder:config.output_folder.clone(),
|
||||||
|
Loading…
Reference in New Issue
Block a user