rpgmxp_tool/commands/extract_assets/
xp.rs

1use super::extract_arraylike;
2use super::extract_map_infos;
3use super::extract_ruby_data;
4use super::extract_scripts;
5use super::FileEntry;
6use super::Options;
7use anyhow::Context;
8use rpgmxp_types::Actor;
9use rpgmxp_types::Animation;
10use rpgmxp_types::Armor;
11use rpgmxp_types::Class;
12use rpgmxp_types::CommonEvent;
13use rpgmxp_types::Enemy;
14use rpgmxp_types::Item;
15use rpgmxp_types::Skill;
16use rpgmxp_types::State;
17use rpgmxp_types::Tileset;
18use rpgmxp_types::Troop;
19use rpgmxp_types::Weapon;
20use std::fs::File;
21use std::path::PathBuf;
22
23pub fn extract(
24    options: &Options,
25    entry: &mut FileEntry<'_>,
26    relative_path_components: Vec<&str>,
27    output_path: PathBuf,
28) -> anyhow::Result<()> {
29    match relative_path_components.as_slice() {
30        ["Data", "Scripts.rxdata"] if !options.skip_extract_scripts => {
31            extract_scripts(entry, output_path)?;
32        }
33        ["Data", "CommonEvents.rxdata"] if !options.skip_extract_common_events => {
34            extract_arraylike::<CommonEvent>(entry, output_path)?;
35        }
36        ["Data", "Actors.rxdata"] if !options.skip_extract_actors => {
37            extract_arraylike::<Actor>(entry, output_path)?;
38        }
39        ["Data", "Weapons.rxdata"] if !options.skip_extract_weapons => {
40            extract_arraylike::<Weapon>(entry, output_path)?;
41        }
42        ["Data", "Armors.rxdata"] if !options.skip_extract_armors => {
43            extract_arraylike::<Armor>(entry, output_path)?;
44        }
45        ["Data", "Skills.rxdata"] if !options.skip_extract_skills => {
46            extract_arraylike::<Skill>(entry, output_path)?;
47        }
48        ["Data", "States.rxdata"] if !options.skip_extract_states => {
49            extract_arraylike::<State>(entry, output_path)?;
50        }
51        ["Data", "Items.rxdata"] if !options.skip_extract_items => {
52            extract_arraylike::<Item>(entry, output_path)?;
53        }
54        ["Data", "Enemies.rxdata"] if !options.skip_extract_enemies => {
55            extract_arraylike::<Enemy>(entry, output_path)?;
56        }
57        ["Data", "Classes.rxdata"] if !options.skip_extract_classes => {
58            extract_arraylike::<Class>(entry, output_path)?;
59        }
60        ["Data", "Troops.rxdata"] if !options.skip_extract_troops => {
61            extract_arraylike::<Troop>(entry, output_path)?;
62        }
63        ["Data", "Tilesets.rxdata"] if !options.skip_extract_tilesets => {
64            extract_arraylike::<Tileset>(entry, output_path)?;
65        }
66        ["Data", "MapInfos.rxdata"] if !options.skip_extract_map_infos => {
67            extract_map_infos(entry, output_path)?;
68        }
69        ["Data", "System.rxdata"] if !options.skip_extract_system => {
70            extract_ruby_data::<rpgmxp_types::System>(entry, output_path)?;
71        }
72        ["Data", "Animations.rxdata"] if !options.skip_extract_animations => {
73            extract_arraylike::<Animation>(entry, output_path)?;
74        }
75        ["Data", file]
76            if !options.skip_extract_maps && crate::util::is_map_file_name(file, "rxdata") =>
77        {
78            extract_ruby_data::<rpgmxp_types::Map>(entry, output_path)?;
79        }
80        _ => {
81            let temp_path = nd_util::with_push_extension(&output_path, "temp");
82            // TODO: Lock?
83            // TODO: Drop delete guard for file?
84            let mut output_file = File::create(&temp_path)
85                .with_context(|| format!("failed to open file at \"{}\"", output_path.display()))?;
86
87            std::io::copy(entry, &mut output_file)?;
88            std::fs::rename(&temp_path, &output_path)?;
89        }
90    }
91
92    Ok(())
93}