Restore save-world issue and tuning state

This commit is contained in:
Jan Petykiewicz 2026-04-17 18:00:35 -07:00
commit 40078707c8
12 changed files with 520 additions and 24 deletions

View file

@ -4931,6 +4931,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,

View file

@ -280,6 +280,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -421,6 +423,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,

View file

@ -452,6 +452,14 @@ fn project_save_slice_components(
"save_slice.cargo_catalog_present".to_string(),
save_slice.cargo_catalog.is_some(),
);
world_flags.insert(
"save_slice.world_issue_37_state_present".to_string(),
save_slice.world_issue_37_state.is_some(),
);
world_flags.insert(
"save_slice.world_economic_tuning_state_present".to_string(),
save_slice.world_economic_tuning_state.is_some(),
);
world_flags.insert(
"save_slice.event_runtime_collection_present".to_string(),
save_slice.event_runtime_collection.is_some(),
@ -541,6 +549,60 @@ fn project_save_slice_components(
if let Some(family) = &save_slice.bridge_family {
metadata.insert("save_slice.bridge_family".to_string(), family.clone());
}
if let Some(issue_state) = &save_slice.world_issue_37_state {
metadata.insert(
"save_slice.world_issue_37_source_kind".to_string(),
issue_state.source_kind.clone(),
);
metadata.insert(
"save_slice.world_issue_37_semantic_family".to_string(),
issue_state.semantic_family.clone(),
);
metadata.insert(
"save_slice.world_issue_37_value".to_string(),
issue_state.issue_value.to_string(),
);
metadata.insert(
"save_slice.world_issue_37_value_hex".to_string(),
issue_state.issue_value_hex.clone(),
);
metadata.insert(
"save_slice.world_issue_37_multiplier_raw_hex".to_string(),
issue_state.multiplier_raw_hex.clone(),
);
metadata.insert(
"save_slice.world_issue_37_multiplier_value_f32".to_string(),
issue_state.multiplier_value_f32_text.clone(),
);
}
if let Some(tuning_state) = &save_slice.world_economic_tuning_state {
metadata.insert(
"save_slice.world_economic_tuning_source_kind".to_string(),
tuning_state.source_kind.clone(),
);
metadata.insert(
"save_slice.world_economic_tuning_semantic_family".to_string(),
tuning_state.semantic_family.clone(),
);
metadata.insert(
"save_slice.world_economic_tuning_mirror_raw_hex".to_string(),
tuning_state.mirror_raw_hex.clone(),
);
metadata.insert(
"save_slice.world_economic_tuning_mirror_value_f32".to_string(),
tuning_state.mirror_value_f32_text.clone(),
);
metadata.insert(
"save_slice.world_economic_tuning_lane_count".to_string(),
tuning_state.lane_raw_u32.len().to_string(),
);
for (index, value) in tuning_state.lane_value_f32_text.iter().enumerate() {
metadata.insert(
format!("save_slice.world_economic_tuning_lane_{index}_f32"),
value.clone(),
);
}
}
let save_profile = if let Some(profile) = &save_slice.profile {
metadata.insert(
@ -637,6 +699,36 @@ fn project_save_slice_components(
limited_track_building_amount: None,
economic_status_code: None,
territory_access_cost: None,
issue_37_value: save_slice
.world_issue_37_state
.as_ref()
.map(|state| state.issue_value),
issue_37_multiplier_raw_u32: save_slice
.world_issue_37_state
.as_ref()
.map(|state| state.multiplier_raw_u32),
issue_37_multiplier_value_f32_text: save_slice
.world_issue_37_state
.as_ref()
.map(|state| state.multiplier_value_f32_text.clone()),
economic_tuning_mirror_raw_u32: save_slice
.world_economic_tuning_state
.as_ref()
.map(|state| state.mirror_raw_u32),
economic_tuning_mirror_value_f32_text: save_slice
.world_economic_tuning_state
.as_ref()
.map(|state| state.mirror_value_f32_text.clone()),
economic_tuning_lane_raw_u32: save_slice
.world_economic_tuning_state
.as_ref()
.map(|state| state.lane_raw_u32.clone())
.unwrap_or_default(),
economic_tuning_lane_value_f32_text: save_slice
.world_economic_tuning_state
.as_ref()
.map(|state| state.lane_value_f32_text.clone())
.unwrap_or_default(),
absolute_counter_restore_kind: Some(
"mode-adjusted-selected-year-lane".to_string(),
),
@ -5378,6 +5470,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -5421,6 +5515,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -5542,6 +5638,25 @@ mod tests {
(5, crate::RuntimeCargoClass::FarmMine),
(9, crate::RuntimeCargoClass::Other),
])),
world_issue_37_state: Some(crate::SmpLoadedWorldIssue37State {
source_kind: "save-fixed-world-block".to_string(),
semantic_family: "world-issue-0x37".to_string(),
issue_value: 3,
issue_value_hex: "0x00000003".to_string(),
multiplier_raw_u32: 0x3d75c28f,
multiplier_raw_hex: "0x3d75c28f".to_string(),
multiplier_value_f32_text: "0.060000".to_string(),
}),
world_economic_tuning_state: Some(crate::SmpLoadedWorldEconomicTuningState {
source_kind: "save-fixed-world-block".to_string(),
semantic_family: "world-economic-tuning".to_string(),
mirror_raw_u32: 0x3f46d093,
mirror_raw_hex: "0x3f46d093".to_string(),
mirror_value_f32_text: "0.776620".to_string(),
lane_raw_u32: vec![0x3f400000, 0x3be56042],
lane_raw_hex: vec!["0x3f400000".to_string(), "0x3be56042".to_string()],
lane_value_f32_text: vec!["0.750000".to_string(), "0.007000".to_string()],
}),
company_roster: None,
chairman_profile_table: None,
special_conditions_table: Some(crate::SmpLoadedSpecialConditionsTable {
@ -5763,6 +5878,42 @@ mod tests {
.ai_ignore_territories_at_startup_enabled,
Some(false)
);
assert_eq!(import.state.world_restore.issue_37_value, Some(3));
assert_eq!(
import.state.world_restore.issue_37_multiplier_raw_u32,
Some(0x3d75c28f)
);
assert_eq!(
import
.state
.world_restore
.issue_37_multiplier_value_f32_text
.as_deref(),
Some("0.060000")
);
assert_eq!(
import.state.world_restore.economic_tuning_mirror_raw_u32,
Some(0x3f46d093)
);
assert_eq!(
import
.state
.world_restore
.economic_tuning_mirror_value_f32_text
.as_deref(),
Some("0.776620")
);
assert_eq!(
import.state.world_restore.economic_tuning_lane_raw_u32,
vec![0x3f400000, 0x3be56042]
);
assert_eq!(
import
.state
.world_restore
.economic_tuning_lane_value_f32_text,
vec!["0.750000".to_string(), "0.007000".to_string()]
);
assert_eq!(
import
.state
@ -5806,6 +5957,36 @@ mod tests {
import.state.special_conditions.get("Disable Cargo Economy"),
Some(&0)
);
assert_eq!(
import
.state
.metadata
.get("save_slice.world_issue_37_value")
.map(String::as_str),
Some("3")
);
assert_eq!(
import
.state
.metadata
.get("save_slice.world_economic_tuning_lane_count")
.map(String::as_str),
Some("2")
);
assert_eq!(
import
.state
.world_flags
.get("save_slice.world_issue_37_state_present"),
Some(&true)
);
assert_eq!(
import
.state
.world_flags
.get("save_slice.world_economic_tuning_state_present"),
Some(&true)
);
assert_eq!(
import
.state
@ -5870,6 +6051,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -5944,6 +6127,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -6045,6 +6230,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: Some(crate::SmpLoadedCompanyRoster {
source_kind: "save-direct-world-block-company-selection-only".to_string(),
semantic_family: "scenario-selected-company-context".to_string(),
@ -6096,6 +6283,8 @@ mod tests {
(5, crate::RuntimeCargoClass::FarmMine),
(9, crate::RuntimeCargoClass::Other),
])),
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -6218,6 +6407,8 @@ mod tests {
(5, crate::RuntimeCargoClass::FarmMine),
(9, crate::RuntimeCargoClass::Other),
])),
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -6318,6 +6509,8 @@ mod tests {
(5, crate::RuntimeCargoClass::FarmMine),
(9, crate::RuntimeCargoClass::Other),
])),
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -6444,6 +6637,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -6531,6 +6726,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -6686,6 +6883,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -6931,6 +7130,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7011,6 +7212,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7115,6 +7318,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7192,6 +7397,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -7272,6 +7479,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -7365,6 +7574,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7474,6 +7685,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7554,6 +7767,8 @@ mod tests {
named_locomotive_availability_table: Some(save_named_locomotive_table(61)),
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7711,6 +7926,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7813,6 +8030,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7892,6 +8111,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7971,6 +8192,8 @@ mod tests {
named_locomotive_availability_table: Some(save_named_locomotive_table(61)),
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8124,6 +8347,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8222,6 +8447,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8299,6 +8526,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8386,6 +8615,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8482,6 +8713,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8586,6 +8819,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8679,6 +8914,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8758,6 +8995,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8907,6 +9146,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9066,6 +9307,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9173,6 +9416,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9261,6 +9506,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9376,6 +9623,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9485,6 +9734,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9584,6 +9835,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9679,6 +9932,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9788,6 +10043,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9882,6 +10139,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9958,6 +10217,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10039,6 +10300,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10125,6 +10388,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10211,6 +10476,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10313,6 +10580,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10406,6 +10675,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10525,6 +10796,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10664,6 +10937,8 @@ mod tests {
(5, crate::RuntimeCargoClass::FarmMine),
(9, crate::RuntimeCargoClass::Other),
])),
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11194,6 +11469,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11378,6 +11655,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11507,6 +11786,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -11635,6 +11916,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -11764,6 +12047,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11877,6 +12162,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12065,6 +12352,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12161,6 +12450,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12259,6 +12550,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12428,6 +12721,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12580,6 +12875,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12673,6 +12970,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12799,6 +13098,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12913,6 +13214,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13082,6 +13385,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13280,6 +13585,8 @@ mod tests {
named_locomotive_availability_table: None,
locomotive_catalog: None,
cargo_catalog: None,
world_issue_37_state: None,
world_economic_tuning_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,

View file

@ -71,23 +71,23 @@ pub use smp::{
SmpLoadedPackedEventConditionRowSummary, SmpLoadedPackedEventGroupedEffectRowSummary,
SmpLoadedPackedEventNegativeSentinelScopeSummary, SmpLoadedPackedEventRecordSummary,
SmpLoadedPackedEventTextBandSummary, SmpLoadedProfile, SmpLoadedSaveSlice,
SmpLoadedSpecialConditionsTable, SmpLocomotivePolicyFieldObservation,
SmpLocomotivePolicyFloatAlignmentCandidate, SmpLocomotivePolicyNeighborhoodProbe,
SmpPackedProfileWordLane, SmpPostSpecialConditionsScalarLane,
SmpPostSpecialConditionsScalarProbe, SmpPostTextFieldNeighborhoodProbe,
SmpPostTextFloatAlignmentCandidate, SmpPostTextGroundedFieldObservation,
SmpPreRecipeScalarPlateauLane, SmpPreRecipeScalarPlateauProbe, SmpPreamble, SmpPreambleWord,
SmpRecipeBookLineSummary, SmpRecipeBookSummaryBook, SmpRecipeBookSummaryProbe,
SmpRt3105PackedProfileBlock, SmpRt3105PackedProfileProbe, SmpRt3105PostSpanBridgeProbe,
SmpRt3105SaveBridgePayloadProbe, SmpRt3105SaveNameTableEntry, SmpRt3105SaveNameTableProbe,
SmpRuntimeAnchorCycleBlock, SmpRuntimePostSpanHeaderCandidate, SmpRuntimePostSpanProbe,
SmpRuntimeTrailerBlock, SmpSaveAnchorRunBlock, SmpSaveBootstrapBlock,
SmpSaveChairmanRecordAnalysisEntry, SmpSaveCompanyChairmanAnalysisReport,
SmpSaveCompanyRecordAnalysisEntry, SmpSaveDwordCandidate, SmpSaveLoadCandidateTableSummary,
SmpSaveLoadSummary, SmpSaveScalarCandidate, SmpSaveTaggedCollectionHeaderProbe,
SmpSaveWorldEconomicTuningProbe, SmpSaveWorldIssue37Probe, SmpSaveWorldSelectionRoleAnalysis,
SmpSaveWorldSelectionRoleAnalysisEntry, SmpSecondaryVariantProbe, SmpSharedHeader,
SmpSpecialConditionEntry, SmpSpecialConditionsProbe,
SmpLoadedSpecialConditionsTable, SmpLoadedWorldEconomicTuningState, SmpLoadedWorldIssue37State,
SmpLocomotivePolicyFieldObservation, SmpLocomotivePolicyFloatAlignmentCandidate,
SmpLocomotivePolicyNeighborhoodProbe, SmpPackedProfileWordLane,
SmpPostSpecialConditionsScalarLane, SmpPostSpecialConditionsScalarProbe,
SmpPostTextFieldNeighborhoodProbe, SmpPostTextFloatAlignmentCandidate,
SmpPostTextGroundedFieldObservation, SmpPreRecipeScalarPlateauLane,
SmpPreRecipeScalarPlateauProbe, SmpPreamble, SmpPreambleWord, SmpRecipeBookLineSummary,
SmpRecipeBookSummaryBook, SmpRecipeBookSummaryProbe, SmpRt3105PackedProfileBlock,
SmpRt3105PackedProfileProbe, SmpRt3105PostSpanBridgeProbe, SmpRt3105SaveBridgePayloadProbe,
SmpRt3105SaveNameTableEntry, SmpRt3105SaveNameTableProbe, SmpRuntimeAnchorCycleBlock,
SmpRuntimePostSpanHeaderCandidate, SmpRuntimePostSpanProbe, SmpRuntimeTrailerBlock,
SmpSaveAnchorRunBlock, SmpSaveBootstrapBlock, SmpSaveChairmanRecordAnalysisEntry,
SmpSaveCompanyChairmanAnalysisReport, SmpSaveCompanyRecordAnalysisEntry, SmpSaveDwordCandidate,
SmpSaveLoadCandidateTableSummary, SmpSaveLoadSummary, SmpSaveScalarCandidate,
SmpSaveTaggedCollectionHeaderProbe, SmpSaveWorldEconomicTuningProbe, SmpSaveWorldIssue37Probe,
SmpSaveWorldSelectionRoleAnalysis, SmpSaveWorldSelectionRoleAnalysisEntry,
SmpSecondaryVariantProbe, SmpSharedHeader, SmpSpecialConditionEntry, SmpSpecialConditionsProbe,
inspect_save_company_and_chairman_analysis_bytes,
inspect_save_company_and_chairman_analysis_file, inspect_smp_bytes, inspect_smp_file,
load_save_slice_file, load_save_slice_from_report,

View file

@ -859,6 +859,20 @@ pub struct RuntimeWorldRestoreState {
#[serde(default)]
pub territory_access_cost: Option<u32>,
#[serde(default)]
pub issue_37_value: Option<u32>,
#[serde(default)]
pub issue_37_multiplier_raw_u32: Option<u32>,
#[serde(default)]
pub issue_37_multiplier_value_f32_text: Option<String>,
#[serde(default)]
pub economic_tuning_mirror_raw_u32: Option<u32>,
#[serde(default)]
pub economic_tuning_mirror_value_f32_text: Option<String>,
#[serde(default)]
pub economic_tuning_lane_raw_u32: Vec<u32>,
#[serde(default)]
pub economic_tuning_lane_value_f32_text: Vec<String>,
#[serde(default)]
pub absolute_counter_restore_kind: Option<String>,
#[serde(default)]
pub absolute_counter_adjustment_context: Option<String>,
@ -2193,6 +2207,13 @@ mod tests {
limited_track_building_amount: None,
economic_status_code: None,
territory_access_cost: None,
issue_37_value: None,
issue_37_multiplier_raw_u32: None,
issue_37_multiplier_value_f32_text: None,
economic_tuning_mirror_raw_u32: None,
economic_tuning_mirror_value_f32_text: None,
economic_tuning_lane_raw_u32: Vec::new(),
economic_tuning_lane_value_f32_text: Vec::new(),
absolute_counter_restore_kind: Some(
"mode-adjusted-selected-year-lane".to_string(),
),

View file

@ -2145,6 +2145,29 @@ pub struct SmpLoadedCargoCatalog {
pub entries: Vec<SmpLoadedCargoCatalogEntry>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpLoadedWorldIssue37State {
pub source_kind: String,
pub semantic_family: String,
pub issue_value: u32,
pub issue_value_hex: String,
pub multiplier_raw_u32: u32,
pub multiplier_raw_hex: String,
pub multiplier_value_f32_text: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpLoadedWorldEconomicTuningState {
pub source_kind: String,
pub semantic_family: String,
pub mirror_raw_u32: u32,
pub mirror_raw_hex: String,
pub mirror_value_f32_text: String,
pub lane_raw_u32: Vec<u32>,
pub lane_raw_hex: Vec<String>,
pub lane_value_f32_text: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpLoadedCompanyRosterEntry {
pub company_id: u32,
@ -2524,6 +2547,10 @@ pub struct SmpLoadedSaveSlice {
#[serde(default)]
pub cargo_catalog: Option<SmpLoadedCargoCatalog>,
#[serde(default)]
pub world_issue_37_state: Option<SmpLoadedWorldIssue37State>,
#[serde(default)]
pub world_economic_tuning_state: Option<SmpLoadedWorldEconomicTuningState>,
#[serde(default)]
pub company_roster: Option<SmpLoadedCompanyRoster>,
#[serde(default)]
pub chairman_profile_table: Option<SmpLoadedChairmanProfileTable>,
@ -2704,6 +2731,14 @@ pub fn load_save_slice_from_report(
.recipe_book_summary_probe
.as_ref()
.and_then(derive_cargo_catalog_from_recipe_book_probe);
let world_issue_37_state = report
.save_world_issue_37_probe
.as_ref()
.map(derive_loaded_world_issue_37_state_from_probe);
let world_economic_tuning_state = report
.save_world_economic_tuning_probe
.as_ref()
.map(derive_loaded_world_economic_tuning_state_from_probe);
let company_roster = report.save_company_roster_probe.clone().or_else(|| {
report
.save_world_selection_context_probe
@ -2837,6 +2872,8 @@ pub fn load_save_slice_from_report(
named_locomotive_availability_table,
locomotive_catalog,
cargo_catalog,
world_issue_37_state,
world_economic_tuning_state,
company_roster,
chairman_profile_table,
special_conditions_table,
@ -3211,6 +3248,43 @@ fn derive_cargo_catalog_from_recipe_book_probe(
})
}
fn derive_loaded_world_issue_37_state_from_probe(
probe: &SmpSaveWorldIssue37Probe,
) -> SmpLoadedWorldIssue37State {
SmpLoadedWorldIssue37State {
source_kind: probe.source_kind.clone(),
semantic_family: probe.semantic_family.clone(),
issue_value: probe.issue_value_lane.raw_u32,
issue_value_hex: probe.issue_value_lane.raw_u32_hex.clone(),
multiplier_raw_u32: probe.multiplier_lane.raw_u32,
multiplier_raw_hex: probe.multiplier_lane.raw_u32_hex.clone(),
multiplier_value_f32_text: format!("{:.6}", probe.multiplier_lane.value_f32),
}
}
fn derive_loaded_world_economic_tuning_state_from_probe(
probe: &SmpSaveWorldEconomicTuningProbe,
) -> SmpLoadedWorldEconomicTuningState {
SmpLoadedWorldEconomicTuningState {
source_kind: probe.source_kind.clone(),
semantic_family: probe.semantic_family.clone(),
mirror_raw_u32: probe.mirror_lane.raw_u32,
mirror_raw_hex: probe.mirror_lane.raw_u32_hex.clone(),
mirror_value_f32_text: format!("{:.6}", probe.mirror_lane.value_f32),
lane_raw_u32: probe.tuning_lanes.iter().map(|lane| lane.raw_u32).collect(),
lane_raw_hex: probe
.tuning_lanes
.iter()
.map(|lane| lane.raw_u32_hex.clone())
.collect(),
lane_value_f32_text: probe
.tuning_lanes
.iter()
.map(|lane| format!("{:.6}", lane.value_f32))
.collect(),
}
}
fn derive_selection_only_company_roster_from_save_world_probe(
probe: &SmpSaveWorldSelectionContextProbe,
header_probe: Option<&SmpSaveTaggedCollectionHeaderProbe>,
@ -15010,6 +15084,73 @@ mod tests {
chairman_role_gate_bytes: vec![2, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
evidence: vec![],
});
report.save_world_issue_37_probe = Some(SmpSaveWorldIssue37Probe {
profile_family: "rt3-105-save-container-v1".to_string(),
source_kind: "save-direct-world-block".to_string(),
semantic_family: "scenario-save-world-issue-0x37".to_string(),
chunk_tag_offset: 0x3ce,
payload_offset: 0x3d2,
payload_len: RT3_SAVE_WORLD_BLOCK_LEN,
payload_len_hex: format!("0x{:x}", RT3_SAVE_WORLD_BLOCK_LEN),
issue_value_lane: SmpSaveDwordCandidate {
label: "issue_0x37_value".to_string(),
relative_offset: 0x29,
relative_offset_hex: "0x29".to_string(),
raw_u32: 3,
raw_u32_hex: "0x00000003".to_string(),
value_i32: 3,
value_f32: f32::from_bits(3),
},
multiplier_lane: SmpSaveDwordCandidate {
label: "issue_0x37_multiplier".to_string(),
relative_offset: 0x25,
relative_offset_hex: "0x25".to_string(),
raw_u32: 0x3d75c28f,
raw_u32_hex: "0x3d75c28f".to_string(),
value_i32: 1031127695,
value_f32: 0.06,
},
evidence: vec![],
});
report.save_world_economic_tuning_probe = Some(SmpSaveWorldEconomicTuningProbe {
profile_family: "rt3-105-save-container-v1".to_string(),
source_kind: "save-direct-world-block".to_string(),
semantic_family: "scenario-save-world-economic-tuning".to_string(),
chunk_tag_offset: 0x3ce,
payload_offset: 0x3d2,
payload_len: RT3_SAVE_WORLD_BLOCK_LEN,
payload_len_hex: format!("0x{:x}", RT3_SAVE_WORLD_BLOCK_LEN),
mirror_lane: SmpSaveDwordCandidate {
label: "economic_tuning_mirror_lane_0".to_string(),
relative_offset: 0xbda,
relative_offset_hex: "0xbda".to_string(),
raw_u32: 0x3f46d093,
raw_u32_hex: "0x3f46d093".to_string(),
value_i32: 1061605523,
value_f32: 0.7766201,
},
tuning_lanes: vec![
SmpSaveDwordCandidate {
label: "economic_tuning_lane_0".to_string(),
relative_offset: 0xbde,
relative_offset_hex: "0xbde".to_string(),
raw_u32: 0x3f400000,
raw_u32_hex: "0x3f400000".to_string(),
value_i32: 1061158912,
value_f32: 0.75,
},
SmpSaveDwordCandidate {
label: "economic_tuning_lane_1".to_string(),
relative_offset: 0xbe2,
relative_offset_hex: "0xbe2".to_string(),
raw_u32: 0x3be56042,
raw_u32_hex: "0x3be56042".to_string(),
value_i32: 1004888130,
value_f32: 0.007,
},
],
evidence: vec![],
});
report.save_company_collection_header_probe = Some(SmpSaveTaggedCollectionHeaderProbe {
profile_family: "rt3-105-save-container-v1".to_string(),
source_kind: "save-company-tagged-header-counts".to_string(),
@ -15077,6 +15218,21 @@ mod tests {
assert_eq!(chairman_table.observed_entry_count, 2);
assert_eq!(chairman_table.selected_chairman_profile_id, Some(9));
assert!(chairman_table.entries.is_empty());
let issue_37_state = slice
.world_issue_37_state
.expect("world issue-0x37 state should load");
assert_eq!(issue_37_state.issue_value, 3);
assert_eq!(issue_37_state.multiplier_raw_hex, "0x3d75c28f");
assert_eq!(issue_37_state.multiplier_value_f32_text, "0.060000");
let tuning_state = slice
.world_economic_tuning_state
.expect("world economic tuning state should load");
assert_eq!(tuning_state.mirror_raw_hex, "0x3f46d093");
assert_eq!(tuning_state.mirror_value_f32_text, "0.776620");
assert_eq!(
tuning_state.lane_value_f32_text,
vec!["0.750000", "0.007000"]
);
assert!(
slice
@ -15090,6 +15246,12 @@ mod tests {
.iter()
.any(|note| note.contains("selected_chairman_profile_id=9"))
);
assert!(
slice
.notes
.iter()
.any(|note| note.contains("grounded issue-0x37 pair: value=3"))
);
assert!(
slice
.notes

View file

@ -20,7 +20,7 @@
"tick_slot": 1
},
"calendar_projection_is_placeholder": true,
"world_flag_count": 8,
"world_flag_count": 10,
"cargo_catalog_count": 11,
"packed_event_collection_present": false,
"event_runtime_record_count": 0

View file

@ -27,7 +27,7 @@
"packed_event_decoded_record_count": 1,
"packed_event_imported_runtime_record_count": 1,
"event_runtime_record_count": 1,
"world_flag_count": 10,
"world_flag_count": 12,
"total_event_record_service_count": 1,
"total_trigger_dispatch_count": 1
},

View file

@ -27,7 +27,7 @@
"packed_event_decoded_record_count": 1,
"packed_event_imported_runtime_record_count": 1,
"event_runtime_record_count": 1,
"world_flag_count": 10,
"world_flag_count": 12,
"total_event_record_service_count": 1,
"total_trigger_dispatch_count": 1
},

View file

@ -21,7 +21,7 @@
},
"calendar_projection_source": "base-snapshot-preserved",
"calendar_projection_is_placeholder": false,
"world_flag_count": 10,
"world_flag_count": 12,
"company_count": 1,
"packed_event_collection_present": true,
"packed_event_record_count": 2,

View file

@ -26,7 +26,7 @@
"cargo_catalog_count": 11,
"event_runtime_record_count": 2,
"cargo_production_override_count": 3,
"world_flag_count": 9,
"world_flag_count": 11,
"total_event_record_service_count": 2,
"total_trigger_dispatch_count": 2
},

View file

@ -29,7 +29,7 @@
"cargo_production_override_count": 3,
"world_restore_limited_track_building_amount": 18,
"world_restore_territory_access_cost": 750000,
"world_flag_count": 9,
"world_flag_count": 11,
"total_event_record_service_count": 2,
"total_trigger_dispatch_count": 2
},