valid parser

This commit is contained in:
Tom Bloor 2024-04-01 04:41:20 +01:00
parent 5265c340b4
commit 2c8c77c97b
Signed by: TBSliver
GPG key ID: 4657C7EBE42CC5CC
10 changed files with 725 additions and 5 deletions

140
Cargo.lock generated
View file

@ -159,6 +159,54 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anstream"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "arboard" name = "arboard"
version = "3.3.2" version = "3.3.2"
@ -636,6 +684,46 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "clap"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.57",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]] [[package]]
name = "clipboard-win" name = "clipboard-win"
version = "5.3.0" version = "5.3.0"
@ -691,6 +779,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "com" name = "com"
version = "0.6.0" version = "0.6.0"
@ -1440,6 +1534,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.3.9" version = "0.3.9"
@ -1531,6 +1631,12 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]] [[package]]
name = "jni" name = "jni"
version = "0.21.1" version = "0.21.1"
@ -1611,7 +1717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"windows-targets 0.48.5", "windows-targets 0.52.4",
] ]
[[package]] [[package]]
@ -1799,7 +1905,10 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
name = "nostalgaia-save-editor" name = "nostalgaia-save-editor"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap",
"eframe", "eframe",
"serde",
"serde_json",
] ]
[[package]] [[package]]
@ -2259,6 +2368,12 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]] [[package]]
name = "same-file" name = "same-file"
version = "1.0.6" version = "1.0.6"
@ -2313,6 +2428,17 @@ dependencies = [
"syn 2.0.57", "syn 2.0.57",
] ]
[[package]]
name = "serde_json"
version = "1.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]] [[package]]
name = "serde_repr" name = "serde_repr"
version = "0.1.18" version = "0.1.18"
@ -2450,6 +2576,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
[[package]]
name = "strsim"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"
@ -2694,6 +2826,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"

View file

@ -7,3 +7,6 @@ edition = "2021"
[dependencies] [dependencies]
eframe = "0.27.1" eframe = "0.27.1"
serde = { version = "1.0.197", features = ["derive"] }
clap = { version = "4.5.4", features = ["derive"] }
serde_json = "1.0.115"

10
src/cli.rs Normal file
View file

@ -0,0 +1,10 @@
use clap::Parser;
#[derive(Parser, Debug)]
#[command(author, version, about, name = "Nostalgaia Save Editor")]
pub(crate) struct Options {
pub(crate) save_file: String,
#[arg(short, long)]
pub(crate) gui: bool,
}

15
src/data/area_config.rs Normal file
View file

@ -0,0 +1,15 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize,Debug, Default)]
pub(crate) struct AreaConfig {
#[serde(rename = "killedEnemies")]
pub killed_enemies: Vec<String>,
#[serde(rename = "destructableObjects")]
pub destructable_objects: Vec<String>,
#[serde(rename = "customObjects")]
pub custom_objects: Vec<String>,
#[serde(rename = "customBeaconResetables")]
pub custom_beacon_resetables: Vec<String>,
#[serde(rename = "visibilityBitMask")]
pub visibility_bit_mask: i64,
}

48
src/data/game_config.rs Normal file
View file

@ -0,0 +1,48 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub(crate) struct GameConfig {
pub previous_saveindex: i64,
pub automatically_select_next_target: bool,
pub freeze_time_on_hit: bool,
pub close_menu_when_attacked: bool,
pub controller_vibration: f64,
pub invert_camera_x: bool,
pub invert_camera_y: bool,
pub lock_camera_rotation: bool,
pub camera_speed: f64,
pub use_custom_camera_pitch: bool,
pub custom_camera_pitch_speed: f64,
pub offline_mode: bool,
pub hide_messages: bool,
pub subtitles: bool,
pub dialogue_auto_progress: bool,
#[serde(rename = "volume_Music")]
pub volume_music: f64,
#[serde(rename = "volume_SFX")]
pub volume_sfx: f64,
#[serde(rename = "volume_Voice")]
pub volume_voice: f64,
pub light_shadow_quality: i64,
pub light_shadow_distance: f64,
pub is_windowed: bool,
pub resolution: Vec<i64>,
pub refresh_rate: i64,
pub brightness: f64,
pub anti_aliasing: bool,
pub volume_lighting: bool,
pub shadow_quality: i64,
pub vsync: bool,
pub vsync_count: i64,
pub low_quality_mode: bool,
#[serde(rename = "mouse_Sensitivity")]
pub mouse_sensitivity: f64,
#[serde(rename = "mouse_InvertX")]
pub mouse_invert_x: bool,
#[serde(rename = "mouse_InvertY")]
pub mouse_invert_y: bool,
pub toggle_sprint: bool,
pub hold_roll_to_sprint: bool,
pub current_language: i64,
}

87
src/data/mod.rs Normal file
View file

@ -0,0 +1,87 @@
mod game_config;
mod area_config;
mod quest_config;
mod world_config;
mod player_config;
use std::collections::VecDeque;
use std::error::Error;
use std::fs;
use std::path::Path;
use game_config::GameConfig;
use area_config::AreaConfig;
use quest_config::QuestConfig;
use player_config::PlayerConfig;
use world_config::WorldConfig;
#[derive(Debug)]
pub(crate) struct CoreConfig {
game_config: GameConfig,
player_config: PlayerConfig,
world_config: WorldConfig,
quest_config: QuestConfig,
area_configs: Vec<AreaConfig>,
}
const SETTINGS_SPLIT: &str = "~SettingsSplit~";
impl CoreConfig {
pub(crate) fn parse_file(path: impl AsRef<Path>) -> Result<Self, Box<dyn Error>> {
let content = fs::read_to_string(path)?;
let Some((raw_game_config, rest_config)) = content.split_once(SETTINGS_SPLIT) else {
return Err(Box::from("Error parsing config"));
};
let game_config: GameConfig = serde_json::from_str(&raw_game_config)?;
// This assumes that there are never any semicolons elsewhere!
let mut rest: VecDeque<&str> = rest_config.split(";").collect();
let player_config: PlayerConfig = serde_json::from_str(rest.pop_front().ok_or("No Player Config")?)?;
let world_config: WorldConfig = serde_json::from_str(rest.pop_front().ok_or("No World Config")?)?;
let quest_config: QuestConfig = serde_json::from_str(rest.pop_front().ok_or("No Quest Config")?)?;
let area_configs: Vec<AreaConfig> = rest.iter()
.map(|s| serde_json::from_str(s))
.filter_map(|s| s.ok())
.collect();
if rest.len() != area_configs.len() {
return Err("Failed Parsing Area Configs".into());
}
Ok(CoreConfig {
game_config,
player_config,
world_config,
quest_config,
area_configs,
})
}
pub(crate) fn to_string(&self) -> Result<String, Box<dyn Error>> {
let game_config = serde_json::to_string(&self.game_config)?;
let area_config: Vec<String> = self.area_configs
.iter()
.map(|a| serde_json::to_string(a))
.filter_map(|a| a.ok())
.collect();
let rest_config = [
serde_json::to_string(&self.player_config)?,
serde_json::to_string(&self.player_config)?,
serde_json::to_string(&self.world_config)?,
serde_json::to_string(&self.quest_config)?,
area_config.join(";"),
].join(";");
let full_config = [
game_config,
rest_config,
].join(SETTINGS_SPLIT);
Ok(full_config)
}
}

212
src/data/player_config.rs Normal file
View file

@ -0,0 +1,212 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default)]
struct InventoryWeapon {
#[serde(rename = "GUID")]
pub guid: String,
#[serde(rename = "isAwake")]
pub is_awake: bool,
#[serde(rename = "hasSeen")]
pub has_seen: bool,
#[serde(rename = "isHoovered")]
pub is_hoovered: bool,
#[serde(rename = "instanceIDOnCreation")]
pub instance_idon_creation: String,
pub level: i64,
#[serde(rename = "newGamePlusCount")]
pub new_game_plus_count: i64,
#[serde(rename = "infusionType")]
pub infusion_type: i64,
}
#[derive(Serialize, Deserialize, Debug, Default)]
struct InventoryItem {
#[serde(rename = "GUID")]
pub guid: String,
pub uses: i64,
#[serde(rename = "isAwake")]
pub is_awake: bool,
#[serde(rename = "isHoovered")]
pub is_hoovered: bool,
#[serde(rename = "hasSeen")]
pub has_seen: bool,
#[serde(rename = "instanceIDOnCreation")]
pub instance_idon_creation: String,
#[serde(rename = "newGamePlusCount")]
pub new_game_plus_count: i64,
}
#[derive(Serialize, Deserialize, Debug, Default)]
struct LoadedRegion {
pub name: String,
#[serde(rename = "usingLOD")]
pub using_lod: bool,
#[serde(rename = "lodIndex")]
pub lod_index: i64,
}
#[derive(Serialize, Deserialize, Debug, Default)]
struct Rotation {
pub x: f64,
pub y: f64,
pub z: f64,
pub w: f64,
}
#[derive(Serialize, Deserialize, Debug, Default)]
struct Position {
pub x: f64,
pub y: f64,
pub z: f64,
}
#[derive(Serialize, Deserialize, Debug, Default)]
pub(crate) struct PlayerConfig {
#[serde(rename = "newGamePlusCount")]
pub new_game_plus_count: i64,
pub accomplishments: Vec<i64>,
pub achievements: Vec<i64>,
#[serde(rename = "easyModeTutorials")]
pub easy_mode_tutorials: Vec<i64>,
#[serde(rename = "wakeUpTutorialStage")]
pub wake_up_tutorial_stage: i64,
#[serde(rename = "hasSeenFlatCounterTutorial")]
pub has_seen_flat_counter_tutorial: bool,
#[serde(rename = "playerClass")]
pub player_class: i64,
pub position: Position,
pub rotation: Rotation,
pub health: f64,
pub memory: i64,
#[serde(rename = "totalMemorySinceStart")]
pub total_memory_since_start: i64,
#[serde(rename = "levelsUpToHoover")]
pub levels_up_to_hoover: i64,
#[serde(rename = "itemsRemembered")]
pub items_remembered: i64,
#[serde(rename = "DLCItemsRemembered")]
pub dlcitems_remembered: i64,
#[serde(rename = "itemsHoovered")]
pub items_hoovered: i64,
#[serde(rename = "easyMode")]
pub easy_mode: bool,
#[serde(rename = "canAccrueSins")]
pub can_accrue_sins: bool,
#[serde(rename = "hooverCanHoover")]
pub hoover_can_hoover: bool,
#[serde(rename = "hooverCanLevelUp")]
pub hoover_can_level_up: bool,
#[serde(rename = "hasHooveredFirstItem")]
pub has_hoovered_first_item: bool,
#[serde(rename = "hasSeenHooverTutorial")]
pub has_seen_hoover_tutorial: bool,
#[serde(rename = "hasSeenMartyrTutorial")]
pub has_seen_martyr_tutorial: bool,
#[serde(rename = "hasHeardWunderBark")]
pub has_heard_wunder_bark: bool,
#[serde(rename = "hooverSins")]
pub hoover_sins: i64,
#[serde(rename = "truthFidelity")]
pub truth_fidelity: i64,
#[serde(rename = "truthPixelation")]
pub truth_pixelation: i64,
pub name: String,
pub guid: String,
#[serde(rename = "beaconIDToLoadAt")]
pub beacon_idto_load_at: String,
#[serde(rename = "tetheredBeaconID")]
pub tethered_beacon_id: String,
#[serde(rename = "hasDoneInitialAcheivementFixCheck")]
pub has_done_initial_acheivement_fix_check: bool,
#[serde(rename = "rememberedGUIDs")]
pub remembered_guids: Vec<String>,
#[serde(rename = "hooveredGUIDs")]
pub hoovered_guids: Vec<String>,
pub _region: String,
#[serde(rename = "regionDisplayName")]
pub region_display_name: String,
#[serde(rename = "discoveredRegions")]
pub discovered_regions: Vec<String>,
#[serde(rename = "loadedRegions")]
pub loaded_regions: Vec<LoadedRegion>,
#[serde(rename = "regionsIWantToLoad")]
pub regions_iwant_to_load: i64,
pub inventory: Vec<InventoryItem>,
#[serde(rename = "inventoryWeapons")]
pub inventory_weapons: Vec<InventoryWeapon>,
pub storage: Vec<InventoryItem>,
#[serde(rename = "equipedConsumables")]
pub equiped_consumables: Vec<String>,
#[serde(rename = "equipedRings")]
pub equiped_rings: Vec<String>,
#[serde(rename = "droppedSpecialItems")]
pub dropped_special_items: Vec<String>,
#[serde(rename = "rightHandEquipIndex")]
pub right_hand_equip_index: i64,
#[serde(rename = "leftHandEquipIndex")]
pub left_hand_equip_index: i64,
#[serde(rename = "slottedRightHands")]
pub slotted_right_hands: Vec<String>,
#[serde(rename = "slottedLeftHands")]
pub slotted_left_hands: Vec<String>,
#[serde(rename = "initRightHandGUID")]
pub init_right_hand_guid: String,
#[serde(rename = "initLeftHandGUID")]
pub init_left_hand_guid: String,
#[serde(rename = "equipedHelm")]
pub equiped_helm: String,
#[serde(rename = "equipedTorso")]
pub equiped_torso: String,
#[serde(rename = "equipedArms")]
pub equiped_arms: String,
#[serde(rename = "equipedLegs")]
pub equiped_legs: String,
#[serde(rename = "selectedConsumableIndex")]
pub selected_consumable_index: i64,
#[serde(rename = "expToNextLevel")]
pub exp_to_next_level: i64,
pub level: i64,
#[serde(rename = "maxIconUses")]
pub max_icon_uses: i64,
#[serde(rename = "hasBeenBit")]
pub has_been_bit: bool,
pub deaths: i64,
#[serde(rename = "rebuffCount")]
pub rebuff_count: i64,
#[serde(rename = "reposteCount")]
pub reposte_count: i64,
#[serde(rename = "backstabCount")]
pub backstab_count: i64,
pub _stat_vitality: i64,
pub _stat_stamina: i64,
#[serde(rename = "_stat_equipLoad")]
pub _stat_equip_load: i64,
pub _stat_strength: i64,
pub _stat_dexterity: i64,
pub _stat_attunement: i64,
pub _stat_luck: i64,
#[serde(rename = "numberOfDeaths")]
pub number_of_deaths: i64,
#[serde(rename = "savedAtDeath")]
pub saved_at_death: bool,
#[serde(rename = "hasCTH")]
pub has_cth: bool,
#[serde(rename = "hasGoFlat")]
pub has_go_flat: bool,
#[serde(rename = "hasDepthHand")]
pub has_depth_hand: bool,
#[serde(rename = "canAttackSpirit")]
pub can_attack_spirit: bool,
#[serde(rename = "plotThreadsCut")]
pub plot_threads_cut: bool,
#[serde(rename = "hooverInWell")]
pub hoover_in_well: bool,
#[serde(rename = "herosSpiritInWell")]
pub heros_spirit_in_well: bool,
#[serde(rename = "innocentSacrificed")]
pub innocent_sacrificed: bool,
#[serde(rename = "hooverDead")]
pub hoover_dead: bool,
#[serde(rename = "regionName")]
pub region_name: String,
}

105
src/data/quest_config.rs Normal file
View file

@ -0,0 +1,105 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default)]
pub(crate) struct QuestConfig {
#[serde(rename = "friendlyNPCsKilled")]
pub friendly_npcs_killed: Vec<i64>,
#[serde(rename = "storyProgressStage")]
pub story_progress_stage: i64,
#[serde(rename = "storyProgressStage_DLC1_Lower")]
pub story_progress_stage_dlc1_lower: i64,
#[serde(rename = "storyProgressStage_DLC1_Upper")]
pub story_progress_stage_dlc1_upper: i64,
#[serde(rename = "hooverConversationIndex")]
pub hoover_conversation_index: i64,
#[serde(rename = "hooverTalkConversationIndex")]
pub hoover_talk_conversation_index: i64,
#[serde(rename = "scoFrickinCursedUsOut")]
pub sco_frickin_cursed_us_out: bool,
#[serde(rename = "blacksmithFirstLinesSpoken")]
pub blacksmith_first_lines_spoken: Vec<bool>,
#[serde(rename = "blacksmithHasSaidEndGame")]
pub blacksmith_has_said_end_game: bool,
#[serde(rename = "blacksmithGenericTalkIndex")]
pub blacksmith_generic_talk_index: i64,
#[serde(rename = "hasSpawnedBridge")]
pub has_spawned_bridge: bool,
#[serde(rename = "DLC_FailedOldManQuestLine")]
pub dlc_failed_old_man_quest_line: bool,
#[serde(rename = "DLC_OldManStartedInSewers")]
pub dlc_old_man_started_in_sewers: bool,
#[serde(rename = "DLC_OldManSecondLocaltionInSewers")]
pub dlc_old_man_second_localtion_in_sewers: bool,
#[serde(rename = "DLC_OldManInitialConversation")]
pub dlc_old_man_initial_conversation: bool,
#[serde(rename = "DLC_OldManSecondConversation")]
pub dlc_old_man_second_conversation: bool,
#[serde(rename = "DLC_OldManEnteredSTown")]
pub dlc_old_man_entered_stown: bool,
#[serde(rename = "DLC_OldManEnteredCave")]
pub dlc_old_man_entered_cave: bool,
#[serde(rename = "DLC_OldManTalkedFirstItem")]
pub dlc_old_man_talked_first_item: bool,
#[serde(rename = "DLC_OldManTalkedSecondItem")]
pub dlc_old_man_talked_second_item: bool,
#[serde(rename = "DLC_KilledEve")]
pub dlc_killed_eve: bool,
#[serde(rename = "DLC_KilledLiuvani")]
pub dlc_killed_liuvani: bool,
#[serde(rename = "DLC_KilledLiuvaniFirst")]
pub dlc_killed_liuvani_first: bool,
#[serde(rename = "DLC_KilledOldMan")]
pub dlc_killed_old_man: bool,
#[serde(rename = "DLC_HasFoughtOldManOnce")]
pub dlc_has_fought_old_man_once: bool,
#[serde(rename = "DLC_HasSeenOldmanFightIntro")]
pub dlc_has_seen_oldman_fight_intro: bool,
#[serde(rename = "DLC_HadFinalOldManConvo")]
pub dlc_had_final_old_man_convo: bool,
#[serde(rename = "DLC_OldManItemsOwned")]
pub dlc_old_man_items_owned: i64,
#[serde(rename = "DLC_OldManHasArmour")]
pub dlc_old_man_has_armour: bool,
#[serde(rename = "DLC_LastBossAttemptDamage")]
pub dlc_last_boss_attempt_damage: i64,
#[serde(rename = "DLC_LastBossConvoIndex1")]
pub dlc_last_boss_convo_index1: i64,
#[serde(rename = "DLC_LastBossConvoIndex2")]
pub dlc_last_boss_convo_index2: i64,
#[serde(rename = "DLC_LastBossConvoIndex3")]
pub dlc_last_boss_convo_index3: i64,
#[serde(rename = "DLC_LastBossConvoIndex4")]
pub dlc_last_boss_convo_index4: i64,
#[serde(rename = "DLC_MadeFinalFormJoke")]
pub dlc_made_final_form_joke: bool,
#[serde(rename = "DLC_HasAttemptedLastBoss")]
pub dlc_has_attempted_last_boss: bool,
#[serde(rename = "DLC_HasTalkedToBlacksmithAboutArmour")]
pub dlc_has_talked_to_blacksmith_about_armour: bool,
#[serde(rename = "DLC_HasTalkedToBlacksmithAfterForging")]
pub dlc_has_talked_to_blacksmith_after_forging: bool,
#[serde(rename = "questStage_OldMan")]
pub quest_stage_old_man: i64,
#[serde(rename = "questStage_Heir")]
pub quest_stage_heir: i64,
#[serde(rename = "questStage_Nameless")]
pub quest_stage_nameless: i64,
#[serde(rename = "questStage_Sco")]
pub quest_stage_sco: i64,
#[serde(rename = "questStage_Innocent")]
pub quest_stage_innocent: i64,
#[serde(rename = "questStage_Maiden")]
pub quest_stage_maiden: i64,
#[serde(rename = "questStage_Hoover")]
pub quest_stage_hoover: i64,
#[serde(rename = "questStage_TheSmith")]
pub quest_stage_the_smith: i64,
#[serde(rename = "questStage_Shopkeeper")]
pub quest_stage_shopkeeper: i64,
#[serde(rename = "questStage_Sando")]
pub quest_stage_sando: i64,
#[serde(rename = "questStage_ChainedHero")]
pub quest_stage_chained_hero: i64,
#[serde(rename = "questStage_BrendenMerkle")]
pub quest_stage_brenden_merkle: i64,
}

86
src/data/world_config.rs Normal file
View file

@ -0,0 +1,86 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default)]
struct CorpseLocation {
pub x: f64,
pub y: f64,
pub z: f64,
}
#[derive(Serialize, Deserialize, Debug, Default)]
pub(crate) struct WorldConfig {
#[serde(rename = "isCorpseOnField")]
pub is_corpse_on_field: bool,
#[serde(rename = "savedMemoryOnDeath")]
pub saved_memory_on_death: bool,
#[serde(rename = "corpseLocation")]
pub corpse_location: CorpseLocation,
#[serde(rename = "corpseMemroy")]
pub corpse_memroy: i64,
#[serde(rename = "usingVerboseItemDetail")]
pub using_verbose_item_detail: bool,
#[serde(rename = "hooverBonusDisplay")]
pub hoover_bonus_display: bool,
#[serde(rename = "forgesLit")]
pub forges_lit: i64,
#[serde(rename = "ambientEventName")]
pub ambient_event_name: String,
#[serde(rename = "litBeacons")]
pub lit_beacons: Vec<String>,
#[serde(rename = "activeFidelityPoint")]
pub active_fidelity_point: String,
#[serde(rename = "messagesRated")]
pub messages_rated: Vec<String>,
#[serde(rename = "myMessages")]
pub my_messages: Vec<String>,
#[serde(rename = "collectionDropIndexes")]
pub collection_drop_indexes: Vec<String>,
#[serde(rename = "openBackDoors")]
pub open_back_doors: Vec<String>,
#[serde(rename = "playTime")]
pub play_time: f64,
#[serde(rename = "timeAtLastSaveOrLoad")]
pub time_at_last_save_or_load: f64,
#[serde(rename = "bossFightAssistances")]
pub boss_fight_assistances: i64,
#[serde(rename = "shrineBGLerpAMount")]
pub shrine_bglerp_amount: f64,
#[serde(rename = "UpperDBGLerpAmount")]
pub upper_dbglerp_amount: f64,
#[serde(rename = "MansionBGLerpAmount")]
pub mansion_bglerp_amount: f64,
#[serde(rename = "NobleWoodBGLerpAmount")]
pub noble_wood_bglerp_amount: f64,
#[serde(rename = "NobleWoodBGGeoLerpAmount")]
pub noble_wood_bggeo_lerp_amount: f64,
#[serde(rename = "HiddenVBGLerpAmount")]
pub hidden_vbglerp_amount: f64,
#[serde(rename = "MoatBGLerpAmount")]
pub moat_bglerp_amount: f64,
#[serde(rename = "MoatBGGeoLerpAmount")]
pub moat_bggeo_lerp_amount: f64,
#[serde(rename = "VCInteriorBGLerpAmount")]
pub vcinterior_bglerp_amount: f64,
#[serde(rename = "trailMarkers")]
pub trail_markers: Vec<String>,
#[serde(rename = "customObjects")]
pub custom_objects: Vec<String>,
#[serde(rename = "rehabilitationTorchesLit")]
pub rehabilitation_torches_lit: i64,
#[serde(rename = "sewerTownTorchesLit")]
pub sewer_town_torches_lit: i64,
#[serde(rename = "unlockedShopkeeperExtraInventory_1")]
pub unlocked_shopkeeper_extra_inventory_1: bool,
#[serde(rename = "unlockedShopkeeperExtraInventory_2")]
pub unlocked_shopkeeper_extra_inventory_2: bool,
#[serde(rename = "unlockedShopkeeperExtraInventory_3")]
pub unlocked_shopkeeper_extra_inventory_3: bool,
#[serde(rename = "hasEndedGameAlready")]
pub has_ended_game_already: bool,
#[serde(rename = "HV_Water_Volume")]
pub hv_water_volume: f64,
#[serde(rename = "HV_Water_ControlType")]
pub hv_water_control_type: i64,
#[serde(rename = "HV_Water_LerpIndex")]
pub hv_water_lerp_index: i64,
}

View file

@ -1,8 +1,24 @@
mod cli;
mod data;
use std::error::Error;
use clap::Parser;
use eframe; use eframe;
use eframe::egui; use eframe::egui;
use crate::cli::Options;
fn main() -> Result<(), eframe::Error> { fn main() -> Result<(), Box<dyn Error>> {
run_gui() let options = Options::parse();
let save_data = data::CoreConfig::parse_file(options.save_file)?;
println!("{}", save_data.to_string()?);
if options.gui {
run_gui()?;
}
Ok(())
} }
fn run_gui() -> Result<(), eframe::Error> { fn run_gui() -> Result<(), eframe::Error> {
@ -18,13 +34,13 @@ fn run_gui() -> Result<(), eframe::Error> {
struct SaveEditor {} struct SaveEditor {}
impl SaveEditor { impl SaveEditor {
fn new(cc: &eframe::CreationContext) -> Self { fn new(_cc: &eframe::CreationContext) -> Self {
Self::default() Self::default()
} }
} }
impl eframe::App for SaveEditor { impl eframe::App for SaveEditor {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| ui.heading("Hello World!")); egui::CentralPanel::default().show(ctx, |ui| ui.heading("Hello World!"));
} }
} }