rpgmxp_tool/commands/extract_assets/
vx_ace.rs1use super::extract_map_infos;
2use super::extract_ruby_data;
3use super::FileEntry;
4use super::Options;
5use anyhow::Context;
6use ruby_marshal::FromValueContext;
7use std::fs::File;
8use std::path::Path;
9use std::path::PathBuf;
10
11fn extract_scripts_vx_ace<P>(file: impl std::io::Read, dir_path: P) -> anyhow::Result<()>
12where
13 P: AsRef<Path>,
14{
15 let dir_path = dir_path.as_ref();
16 let temp_dir_path = nd_util::with_push_extension(dir_path, "temp");
17
18 std::fs::create_dir_all(&temp_dir_path)?;
21
22 let arena = ruby_marshal::load(file).context("failed to load ruby data")?;
23 let ctx = FromValueContext::new(&arena);
24 let script_list: rpgmvx_ace_types::ScriptList = ctx.from_value(arena.root())?;
25
26 for (script_index, script) in script_list.scripts.iter().enumerate() {
27 println!(" extracting script \"{}\"", script.name);
28
29 let escaped_script_name = crate::util::percent_escape_file_name(&script.name);
30
31 let out_path = temp_dir_path.join(format!("{script_index:03}-{escaped_script_name}.rb"));
32 let temp_path = nd_util::with_push_extension(&out_path, "temp");
33
34 std::fs::write(&temp_path, &script.data)?;
37 std::fs::rename(temp_path, out_path)?;
38 }
39
40 std::fs::rename(temp_dir_path, dir_path)?;
41
42 Ok(())
43}
44
45pub fn extract(
46 options: &Options,
47 entry: &mut FileEntry<'_>,
48 relative_path_components: Vec<&str>,
49 output_path: PathBuf,
50) -> anyhow::Result<()> {
51 match relative_path_components.as_slice() {
52 ["Data", "Scripts.rvdata2"] if !options.skip_extract_scripts => {
53 extract_scripts_vx_ace(entry, output_path)?;
54 }
55 ["Data", "MapInfos.rvdata2"] if !options.skip_extract_map_infos => {
56 extract_map_infos(entry, output_path)?;
57 }
58 ["Data", file]
59 if !options.skip_extract_maps && crate::util::is_map_file_name(file, "rvdata2") =>
60 {
61 extract_ruby_data::<rpgmvx_ace_types::Map>(entry, output_path)?;
62 }
63 _ => {
64 let temp_path = nd_util::with_push_extension(&output_path, "temp");
65 let mut output_file = File::create(&temp_path)
68 .with_context(|| format!("failed to open file at \"{}\"", output_path.display()))?;
69
70 std::io::copy(entry, &mut output_file)?;
71 std::fs::rename(&temp_path, &output_path)?;
72 }
73 }
74
75 Ok(())
76}