Recover scalar-band packed event metadata

This commit is contained in:
Jan Petykiewicz 2026-04-16 11:02:21 -07:00
commit e2174713a9
8 changed files with 685 additions and 39 deletions

View file

@ -4463,6 +4463,9 @@ mod tests {
let overlay_locomotive_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
"../../fixtures/runtime/packed-event-locomotive-availability-overlay-fixture.json",
);
let scalar_band_parity_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
"../../fixtures/runtime/packed-event-world-scalar-band-parity-save-slice-fixture.json",
);
run_runtime_summarize_fixture(&parity_fixture)
.expect("save-slice-backed parity fixture should summarize");
@ -4487,6 +4490,8 @@ mod tests {
);
run_runtime_summarize_fixture(&overlay_locomotive_fixture)
.expect("overlay-backed locomotive availability fixture should summarize");
run_runtime_summarize_fixture(&scalar_band_parity_fixture)
.expect("save-slice-backed recovered scalar-band parity fixture should summarize");
}
#[test]

View file

@ -3070,11 +3070,19 @@ mod tests {
descriptor_id: u32,
value: i32,
) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
let recovered_locomotive_id = match descriptor_id {
352..=451 => Some(descriptor_id - 351),
475..=500 => Some(descriptor_id - 374),
_ => None,
};
let descriptor_label = recovered_locomotive_id
.map(|loco_id| format!("Locomotive {loco_id} Cost"))
.unwrap_or_else(|| "Locomotive Cost".to_string());
crate::SmpLoadedPackedEventGroupedEffectRowSummary {
group_index: 0,
row_index: 0,
descriptor_id,
descriptor_label: Some("Unknown Loco Cost".to_string()),
descriptor_label: Some(descriptor_label.clone()),
target_mask_bits: Some(0x08),
parameter_family: Some("locomotive_cost_scalar".to_string()),
opcode: 3,
@ -3087,12 +3095,65 @@ mod tests {
value_word_0x16: 0,
row_shape: "scalar_assignment".to_string(),
semantic_family: Some("scalar_assignment".to_string()),
semantic_preview: Some(format!("Set Unknown Loco Cost to {value}")),
recovered_locomotive_id: match descriptor_id {
352..=451 => Some(descriptor_id - 351),
475..=500 => Some(descriptor_id - 374),
_ => None,
},
semantic_preview: Some(format!("Set {descriptor_label} to {value}")),
recovered_locomotive_id,
locomotive_name: None,
notes: vec![],
}
}
fn real_cargo_production_row(
descriptor_id: u32,
value: i32,
) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
let slot = descriptor_id.saturating_sub(229);
let descriptor_label = format!("Cargo Production Slot {slot}");
crate::SmpLoadedPackedEventGroupedEffectRowSummary {
group_index: 0,
row_index: 0,
descriptor_id,
descriptor_label: Some(descriptor_label.clone()),
target_mask_bits: Some(0x08),
parameter_family: Some("cargo_production_scalar".to_string()),
opcode: 3,
raw_scalar_value: value,
value_byte_0x09: 0,
value_dword_0x0d: 0,
value_byte_0x11: 0,
value_byte_0x12: 0,
value_word_0x14: 0,
value_word_0x16: 0,
row_shape: "scalar_assignment".to_string(),
semantic_family: Some("scalar_assignment".to_string()),
semantic_preview: Some(format!("Set {descriptor_label} to {value}")),
recovered_locomotive_id: None,
locomotive_name: None,
notes: vec![],
}
}
fn real_territory_access_cost_row(
value: i32,
) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
crate::SmpLoadedPackedEventGroupedEffectRowSummary {
group_index: 0,
row_index: 0,
descriptor_id: 453,
descriptor_label: Some("Territory Access Cost".to_string()),
target_mask_bits: Some(0x08),
parameter_family: Some("territory_access_cost_scalar".to_string()),
opcode: 3,
raw_scalar_value: value,
value_byte_0x09: 0,
value_dword_0x0d: 0,
value_byte_0x11: 0,
value_byte_0x12: 0,
value_word_0x14: 0,
value_word_0x16: 0,
row_shape: "scalar_assignment".to_string(),
semantic_family: Some("scalar_assignment".to_string()),
semantic_preview: Some(format!("Set Territory Access Cost to {value}")),
recovered_locomotive_id: None,
locomotive_name: None,
notes: vec![],
}
@ -5155,6 +5216,152 @@ mod tests {
);
}
#[test]
fn keeps_recovered_cargo_production_rows_parity_only() {
let save_slice = SmpLoadedSaveSlice {
file_extension_hint: Some("gms".to_string()),
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
mechanism_family: "classic-save-rehydrate-v1".to_string(),
mechanism_confidence: "grounded".to_string(),
trailer_family: None,
bridge_family: None,
profile: None,
candidate_availability_table: None,
named_locomotive_availability_table: None,
special_conditions_table: None,
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
source_kind: "packed-event-runtime-collection".to_string(),
mechanism_family: "classic-save-rehydrate-v1".to_string(),
mechanism_confidence: "grounded".to_string(),
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
metadata_tag_offset: 0x7100,
records_tag_offset: 0x7200,
close_tag_offset: 0x7600,
packed_state_version: 0x3e9,
packed_state_version_hex: "0x000003e9".to_string(),
live_id_bound: 35,
live_record_count: 1,
live_entry_ids: vec![35],
decoded_record_count: 1,
imported_runtime_record_count: 0,
records: vec![crate::SmpLoadedPackedEventRecordSummary {
record_index: 0,
live_entry_id: 35,
payload_offset: Some(0x7202),
payload_len: Some(96),
decode_status: "parity_only".to_string(),
payload_family: "real_packed_v1".to_string(),
trigger_kind: Some(7),
active: None,
marks_collection_dirty: None,
one_shot: Some(false),
compact_control: Some(real_compact_control()),
text_bands: vec![],
standalone_condition_row_count: 0,
standalone_condition_rows: vec![],
negative_sentinel_scope: None,
grouped_effect_row_counts: vec![1, 0, 0, 0],
grouped_effect_rows: vec![real_cargo_production_row(230, 125)],
decoded_conditions: Vec::new(),
decoded_actions: vec![],
executable_import_ready: false,
notes: vec!["cargo production rows remain metadata-only".to_string()],
}],
}),
notes: vec![],
};
let import = project_save_slice_to_runtime_state_import(
&save_slice,
"packed-events-cargo-production-frontier",
None,
)
.expect("save slice should project");
assert!(import.state.event_runtime_records.is_empty());
assert_eq!(
import
.state
.packed_event_collection
.as_ref()
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
Some("blocked_unmapped_world_descriptor")
);
}
#[test]
fn keeps_recovered_territory_access_cost_rows_parity_only() {
let save_slice = SmpLoadedSaveSlice {
file_extension_hint: Some("gms".to_string()),
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
mechanism_family: "classic-save-rehydrate-v1".to_string(),
mechanism_confidence: "grounded".to_string(),
trailer_family: None,
bridge_family: None,
profile: None,
candidate_availability_table: None,
named_locomotive_availability_table: None,
special_conditions_table: None,
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
source_kind: "packed-event-runtime-collection".to_string(),
mechanism_family: "classic-save-rehydrate-v1".to_string(),
mechanism_confidence: "grounded".to_string(),
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
metadata_tag_offset: 0x7100,
records_tag_offset: 0x7200,
close_tag_offset: 0x7600,
packed_state_version: 0x3e9,
packed_state_version_hex: "0x000003e9".to_string(),
live_id_bound: 36,
live_record_count: 1,
live_entry_ids: vec![36],
decoded_record_count: 1,
imported_runtime_record_count: 0,
records: vec![crate::SmpLoadedPackedEventRecordSummary {
record_index: 0,
live_entry_id: 36,
payload_offset: Some(0x7202),
payload_len: Some(96),
decode_status: "parity_only".to_string(),
payload_family: "real_packed_v1".to_string(),
trigger_kind: Some(7),
active: None,
marks_collection_dirty: None,
one_shot: Some(false),
compact_control: Some(real_compact_control()),
text_bands: vec![],
standalone_condition_row_count: 0,
standalone_condition_rows: vec![],
negative_sentinel_scope: None,
grouped_effect_row_counts: vec![1, 0, 0, 0],
grouped_effect_rows: vec![real_territory_access_cost_row(750000)],
decoded_conditions: Vec::new(),
decoded_actions: vec![],
executable_import_ready: false,
notes: vec!["territory access cost rows remain metadata-only".to_string()],
}],
}),
notes: vec![],
};
let import = project_save_slice_to_runtime_state_import(
&save_slice,
"packed-events-territory-access-cost-frontier",
None,
)
.expect("save slice should project");
assert!(import.state.event_runtime_records.is_empty());
assert_eq!(
import
.state
.packed_event_collection
.as_ref()
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
Some("blocked_unmapped_world_descriptor")
);
}
#[test]
fn overlays_real_company_cash_descriptor_into_executable_runtime_record() {
let base_state = RuntimeState {

View file

@ -1,5 +1,7 @@
use std::collections::BTreeMap;
use std::fs;
use std::path::Path;
use std::sync::OnceLock;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
@ -2684,6 +2686,11 @@ fn parse_real_grouped_effect_row_summary(
"locomotive availability descriptor maps to live locomotive id {loco_id}"
));
}
if let Some(loco_id) = recovered_locomotive_cost_loco_id(descriptor_id) {
notes.push(format!(
"locomotive cost descriptor maps to live locomotive id {loco_id}"
));
}
Some(SmpLoadedPackedEventGroupedEffectRowSummary {
group_index,
@ -2711,7 +2718,8 @@ fn parse_real_grouped_effect_row_summary(
value_word_0x14,
value_word_0x16,
)),
recovered_locomotive_id: recovered_locomotive_availability_loco_id(descriptor_id),
recovered_locomotive_id: recovered_locomotive_availability_loco_id(descriptor_id)
.or_else(|| recovered_locomotive_cost_loco_id(descriptor_id)),
locomotive_name,
notes,
})
@ -2823,16 +2831,16 @@ fn real_grouped_effect_descriptor_metadata(
fn recovered_cargo_production_descriptor_metadata(
descriptor_id: u32,
) -> Option<RealGroupedEffectDescriptorMetadata> {
(230..=240)
.contains(&descriptor_id)
.then_some(RealGroupedEffectDescriptorMetadata {
recovered_cargo_production_label(descriptor_id).map(|label| {
RealGroupedEffectDescriptorMetadata {
descriptor_id,
label: "Unknown Cargo Production",
label,
target_mask_bits: 0x08,
parameter_family: "unknown_cargo_production_scalar",
parameter_family: "cargo_production_scalar",
runtime_key: None,
executable_in_runtime: false,
})
}
})
}
fn recovered_locomotive_availability_descriptor_metadata(
@ -2872,31 +2880,66 @@ fn recovered_locomotive_availability_loco_id(descriptor_id: u32) -> Option<u32>
None
}
fn recovered_cargo_production_label(descriptor_id: u32) -> Option<&'static str> {
static LABELS: OnceLock<BTreeMap<u32, &'static str>> = OnceLock::new();
LABELS
.get_or_init(|| {
(230..=240)
.enumerate()
.map(|(slot_index, descriptor_id)| {
let label = Box::leak(
format!("Cargo Production Slot {}", slot_index + 1).into_boxed_str(),
) as &'static str;
(descriptor_id, label)
})
.collect()
})
.get(&descriptor_id)
.copied()
}
fn recovered_locomotive_cost_loco_id(descriptor_id: u32) -> Option<u32> {
if (352..=451).contains(&descriptor_id) {
return Some(descriptor_id - 351);
}
if (475..=500).contains(&descriptor_id) {
return Some(descriptor_id - 374);
}
None
}
fn recovered_locomotive_cost_label(descriptor_id: u32) -> Option<&'static str> {
static LABELS: OnceLock<BTreeMap<u32, &'static str>> = OnceLock::new();
LABELS
.get_or_init(|| {
(352..=451)
.chain(475..=500)
.filter_map(|descriptor_id| {
recovered_locomotive_cost_loco_id(descriptor_id).map(|loco_id| {
let label = Box::leak(format!("Locomotive {loco_id} Cost").into_boxed_str())
as &'static str;
(descriptor_id, label)
})
})
.collect()
})
.get(&descriptor_id)
.copied()
}
fn recovered_locomotive_cost_descriptor_metadata(
descriptor_id: u32,
) -> Option<RealGroupedEffectDescriptorMetadata> {
(352..=451)
.contains(&descriptor_id)
.then_some(RealGroupedEffectDescriptorMetadata {
recovered_locomotive_cost_label(descriptor_id).map(|label| {
RealGroupedEffectDescriptorMetadata {
descriptor_id,
label: "Unknown Loco Cost",
label,
target_mask_bits: 0x08,
parameter_family: "locomotive_cost_scalar",
runtime_key: None,
executable_in_runtime: false,
})
.or_else(|| {
(475..=500)
.contains(&descriptor_id)
.then_some(RealGroupedEffectDescriptorMetadata {
descriptor_id,
label: "Unknown Loco Cost",
target_mask_bits: 0x08,
parameter_family: "locomotive_cost_scalar",
runtime_key: None,
executable_in_runtime: false,
})
})
}
})
}
fn recovered_territory_access_cost_descriptor_metadata(
@ -2904,7 +2947,7 @@ fn recovered_territory_access_cost_descriptor_metadata(
) -> Option<RealGroupedEffectDescriptorMetadata> {
(descriptor_id == 453).then_some(RealGroupedEffectDescriptorMetadata {
descriptor_id,
label: "Territory access cost",
label: "Territory Access Cost",
target_mask_bits: 0x08,
parameter_family: "territory_access_cost_scalar",
runtime_key: None,
@ -9292,6 +9335,81 @@ mod tests {
);
}
#[test]
fn looks_up_recovered_cargo_production_descriptor_metadata() {
let metadata =
real_grouped_effect_descriptor_metadata(230).expect("descriptor metadata should exist");
assert_eq!(metadata.label, "Cargo Production Slot 1");
assert_eq!(metadata.target_mask_bits, 0x08);
assert_eq!(metadata.parameter_family, "cargo_production_scalar");
assert_eq!(metadata.runtime_key, None);
assert!(!metadata.executable_in_runtime);
}
#[test]
fn looks_up_recovered_lower_band_locomotive_cost_descriptor_metadata() {
let metadata =
real_grouped_effect_descriptor_metadata(352).expect("descriptor metadata should exist");
assert_eq!(metadata.label, "Locomotive 1 Cost");
assert_eq!(metadata.target_mask_bits, 0x08);
assert_eq!(metadata.parameter_family, "locomotive_cost_scalar");
assert_eq!(metadata.runtime_key, None);
assert_eq!(recovered_locomotive_cost_loco_id(352), Some(1));
assert!(!metadata.executable_in_runtime);
}
#[test]
fn looks_up_recovered_upper_band_locomotive_cost_descriptor_metadata() {
let metadata =
real_grouped_effect_descriptor_metadata(475).expect("descriptor metadata should exist");
assert_eq!(metadata.label, "Locomotive 101 Cost");
assert_eq!(metadata.parameter_family, "locomotive_cost_scalar");
assert_eq!(recovered_locomotive_cost_loco_id(475), Some(101));
assert!(!metadata.executable_in_runtime);
}
#[test]
fn looks_up_recovered_territory_access_cost_descriptor_metadata() {
let metadata =
real_grouped_effect_descriptor_metadata(453).expect("descriptor metadata should exist");
assert_eq!(metadata.label, "Territory Access Cost");
assert_eq!(metadata.target_mask_bits, 0x08);
assert_eq!(metadata.parameter_family, "territory_access_cost_scalar");
assert_eq!(metadata.runtime_key, None);
assert!(!metadata.executable_in_runtime);
}
#[test]
fn parses_recovered_locomotive_cost_row_with_structured_locomotive_id() {
let row_bytes = build_real_grouped_effect_row(RealGroupedEffectRowSpec {
descriptor_id: 352,
raw_scalar_value: 250000,
opcode: 3,
value_byte_0x09: 0,
value_dword_0x0d: 0,
value_byte_0x11: 0,
value_byte_0x12: 0,
value_word_0x14: 0,
value_word_0x16: 0,
locomotive_name: None,
});
let row = parse_real_grouped_effect_row_summary(&row_bytes, 0, 0, None)
.expect("row should parse");
assert_eq!(row.descriptor_id, 352);
assert_eq!(row.descriptor_label.as_deref(), Some("Locomotive 1 Cost"));
assert_eq!(row.recovered_locomotive_id, Some(1));
assert_eq!(
row.parameter_family.as_deref(),
Some("locomotive_cost_scalar")
);
}
#[test]
fn looks_up_recovered_locomotive_policy_descriptor_metadata() {
let metadata =