Execute recovered world scalar event descriptors
This commit is contained in:
parent
09039d24e4
commit
13c7268b0d
23 changed files with 675 additions and 98 deletions
26
README.md
26
README.md
|
|
@ -51,23 +51,25 @@ recovered locomotives-page `real_packed_v1` record that lands in the explicit
|
||||||
`blocked_unmapped_world_descriptor` bucket. The next recovered descriptor band is now partially
|
`blocked_unmapped_world_descriptor` bucket. The next recovered descriptor band is now partially
|
||||||
executable too: descriptors `454..456` (`All Steam/Diesel/Electric Locos Avail.`) now lower
|
executable too: descriptors `454..456` (`All Steam/Diesel/Electric Locos Avail.`) now lower
|
||||||
through checked-in metadata into keyed `world_flags`, while the wider locomotive availability/cost
|
through checked-in metadata into keyed `world_flags`, while the wider locomotive availability/cost
|
||||||
scalar bands are now split more cleanly: the boolean `0/1` availability subset can import through
|
scalar bands are now split more cleanly: the recovered locomotive availability bands can import as
|
||||||
an overlay-backed `RuntimeState.locomotive_catalog` into
|
full scalar overrides through an overlay-backed `RuntimeState.locomotive_catalog` into
|
||||||
`RuntimeState.named_locomotive_availability`, while non-boolean availability payloads still remain
|
`RuntimeState.named_locomotive_availability`, while save-slice-only imports of those rows still
|
||||||
parity-only. The runtime still carries the save-owned named locomotive availability table directly
|
block explicitly when catalog context is missing. The runtime still carries the save-owned named
|
||||||
too:
|
locomotive availability table directly too:
|
||||||
checked-in save-slice documents can populate `RuntimeState.named_locomotive_availability`, and
|
checked-in save-slice documents can populate `RuntimeState.named_locomotive_availability`, and
|
||||||
imported runtime effects can mutate that map through the ordinary event-service path without
|
imported runtime effects can mutate that map through the ordinary event-service path without
|
||||||
needing full Trainbuy or live-locomotive parity. A parallel event-owned named locomotive cost map
|
needing full Trainbuy or live-locomotive parity. A parallel event-owned named locomotive cost map
|
||||||
now exists too: recovered locomotive-cost descriptors from bands `352..451` and `475..500` can
|
now exists too: recovered locomotive-cost descriptors from bands `352..451` and `475..500` can
|
||||||
import through the same overlay-backed locomotive catalog into
|
import through the same overlay-backed locomotive catalog into
|
||||||
`RuntimeState.named_locomotive_cost`, while cargo-production and territory-access-cost rows remain
|
`RuntimeState.named_locomotive_cost`, and the remaining recovered scalar world families now execute
|
||||||
metadata-rich parity-only families until a later slice grounds an honest landing surface. Explicit
|
too: cargo-production slots `230..240` lower into `cargo_production_overrides`, and descriptor
|
||||||
unmapped world-condition and world-descriptor frontier buckets still remain where current
|
`453` lowers into `world_restore.territory_access_cost`. Explicit unmapped world-condition and
|
||||||
checked-in metadata stops. Shell purchase-flow, Trainbuy refresh, cached locomotive-rating
|
world-descriptor frontier buckets still remain where current checked-in metadata stops, with the
|
||||||
recomputation, and selected-profile parity remain out of scope. Mixed supported/unsupported real
|
main scalar residue now being missing-catalog locomotive rows rather than unknown world-side
|
||||||
rows still stay parity-only. The PE32 hook remains useful as capture and integration tooling, but
|
families. Shell purchase-flow, Trainbuy refresh, cached locomotive-rating recomputation, and
|
||||||
it is no longer the main execution milestone.
|
selected-profile parity remain out of scope. Mixed supported/unsupported real rows still stay
|
||||||
|
parity-only. The PE32 hook remains useful as capture and integration tooling, but it is no longer
|
||||||
|
the main execution milestone.
|
||||||
|
|
||||||
## Project Docs
|
## Project Docs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4468,6 +4468,9 @@ mod tests {
|
||||||
let scalar_band_parity_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
let scalar_band_parity_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||||
"../../fixtures/runtime/packed-event-world-scalar-band-parity-save-slice-fixture.json",
|
"../../fixtures/runtime/packed-event-world-scalar-band-parity-save-slice-fixture.json",
|
||||||
);
|
);
|
||||||
|
let world_scalar_executable_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||||
|
"../../fixtures/runtime/packed-event-world-scalar-executable-save-slice-fixture.json",
|
||||||
|
);
|
||||||
|
|
||||||
run_runtime_summarize_fixture(&parity_fixture)
|
run_runtime_summarize_fixture(&parity_fixture)
|
||||||
.expect("save-slice-backed parity fixture should summarize");
|
.expect("save-slice-backed parity fixture should summarize");
|
||||||
|
|
@ -4496,6 +4499,8 @@ mod tests {
|
||||||
.expect("overlay-backed locomotive cost fixture should summarize");
|
.expect("overlay-backed locomotive cost fixture should summarize");
|
||||||
run_runtime_summarize_fixture(&scalar_band_parity_fixture)
|
run_runtime_summarize_fixture(&scalar_band_parity_fixture)
|
||||||
.expect("save-slice-backed recovered scalar-band parity fixture should summarize");
|
.expect("save-slice-backed recovered scalar-band parity fixture should summarize");
|
||||||
|
run_runtime_summarize_fixture(&world_scalar_executable_fixture)
|
||||||
|
.expect("save-slice-backed executable world-scalar fixture should summarize");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
},
|
},
|
||||||
|
|
@ -359,6 +360,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ pub struct ExpectedRuntimeSummary {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub world_restore_economic_status_code: Option<i32>,
|
pub world_restore_economic_status_code: Option<i32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub world_restore_territory_access_cost: Option<u32>,
|
||||||
|
#[serde(default)]
|
||||||
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
||||||
|
|
@ -160,6 +162,8 @@ pub struct ExpectedRuntimeSummary {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub named_locomotive_cost_count: Option<usize>,
|
pub named_locomotive_cost_count: Option<usize>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub cargo_production_override_count: Option<usize>,
|
||||||
|
#[serde(default)]
|
||||||
pub special_condition_count: Option<usize>,
|
pub special_condition_count: Option<usize>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub enabled_special_condition_count: Option<usize>,
|
pub enabled_special_condition_count: Option<usize>,
|
||||||
|
|
@ -373,6 +377,14 @@ impl ExpectedRuntimeSummary {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(value) = self.world_restore_territory_access_cost {
|
||||||
|
if actual.world_restore_territory_access_cost != Some(value) {
|
||||||
|
mismatches.push(format!(
|
||||||
|
"world_restore_territory_access_cost mismatch: expected {value}, got {:?}",
|
||||||
|
actual.world_restore_territory_access_cost
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(kind) = &self.world_restore_absolute_counter_restore_kind {
|
if let Some(kind) = &self.world_restore_absolute_counter_restore_kind {
|
||||||
if actual.world_restore_absolute_counter_restore_kind.as_ref() != Some(kind) {
|
if actual.world_restore_absolute_counter_restore_kind.as_ref() != Some(kind) {
|
||||||
mismatches.push(format!(
|
mismatches.push(format!(
|
||||||
|
|
@ -785,6 +797,14 @@ impl ExpectedRuntimeSummary {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(count) = self.cargo_production_override_count {
|
||||||
|
if actual.cargo_production_override_count != count {
|
||||||
|
mismatches.push(format!(
|
||||||
|
"cargo_production_override_count mismatch: expected {count}, got {}",
|
||||||
|
actual.cargo_production_override_count
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(count) = self.special_condition_count {
|
if let Some(count) = self.special_condition_count {
|
||||||
if actual.special_condition_count != count {
|
if actual.special_condition_count != count {
|
||||||
mismatches.push(format!(
|
mismatches.push(format!(
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ struct SaveSliceProjection {
|
||||||
candidate_availability: BTreeMap<String, u32>,
|
candidate_availability: BTreeMap<String, u32>,
|
||||||
named_locomotive_availability: BTreeMap<String, u32>,
|
named_locomotive_availability: BTreeMap<String, u32>,
|
||||||
named_locomotive_cost: BTreeMap<String, u32>,
|
named_locomotive_cost: BTreeMap<String, u32>,
|
||||||
|
cargo_production_overrides: BTreeMap<u32, u32>,
|
||||||
special_conditions: BTreeMap<String, u32>,
|
special_conditions: BTreeMap<String, u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,6 +252,7 @@ pub fn project_save_slice_to_runtime_state_import(
|
||||||
candidate_availability: projection.candidate_availability,
|
candidate_availability: projection.candidate_availability,
|
||||||
named_locomotive_availability: projection.named_locomotive_availability,
|
named_locomotive_availability: projection.named_locomotive_availability,
|
||||||
named_locomotive_cost: projection.named_locomotive_cost,
|
named_locomotive_cost: projection.named_locomotive_cost,
|
||||||
|
cargo_production_overrides: projection.cargo_production_overrides,
|
||||||
special_conditions: projection.special_conditions,
|
special_conditions: projection.special_conditions,
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -293,7 +295,10 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
||||||
calendar: base_state.calendar,
|
calendar: base_state.calendar,
|
||||||
world_flags,
|
world_flags,
|
||||||
save_profile: projection.save_profile,
|
save_profile: projection.save_profile,
|
||||||
world_restore: projection.world_restore,
|
world_restore: RuntimeWorldRestoreState {
|
||||||
|
territory_access_cost: base_state.world_restore.territory_access_cost,
|
||||||
|
..projection.world_restore
|
||||||
|
},
|
||||||
metadata,
|
metadata,
|
||||||
companies: base_state.companies.clone(),
|
companies: base_state.companies.clone(),
|
||||||
selected_company_id: base_state.selected_company_id,
|
selected_company_id: base_state.selected_company_id,
|
||||||
|
|
@ -311,6 +316,7 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
||||||
candidate_availability: projection.candidate_availability,
|
candidate_availability: projection.candidate_availability,
|
||||||
named_locomotive_availability: projection.named_locomotive_availability,
|
named_locomotive_availability: projection.named_locomotive_availability,
|
||||||
named_locomotive_cost: base_state.named_locomotive_cost.clone(),
|
named_locomotive_cost: base_state.named_locomotive_cost.clone(),
|
||||||
|
cargo_production_overrides: base_state.cargo_production_overrides.clone(),
|
||||||
special_conditions: projection.special_conditions,
|
special_conditions: projection.special_conditions,
|
||||||
service_state: base_state.service_state.clone(),
|
service_state: base_state.service_state.clone(),
|
||||||
};
|
};
|
||||||
|
|
@ -554,6 +560,7 @@ fn project_save_slice_components(
|
||||||
ai_ignore_territories_at_startup_enabled: special_condition_enabled(34),
|
ai_ignore_territories_at_startup_enabled: special_condition_enabled(34),
|
||||||
limited_track_building_amount: None,
|
limited_track_building_amount: None,
|
||||||
economic_status_code: None,
|
economic_status_code: None,
|
||||||
|
territory_access_cost: None,
|
||||||
absolute_counter_restore_kind: Some(
|
absolute_counter_restore_kind: Some(
|
||||||
"mode-adjusted-selected-year-lane".to_string(),
|
"mode-adjusted-selected-year-lane".to_string(),
|
||||||
),
|
),
|
||||||
|
|
@ -640,6 +647,7 @@ fn project_save_slice_components(
|
||||||
}
|
}
|
||||||
|
|
||||||
let named_locomotive_cost = BTreeMap::new();
|
let named_locomotive_cost = BTreeMap::new();
|
||||||
|
let cargo_production_overrides = BTreeMap::new();
|
||||||
|
|
||||||
for (index, note) in save_slice.notes.iter().enumerate() {
|
for (index, note) in save_slice.notes.iter().enumerate() {
|
||||||
metadata.insert(format!("save_slice.note.{index}"), note.clone());
|
metadata.insert(format!("save_slice.note.{index}"), note.clone());
|
||||||
|
|
@ -655,6 +663,7 @@ fn project_save_slice_components(
|
||||||
candidate_availability,
|
candidate_availability,
|
||||||
named_locomotive_availability,
|
named_locomotive_availability,
|
||||||
named_locomotive_cost,
|
named_locomotive_cost,
|
||||||
|
cargo_production_overrides,
|
||||||
special_conditions,
|
special_conditions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -978,6 +987,14 @@ fn lower_contextual_real_grouped_effects(
|
||||||
|
|
||||||
let mut effects = Vec::with_capacity(record.grouped_effect_rows.len());
|
let mut effects = Vec::with_capacity(record.grouped_effect_rows.len());
|
||||||
for row in &record.grouped_effect_rows {
|
for row in &record.grouped_effect_rows {
|
||||||
|
if let Some(effect) = lower_contextual_cargo_production_effect(row)? {
|
||||||
|
effects.push(effect);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(effect) = lower_contextual_territory_access_cost_effect(row)? {
|
||||||
|
effects.push(effect);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if let Some(effect) = lower_contextual_locomotive_cost_effect(row, company_context)? {
|
if let Some(effect) = lower_contextual_locomotive_cost_effect(row, company_context)? {
|
||||||
effects.push(effect);
|
effects.push(effect);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1011,10 +1028,8 @@ fn lower_contextual_locomotive_availability_effect(
|
||||||
if row.row_shape != "scalar_assignment" {
|
if row.row_shape != "scalar_assignment" {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
let value = match row.raw_scalar_value {
|
let Some(value) = u32::try_from(row.raw_scalar_value).ok() else {
|
||||||
0 => false,
|
return Ok(None);
|
||||||
1 => true,
|
|
||||||
_ => return Ok(None),
|
|
||||||
};
|
};
|
||||||
let Some(locomotive_id) = row.recovered_locomotive_id else {
|
let Some(locomotive_id) = row.recovered_locomotive_id else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
|
@ -1026,12 +1041,48 @@ fn lower_contextual_locomotive_availability_effect(
|
||||||
else {
|
else {
|
||||||
return Err(ImportBlocker::MissingLocomotiveCatalogContext);
|
return Err(ImportBlocker::MissingLocomotiveCatalogContext);
|
||||||
};
|
};
|
||||||
Ok(Some(RuntimeEffect::SetNamedLocomotiveAvailability {
|
Ok(Some(RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_contextual_cargo_production_effect(
|
||||||
|
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||||
|
) -> Result<Option<RuntimeEffect>, ImportBlocker> {
|
||||||
|
if row.parameter_family.as_deref() != Some("cargo_production_scalar") {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
if row.row_shape != "scalar_assignment" {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let Some(value) = u32::try_from(row.raw_scalar_value).ok() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
let Some(slot) = row.descriptor_id.checked_sub(229) else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
if !(1..=11).contains(&slot) {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
Ok(Some(RuntimeEffect::SetCargoProductionSlot { slot, value }))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_contextual_territory_access_cost_effect(
|
||||||
|
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||||
|
) -> Result<Option<RuntimeEffect>, ImportBlocker> {
|
||||||
|
if row.parameter_family.as_deref() != Some("territory_access_cost_scalar") {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
if row.row_shape != "scalar_assignment" {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let Some(value) = u32::try_from(row.raw_scalar_value).ok() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
Ok(Some(RuntimeEffect::SetTerritoryAccessCost { value }))
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_contextual_locomotive_cost_effect(
|
fn lower_contextual_locomotive_cost_effect(
|
||||||
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||||
company_context: &ImportRuntimeContext,
|
company_context: &ImportRuntimeContext,
|
||||||
|
|
@ -1288,12 +1339,27 @@ fn lower_condition_targets_in_effect(
|
||||||
value: *value,
|
value: *value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, value } => {
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||||
|
name: name.clone(),
|
||||||
|
value: *value,
|
||||||
|
}
|
||||||
|
}
|
||||||
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
||||||
RuntimeEffect::SetNamedLocomotiveCost {
|
RuntimeEffect::SetNamedLocomotiveCost {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
value: *value,
|
value: *value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetCargoProductionSlot { slot, value } => {
|
||||||
|
RuntimeEffect::SetCargoProductionSlot {
|
||||||
|
slot: *slot,
|
||||||
|
value: *value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RuntimeEffect::SetTerritoryAccessCost { value } => {
|
||||||
|
RuntimeEffect::SetTerritoryAccessCost { value: *value }
|
||||||
|
}
|
||||||
RuntimeEffect::SetSpecialCondition { label, value } => RuntimeEffect::SetSpecialCondition {
|
RuntimeEffect::SetSpecialCondition { label, value } => RuntimeEffect::SetSpecialCondition {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
value: *value,
|
value: *value,
|
||||||
|
|
@ -1729,12 +1795,27 @@ fn smp_runtime_effect_to_runtime_effect(
|
||||||
value: *value,
|
value: *value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, value } => {
|
||||||
|
Ok(RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||||
|
name: name.clone(),
|
||||||
|
value: *value,
|
||||||
|
})
|
||||||
|
}
|
||||||
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
||||||
Ok(RuntimeEffect::SetNamedLocomotiveCost {
|
Ok(RuntimeEffect::SetNamedLocomotiveCost {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
value: *value,
|
value: *value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetCargoProductionSlot { slot, value } => {
|
||||||
|
Ok(RuntimeEffect::SetCargoProductionSlot {
|
||||||
|
slot: *slot,
|
||||||
|
value: *value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
RuntimeEffect::SetTerritoryAccessCost { value } => {
|
||||||
|
Ok(RuntimeEffect::SetTerritoryAccessCost { value: *value })
|
||||||
|
}
|
||||||
RuntimeEffect::SetSpecialCondition { label, value } => {
|
RuntimeEffect::SetSpecialCondition { label, value } => {
|
||||||
Ok(RuntimeEffect::SetSpecialCondition {
|
Ok(RuntimeEffect::SetSpecialCondition {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
|
|
@ -2296,7 +2377,10 @@ fn runtime_effect_uses_condition_true_company(effect: &RuntimeEffect) -> bool {
|
||||||
| RuntimeEffect::DeactivatePlayer { .. }
|
| RuntimeEffect::DeactivatePlayer { .. }
|
||||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||||
|
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||||
|
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||||
|
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||||
| RuntimeEffect::SetSpecialCondition { .. }
|
| RuntimeEffect::SetSpecialCondition { .. }
|
||||||
| RuntimeEffect::ActivateEventRecord { .. }
|
| RuntimeEffect::ActivateEventRecord { .. }
|
||||||
| RuntimeEffect::DeactivateEventRecord { .. }
|
| RuntimeEffect::DeactivateEventRecord { .. }
|
||||||
|
|
@ -2375,7 +2459,10 @@ fn runtime_effect_company_target_import_blocker(
|
||||||
| RuntimeEffect::SetEconomicStatusCode { .. }
|
| RuntimeEffect::SetEconomicStatusCode { .. }
|
||||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||||
|
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||||
|
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||||
|
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||||
| RuntimeEffect::SetSpecialCondition { .. }
|
| RuntimeEffect::SetSpecialCondition { .. }
|
||||||
| RuntimeEffect::ActivateEventRecord { .. }
|
| RuntimeEffect::ActivateEventRecord { .. }
|
||||||
| RuntimeEffect::DeactivateEventRecord { .. }
|
| RuntimeEffect::DeactivateEventRecord { .. }
|
||||||
|
|
@ -2717,6 +2804,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -4882,7 +4970,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn leaves_recovered_locomotive_availability_rows_blocked_unmapped_world_descriptor() {
|
fn blocks_scalar_locomotive_availability_rows_without_catalog_context() {
|
||||||
let save_slice = SmpLoadedSaveSlice {
|
let save_slice = SmpLoadedSaveSlice {
|
||||||
file_extension_hint: Some("gms".to_string()),
|
file_extension_hint: Some("gms".to_string()),
|
||||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||||
|
|
@ -4953,7 +5041,7 @@ mod tests {
|
||||||
executable_import_ready: false,
|
executable_import_ready: false,
|
||||||
notes: vec![
|
notes: vec![
|
||||||
"decoded from grounded real 0x4e9a row framing".to_string(),
|
"decoded from grounded real 0x4e9a row framing".to_string(),
|
||||||
"recovered locomotive availability descriptor family remains parity-only"
|
"scalar locomotive availability rows still need catalog context"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
|
|
@ -4975,7 +5063,7 @@ mod tests {
|
||||||
.packed_event_collection
|
.packed_event_collection
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||||
Some("blocked_unmapped_world_descriptor")
|
Some("blocked_missing_locomotive_catalog_context")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5056,7 +5144,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn overlays_boolean_locomotive_availability_rows_into_named_availability_effects() {
|
fn overlays_scalar_locomotive_availability_rows_into_named_availability_effects() {
|
||||||
let base_state = RuntimeState {
|
let base_state = RuntimeState {
|
||||||
calendar: CalendarPoint {
|
calendar: CalendarPoint {
|
||||||
year: 1845,
|
year: 1845,
|
||||||
|
|
@ -5094,6 +5182,7 @@ mod tests {
|
||||||
("Locomotive 112".to_string(), 1),
|
("Locomotive 112".to_string(), 1),
|
||||||
]),
|
]),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -5141,14 +5230,14 @@ mod tests {
|
||||||
negative_sentinel_scope: None,
|
negative_sentinel_scope: None,
|
||||||
grouped_effect_row_counts: vec![2, 0, 0, 0],
|
grouped_effect_row_counts: vec![2, 0, 0, 0],
|
||||||
grouped_effect_rows: vec![
|
grouped_effect_rows: vec![
|
||||||
real_locomotive_availability_row(250, 1),
|
real_locomotive_availability_row(250, 42),
|
||||||
real_locomotive_availability_row(457, 0),
|
real_locomotive_availability_row(457, 7),
|
||||||
],
|
],
|
||||||
decoded_conditions: Vec::new(),
|
decoded_conditions: Vec::new(),
|
||||||
decoded_actions: vec![],
|
decoded_actions: vec![],
|
||||||
executable_import_ready: false,
|
executable_import_ready: false,
|
||||||
notes: vec![
|
notes: vec![
|
||||||
"boolean locomotive availability rows use overlay catalog context"
|
"scalar locomotive availability rows use overlay catalog context"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
|
|
@ -5185,14 +5274,14 @@ mod tests {
|
||||||
.state
|
.state
|
||||||
.named_locomotive_availability
|
.named_locomotive_availability
|
||||||
.get("Locomotive 10"),
|
.get("Locomotive 10"),
|
||||||
Some(&1)
|
Some(&42)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
import
|
import
|
||||||
.state
|
.state
|
||||||
.named_locomotive_availability
|
.named_locomotive_availability
|
||||||
.get("Locomotive 112"),
|
.get("Locomotive 112"),
|
||||||
Some(&0)
|
Some(&7)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5385,6 +5474,7 @@ mod tests {
|
||||||
("Locomotive 1".to_string(), 100000),
|
("Locomotive 1".to_string(), 100000),
|
||||||
("Locomotive 101".to_string(), 200000),
|
("Locomotive 101".to_string(), 200000),
|
||||||
]),
|
]),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -5554,7 +5644,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn keeps_recovered_cargo_production_rows_parity_only() {
|
fn imports_recovered_cargo_production_rows_into_runtime_records() {
|
||||||
let save_slice = SmpLoadedSaveSlice {
|
let save_slice = SmpLoadedSaveSlice {
|
||||||
file_extension_hint: Some("gms".to_string()),
|
file_extension_hint: Some("gms".to_string()),
|
||||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||||
|
|
@ -5602,32 +5692,42 @@ mod tests {
|
||||||
decoded_conditions: Vec::new(),
|
decoded_conditions: Vec::new(),
|
||||||
decoded_actions: vec![],
|
decoded_actions: vec![],
|
||||||
executable_import_ready: false,
|
executable_import_ready: false,
|
||||||
notes: vec!["cargo production rows remain metadata-only".to_string()],
|
notes: vec![
|
||||||
|
"cargo production rows now import through world overrides".to_string(),
|
||||||
|
],
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
notes: vec![],
|
notes: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let import = project_save_slice_to_runtime_state_import(
|
let mut import = project_save_slice_to_runtime_state_import(
|
||||||
&save_slice,
|
&save_slice,
|
||||||
"packed-events-cargo-production-frontier",
|
"packed-events-cargo-production-frontier",
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.expect("save slice should project");
|
.expect("save slice should project");
|
||||||
|
|
||||||
assert!(import.state.event_runtime_records.is_empty());
|
assert_eq!(import.state.event_runtime_records.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
import
|
import
|
||||||
.state
|
.state
|
||||||
.packed_event_collection
|
.packed_event_collection
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||||
Some("blocked_unmapped_world_descriptor")
|
Some("imported")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
execute_step_command(
|
||||||
|
&mut import.state,
|
||||||
|
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||||
|
)
|
||||||
|
.expect("cargo production runtime record should run");
|
||||||
|
|
||||||
|
assert_eq!(import.state.cargo_production_overrides.get(&1), Some(&125));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn keeps_recovered_territory_access_cost_rows_parity_only() {
|
fn imports_recovered_territory_access_cost_rows_into_runtime_records() {
|
||||||
let save_slice = SmpLoadedSaveSlice {
|
let save_slice = SmpLoadedSaveSlice {
|
||||||
file_extension_hint: Some("gms".to_string()),
|
file_extension_hint: Some("gms".to_string()),
|
||||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||||
|
|
@ -5675,27 +5775,40 @@ mod tests {
|
||||||
decoded_conditions: Vec::new(),
|
decoded_conditions: Vec::new(),
|
||||||
decoded_actions: vec![],
|
decoded_actions: vec![],
|
||||||
executable_import_ready: false,
|
executable_import_ready: false,
|
||||||
notes: vec!["territory access cost rows remain metadata-only".to_string()],
|
notes: vec![
|
||||||
|
"territory access cost rows now import through world restore".to_string(),
|
||||||
|
],
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
notes: vec![],
|
notes: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let import = project_save_slice_to_runtime_state_import(
|
let mut import = project_save_slice_to_runtime_state_import(
|
||||||
&save_slice,
|
&save_slice,
|
||||||
"packed-events-territory-access-cost-frontier",
|
"packed-events-territory-access-cost-frontier",
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.expect("save slice should project");
|
.expect("save slice should project");
|
||||||
|
|
||||||
assert!(import.state.event_runtime_records.is_empty());
|
assert_eq!(import.state.event_runtime_records.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
import
|
import
|
||||||
.state
|
.state
|
||||||
.packed_event_collection
|
.packed_event_collection
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||||
Some("blocked_unmapped_world_descriptor")
|
Some("imported")
|
||||||
|
);
|
||||||
|
|
||||||
|
execute_step_command(
|
||||||
|
&mut import.state,
|
||||||
|
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||||
|
)
|
||||||
|
.expect("territory access cost runtime record should run");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
import.state.world_restore.territory_access_cost,
|
||||||
|
Some(750000)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5736,6 +5849,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -8596,6 +8710,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState {
|
service_state: RuntimeServiceState {
|
||||||
periodic_boundary_calls: 9,
|
periodic_boundary_calls: 9,
|
||||||
|
|
@ -8766,6 +8881,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -317,10 +317,21 @@ pub enum RuntimeEffect {
|
||||||
name: String,
|
name: String,
|
||||||
value: bool,
|
value: bool,
|
||||||
},
|
},
|
||||||
|
SetNamedLocomotiveAvailabilityValue {
|
||||||
|
name: String,
|
||||||
|
value: u32,
|
||||||
|
},
|
||||||
SetNamedLocomotiveCost {
|
SetNamedLocomotiveCost {
|
||||||
name: String,
|
name: String,
|
||||||
value: u32,
|
value: u32,
|
||||||
},
|
},
|
||||||
|
SetCargoProductionSlot {
|
||||||
|
slot: u32,
|
||||||
|
value: u32,
|
||||||
|
},
|
||||||
|
SetTerritoryAccessCost {
|
||||||
|
value: u32,
|
||||||
|
},
|
||||||
SetSpecialCondition {
|
SetSpecialCondition {
|
||||||
label: String,
|
label: String,
|
||||||
value: u32,
|
value: u32,
|
||||||
|
|
@ -614,6 +625,8 @@ pub struct RuntimeWorldRestoreState {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub economic_status_code: Option<i32>,
|
pub economic_status_code: Option<i32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub territory_access_cost: Option<u32>,
|
||||||
|
#[serde(default)]
|
||||||
pub absolute_counter_restore_kind: Option<String>,
|
pub absolute_counter_restore_kind: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub absolute_counter_adjustment_context: Option<String>,
|
pub absolute_counter_adjustment_context: Option<String>,
|
||||||
|
|
@ -659,6 +672,8 @@ pub struct RuntimeState {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub named_locomotive_cost: BTreeMap<String, u32>,
|
pub named_locomotive_cost: BTreeMap<String, u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub cargo_production_overrides: BTreeMap<u32, u32>,
|
||||||
|
#[serde(default)]
|
||||||
pub special_conditions: BTreeMap<String, u32>,
|
pub special_conditions: BTreeMap<String, u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub service_state: RuntimeServiceState,
|
pub service_state: RuntimeServiceState,
|
||||||
|
|
@ -1173,6 +1188,14 @@ impl RuntimeState {
|
||||||
return Err("named_locomotive_cost contains an empty key".to_string());
|
return Err("named_locomotive_cost contains an empty key".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for slot in self.cargo_production_overrides.keys() {
|
||||||
|
if !(1..=11).contains(slot) {
|
||||||
|
return Err(format!(
|
||||||
|
"cargo_production_overrides contains out-of-range slot {}",
|
||||||
|
slot
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
for key in self.special_conditions.keys() {
|
for key in self.special_conditions.keys() {
|
||||||
if key.trim().is_empty() {
|
if key.trim().is_empty() {
|
||||||
return Err("special_conditions contains an empty key".to_string());
|
return Err("special_conditions contains an empty key".to_string());
|
||||||
|
|
@ -1249,11 +1272,22 @@ fn validate_runtime_effect(
|
||||||
return Err("name must not be empty".to_string());
|
return Err("name must not be empty".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, .. } => {
|
||||||
|
if name.trim().is_empty() {
|
||||||
|
return Err("name must not be empty".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
RuntimeEffect::SetNamedLocomotiveCost { name, .. } => {
|
RuntimeEffect::SetNamedLocomotiveCost { name, .. } => {
|
||||||
if name.trim().is_empty() {
|
if name.trim().is_empty() {
|
||||||
return Err("name must not be empty".to_string());
|
return Err("name must not be empty".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetCargoProductionSlot { slot, .. } => {
|
||||||
|
if !(1..=11).contains(slot) {
|
||||||
|
return Err("slot must be in 1..=11".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RuntimeEffect::SetTerritoryAccessCost { .. } => {}
|
||||||
RuntimeEffect::SetSpecialCondition { label, .. } => {
|
RuntimeEffect::SetSpecialCondition { label, .. } => {
|
||||||
if label.trim().is_empty() {
|
if label.trim().is_empty() {
|
||||||
return Err("label must not be empty".to_string());
|
return Err("label must not be empty".to_string());
|
||||||
|
|
@ -1476,6 +1510,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1512,6 +1547,7 @@ mod tests {
|
||||||
ai_ignore_territories_at_startup_enabled: Some(false),
|
ai_ignore_territories_at_startup_enabled: Some(false),
|
||||||
limited_track_building_amount: None,
|
limited_track_building_amount: None,
|
||||||
economic_status_code: None,
|
economic_status_code: None,
|
||||||
|
territory_access_cost: None,
|
||||||
absolute_counter_restore_kind: Some(
|
absolute_counter_restore_kind: Some(
|
||||||
"mode-adjusted-selected-year-lane".to_string(),
|
"mode-adjusted-selected-year-lane".to_string(),
|
||||||
),
|
),
|
||||||
|
|
@ -1534,6 +1570,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1591,6 +1628,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1658,6 +1696,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1756,6 +1795,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1800,6 +1840,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1844,6 +1885,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1905,6 +1947,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1956,6 +1999,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -2011,6 +2055,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -2062,6 +2107,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -2119,6 +2165,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -2170,6 +2217,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -2221,6 +2269,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2838,7 +2838,7 @@ fn recovered_cargo_production_descriptor_metadata(
|
||||||
target_mask_bits: 0x08,
|
target_mask_bits: 0x08,
|
||||||
parameter_family: "cargo_production_scalar",
|
parameter_family: "cargo_production_scalar",
|
||||||
runtime_key: None,
|
runtime_key: None,
|
||||||
executable_in_runtime: false,
|
executable_in_runtime: true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -2951,7 +2951,7 @@ fn recovered_territory_access_cost_descriptor_metadata(
|
||||||
target_mask_bits: 0x08,
|
target_mask_bits: 0x08,
|
||||||
parameter_family: "territory_access_cost_scalar",
|
parameter_family: "territory_access_cost_scalar",
|
||||||
runtime_key: None,
|
runtime_key: None,
|
||||||
executable_in_runtime: false,
|
executable_in_runtime: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3241,6 +3241,28 @@ fn decode_real_grouped_effect_action(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if descriptor_metadata.executable_in_runtime
|
||||||
|
&& descriptor_metadata.parameter_family == "cargo_production_scalar"
|
||||||
|
&& row.row_shape == "scalar_assignment"
|
||||||
|
&& row.raw_scalar_value >= 0
|
||||||
|
{
|
||||||
|
let slot = descriptor_metadata.descriptor_id.checked_sub(229)?;
|
||||||
|
return Some(RuntimeEffect::SetCargoProductionSlot {
|
||||||
|
slot,
|
||||||
|
value: row.raw_scalar_value as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if descriptor_metadata.executable_in_runtime
|
||||||
|
&& descriptor_metadata.parameter_family == "territory_access_cost_scalar"
|
||||||
|
&& row.row_shape == "scalar_assignment"
|
||||||
|
&& row.raw_scalar_value >= 0
|
||||||
|
{
|
||||||
|
return Some(RuntimeEffect::SetTerritoryAccessCost {
|
||||||
|
value: row.raw_scalar_value as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if descriptor_metadata.executable_in_runtime
|
if descriptor_metadata.executable_in_runtime
|
||||||
&& descriptor_metadata.parameter_family == "world_flag_toggle"
|
&& descriptor_metadata.parameter_family == "world_flag_toggle"
|
||||||
&& row.row_shape == "bool_toggle"
|
&& row.row_shape == "bool_toggle"
|
||||||
|
|
@ -3489,7 +3511,10 @@ fn runtime_effect_supported_for_save_import(effect: &RuntimeEffect) -> bool {
|
||||||
| RuntimeEffect::SetEconomicStatusCode { .. }
|
| RuntimeEffect::SetEconomicStatusCode { .. }
|
||||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||||
|
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||||
|
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||||
|
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||||
| RuntimeEffect::SetSpecialCondition { .. }
|
| RuntimeEffect::SetSpecialCondition { .. }
|
||||||
| RuntimeEffect::ConfiscateCompanyAssets { .. }
|
| RuntimeEffect::ConfiscateCompanyAssets { .. }
|
||||||
| RuntimeEffect::DeactivateCompany { .. }
|
| RuntimeEffect::DeactivateCompany { .. }
|
||||||
|
|
@ -9345,7 +9370,7 @@ mod tests {
|
||||||
assert_eq!(metadata.target_mask_bits, 0x08);
|
assert_eq!(metadata.target_mask_bits, 0x08);
|
||||||
assert_eq!(metadata.parameter_family, "cargo_production_scalar");
|
assert_eq!(metadata.parameter_family, "cargo_production_scalar");
|
||||||
assert_eq!(metadata.runtime_key, None);
|
assert_eq!(metadata.runtime_key, None);
|
||||||
assert!(!metadata.executable_in_runtime);
|
assert!(metadata.executable_in_runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -9381,7 +9406,7 @@ mod tests {
|
||||||
assert_eq!(metadata.target_mask_bits, 0x08);
|
assert_eq!(metadata.target_mask_bits, 0x08);
|
||||||
assert_eq!(metadata.parameter_family, "territory_access_cost_scalar");
|
assert_eq!(metadata.parameter_family, "territory_access_cost_scalar");
|
||||||
assert_eq!(metadata.runtime_key, None);
|
assert_eq!(metadata.runtime_key, None);
|
||||||
assert!(!metadata.executable_in_runtime);
|
assert!(metadata.executable_in_runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -495,9 +495,20 @@ fn apply_runtime_effects(
|
||||||
.named_locomotive_availability
|
.named_locomotive_availability
|
||||||
.insert(name.clone(), u32::from(*value));
|
.insert(name.clone(), u32::from(*value));
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, value } => {
|
||||||
|
state
|
||||||
|
.named_locomotive_availability
|
||||||
|
.insert(name.clone(), *value);
|
||||||
|
}
|
||||||
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
||||||
state.named_locomotive_cost.insert(name.clone(), *value);
|
state.named_locomotive_cost.insert(name.clone(), *value);
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetCargoProductionSlot { slot, value } => {
|
||||||
|
state.cargo_production_overrides.insert(*slot, *value);
|
||||||
|
}
|
||||||
|
RuntimeEffect::SetTerritoryAccessCost { value } => {
|
||||||
|
state.world_restore.territory_access_cost = Some(*value);
|
||||||
|
}
|
||||||
RuntimeEffect::SetSpecialCondition { label, value } => {
|
RuntimeEffect::SetSpecialCondition { label, value } => {
|
||||||
state.special_conditions.insert(label.clone(), *value);
|
state.special_conditions.insert(label.clone(), *value);
|
||||||
}
|
}
|
||||||
|
|
@ -1169,6 +1180,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -1457,6 +1469,80 @@ mod tests {
|
||||||
assert_eq!(result.service_events[0].applied_effect_count, 2);
|
assert_eq!(result.service_events[0].applied_effect_count, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn applies_scalar_named_locomotive_availability_effects() {
|
||||||
|
let mut state = RuntimeState {
|
||||||
|
event_runtime_records: vec![RuntimeEventRecord {
|
||||||
|
record_id: 12,
|
||||||
|
trigger_kind: 7,
|
||||||
|
active: true,
|
||||||
|
service_count: 0,
|
||||||
|
marks_collection_dirty: false,
|
||||||
|
one_shot: false,
|
||||||
|
has_fired: false,
|
||||||
|
conditions: Vec::new(),
|
||||||
|
effects: vec![
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||||
|
name: "Big Boy".to_string(),
|
||||||
|
value: 42,
|
||||||
|
},
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||||
|
name: "GP7".to_string(),
|
||||||
|
value: 7,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
..state()
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = execute_step_command(
|
||||||
|
&mut state,
|
||||||
|
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||||
|
)
|
||||||
|
.expect("scalar named locomotive availability effects should succeed");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
state.named_locomotive_availability.get("Big Boy"),
|
||||||
|
Some(&42)
|
||||||
|
);
|
||||||
|
assert_eq!(state.named_locomotive_availability.get("GP7"), Some(&7));
|
||||||
|
assert_eq!(result.service_events[0].applied_effect_count, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn applies_world_scalar_override_effects() {
|
||||||
|
let mut state = RuntimeState {
|
||||||
|
event_runtime_records: vec![RuntimeEventRecord {
|
||||||
|
record_id: 13,
|
||||||
|
trigger_kind: 7,
|
||||||
|
active: true,
|
||||||
|
service_count: 0,
|
||||||
|
marks_collection_dirty: false,
|
||||||
|
one_shot: false,
|
||||||
|
has_fired: false,
|
||||||
|
conditions: Vec::new(),
|
||||||
|
effects: vec![
|
||||||
|
RuntimeEffect::SetCargoProductionSlot {
|
||||||
|
slot: 1,
|
||||||
|
value: 125,
|
||||||
|
},
|
||||||
|
RuntimeEffect::SetTerritoryAccessCost { value: 750000 },
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
..state()
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = execute_step_command(
|
||||||
|
&mut state,
|
||||||
|
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||||
|
)
|
||||||
|
.expect("world scalar override effects should succeed");
|
||||||
|
|
||||||
|
assert_eq!(state.cargo_production_overrides.get(&1), Some(&125));
|
||||||
|
assert_eq!(state.world_restore.territory_access_cost, Some(750000));
|
||||||
|
assert_eq!(result.service_events[0].applied_effect_count, 2);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn resolves_symbolic_company_targets() {
|
fn resolves_symbolic_company_targets() {
|
||||||
let mut state = RuntimeState {
|
let mut state = RuntimeState {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ pub struct RuntimeSummary {
|
||||||
pub world_restore_ai_ignore_territories_at_startup_enabled: Option<bool>,
|
pub world_restore_ai_ignore_territories_at_startup_enabled: Option<bool>,
|
||||||
pub world_restore_limited_track_building_amount: Option<i32>,
|
pub world_restore_limited_track_building_amount: Option<i32>,
|
||||||
pub world_restore_economic_status_code: Option<i32>,
|
pub world_restore_economic_status_code: Option<i32>,
|
||||||
|
pub world_restore_territory_access_cost: Option<u32>,
|
||||||
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
||||||
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
||||||
pub metadata_count: usize,
|
pub metadata_count: usize,
|
||||||
|
|
@ -77,6 +78,7 @@ pub struct RuntimeSummary {
|
||||||
pub named_locomotive_availability_count: usize,
|
pub named_locomotive_availability_count: usize,
|
||||||
pub zero_named_locomotive_availability_count: usize,
|
pub zero_named_locomotive_availability_count: usize,
|
||||||
pub named_locomotive_cost_count: usize,
|
pub named_locomotive_cost_count: usize,
|
||||||
|
pub cargo_production_override_count: usize,
|
||||||
pub special_condition_count: usize,
|
pub special_condition_count: usize,
|
||||||
pub enabled_special_condition_count: usize,
|
pub enabled_special_condition_count: usize,
|
||||||
pub save_profile_kind: Option<String>,
|
pub save_profile_kind: Option<String>,
|
||||||
|
|
@ -149,6 +151,7 @@ impl RuntimeSummary {
|
||||||
.world_restore
|
.world_restore
|
||||||
.limited_track_building_amount,
|
.limited_track_building_amount,
|
||||||
world_restore_economic_status_code: state.world_restore.economic_status_code,
|
world_restore_economic_status_code: state.world_restore.economic_status_code,
|
||||||
|
world_restore_territory_access_cost: state.world_restore.territory_access_cost,
|
||||||
world_restore_absolute_counter_restore_kind: state
|
world_restore_absolute_counter_restore_kind: state
|
||||||
.world_restore
|
.world_restore
|
||||||
.absolute_counter_restore_kind
|
.absolute_counter_restore_kind
|
||||||
|
|
@ -597,6 +600,7 @@ impl RuntimeSummary {
|
||||||
.filter(|value| **value == 0)
|
.filter(|value| **value == 0)
|
||||||
.count(),
|
.count(),
|
||||||
named_locomotive_cost_count: state.named_locomotive_cost.len(),
|
named_locomotive_cost_count: state.named_locomotive_cost.len(),
|
||||||
|
cargo_production_override_count: state.cargo_production_overrides.len(),
|
||||||
special_condition_count: state.special_conditions.len(),
|
special_condition_count: state.special_conditions.len(),
|
||||||
enabled_special_condition_count: state
|
enabled_special_condition_count: state
|
||||||
.special_conditions
|
.special_conditions
|
||||||
|
|
@ -820,6 +824,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -920,6 +925,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -969,6 +975,7 @@ mod tests {
|
||||||
("Mikado".to_string(), 0),
|
("Mikado".to_string(), 0),
|
||||||
]),
|
]),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1010,6 +1017,7 @@ mod tests {
|
||||||
("Big Boy".to_string(), 250000),
|
("Big Boy".to_string(), 250000),
|
||||||
("GP7".to_string(), 175000),
|
("GP7".to_string(), 175000),
|
||||||
]),
|
]),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1019,6 +1027,47 @@ mod tests {
|
||||||
assert_eq!(summary.named_locomotive_cost_count, 2);
|
assert_eq!(summary.named_locomotive_cost_count, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn counts_world_scalar_override_surfaces() {
|
||||||
|
let state = RuntimeState {
|
||||||
|
calendar: CalendarPoint {
|
||||||
|
year: 1830,
|
||||||
|
month_slot: 0,
|
||||||
|
phase_slot: 0,
|
||||||
|
tick_slot: 0,
|
||||||
|
},
|
||||||
|
world_flags: BTreeMap::new(),
|
||||||
|
save_profile: RuntimeSaveProfileState::default(),
|
||||||
|
world_restore: RuntimeWorldRestoreState {
|
||||||
|
territory_access_cost: Some(750000),
|
||||||
|
..RuntimeWorldRestoreState::default()
|
||||||
|
},
|
||||||
|
metadata: BTreeMap::new(),
|
||||||
|
companies: Vec::new(),
|
||||||
|
selected_company_id: None,
|
||||||
|
players: Vec::new(),
|
||||||
|
selected_player_id: None,
|
||||||
|
trains: Vec::new(),
|
||||||
|
locomotive_catalog: Vec::new(),
|
||||||
|
territories: Vec::new(),
|
||||||
|
company_territory_track_piece_counts: Vec::new(),
|
||||||
|
company_territory_access: Vec::new(),
|
||||||
|
packed_event_collection: None,
|
||||||
|
event_runtime_records: Vec::new(),
|
||||||
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::from([(1, 125), (2, 250)]),
|
||||||
|
special_conditions: BTreeMap::new(),
|
||||||
|
service_state: RuntimeServiceState::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let summary = RuntimeSummary::from_state(&state);
|
||||||
|
|
||||||
|
assert_eq!(summary.cargo_production_override_count, 2);
|
||||||
|
assert_eq!(summary.world_restore_territory_access_cost, Some(750000));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn counts_world_frontier_buckets_separately() {
|
fn counts_world_frontier_buckets_separately() {
|
||||||
let state = RuntimeState {
|
let state = RuntimeState {
|
||||||
|
|
@ -1110,6 +1159,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1189,6 +1239,7 @@ mod tests {
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
named_locomotive_availability: BTreeMap::new(),
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
named_locomotive_cost: BTreeMap::new(),
|
named_locomotive_cost: BTreeMap::new(),
|
||||||
|
cargo_production_overrides: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -126,16 +126,18 @@ The highest-value next passes are now:
|
||||||
- the next recovered locomotives-page descriptor batch is partially executable too:
|
- the next recovered locomotives-page descriptor batch is partially executable too:
|
||||||
descriptors `454..456` (`All Steam/Diesel/Electric Locos Avail.`) now lower through checked-in
|
descriptors `454..456` (`All Steam/Diesel/Electric Locos Avail.`) now lower through checked-in
|
||||||
metadata into keyed `world_flags`, while the wider locomotive availability/cost scalar bands now
|
metadata into keyed `world_flags`, while the wider locomotive availability/cost scalar bands now
|
||||||
split cleanly between executable boolean availability rows and recovered metadata-rich parity
|
split cleanly between executable scalar availability/cost rows and the remaining world-side
|
||||||
rows for the remaining cargo-production, locomotive-cost, and territory-access-cost families
|
scalar families
|
||||||
- the runtime now also carries both the save-owned named locomotive availability table and an
|
- the runtime now also carries both the save-owned named locomotive availability table and an
|
||||||
overlay-backed locomotive catalog context: checked-in save-slice documents can populate
|
overlay-backed locomotive catalog context: checked-in save-slice documents can populate
|
||||||
`RuntimeState.named_locomotive_availability`, and boolean `0/1` availability descriptors can
|
`RuntimeState.named_locomotive_availability`, and recovered scalar availability descriptors can
|
||||||
lower through `RuntimeState.locomotive_catalog` into the same ordinary event-service path
|
lower through `RuntimeState.locomotive_catalog` into the same ordinary event-service path
|
||||||
- that same overlay-backed locomotive catalog now unlocks the recovered locomotive-cost bands too:
|
- that same overlay-backed locomotive catalog now unlocks the recovered locomotive-cost bands too:
|
||||||
nonnegative scalar rows from descriptors `352..451` and `475..500` can lower into the new
|
nonnegative scalar rows from descriptors `352..451` and `475..500` can lower into the new
|
||||||
event-owned `RuntimeState.named_locomotive_cost` map through the ordinary runtime path, while
|
event-owned `RuntimeState.named_locomotive_cost` map through the ordinary runtime path
|
||||||
cargo-production and territory-access-cost rows remain metadata-rich parity-only families
|
- cargo-production `230..240` and territory-access-cost `453` now execute too through minimal
|
||||||
|
world-side scalar landing surfaces: slot-indexed `cargo_production_overrides` and
|
||||||
|
`world_restore.territory_access_cost`
|
||||||
- keep in mind that the current local `.gms` corpus still exports with no packed event collection,
|
- keep in mind that the current local `.gms` corpus still exports with no packed event collection,
|
||||||
so real descriptor mapping needs to stay plumbing-first until better captures exist
|
so real descriptor mapping needs to stay plumbing-first until better captures exist
|
||||||
- use `rrt-hook` primarily as optional capture or integration tooling, not as the first execution
|
- use `rrt-hook` primarily as optional capture or integration tooling, not as the first execution
|
||||||
|
|
|
||||||
|
|
@ -86,21 +86,22 @@ Implemented today:
|
||||||
save-slice documents can carry the persisted `[world+0x66b6]` name table into
|
save-slice documents can carry the persisted `[world+0x66b6]` name table into
|
||||||
`RuntimeState.named_locomotive_availability`, and imported runtime effects can mutate that map
|
`RuntimeState.named_locomotive_availability`, and imported runtime effects can mutate that map
|
||||||
through the ordinary event-service path without requiring Trainbuy or live locomotive-pool parity
|
through the ordinary event-service path without requiring Trainbuy or live locomotive-pool parity
|
||||||
- the boolean `0/1` subset of the recovered locomotives-page availability bands can now import
|
- the recovered locomotives-page availability bands can now import as full scalar overrides
|
||||||
through an overlay-backed `RuntimeState.locomotive_catalog`; non-boolean availability payloads
|
through an overlay-backed `RuntimeState.locomotive_catalog` into
|
||||||
still remain parity-only, but the adjacent locomotive-cost bands `352..451` and `475..500` now
|
`RuntimeState.named_locomotive_availability`; save-slice-only imports of those rows now fail on
|
||||||
import too through the same overlay-backed catalog into the event-owned
|
the explicit `blocked_missing_locomotive_catalog_context` frontier rather than a generic
|
||||||
`RuntimeState.named_locomotive_cost` map when their scalar payloads are nonnegative
|
unmapped-world bucket
|
||||||
- cargo-production `230..240` and territory-access-cost `453` rows now remain as the primary
|
- the adjacent locomotive-cost bands `352..451` and `475..500` now import too through the same
|
||||||
recovered scalar-band parity families: their labels, target masks, and slot identities are
|
overlay-backed catalog into the event-owned `RuntimeState.named_locomotive_cost` map when their
|
||||||
checked in, but execution for those families is still deferred until a grounded landing surface
|
scalar payloads are nonnegative
|
||||||
exists
|
- the remaining recovered scalar world families now execute as well: cargo-production `230..240`
|
||||||
|
rows lower into slot-indexed `cargo_production_overrides`, and territory-access-cost descriptor
|
||||||
|
`453` lowers into `world_restore.territory_access_cost`
|
||||||
|
|
||||||
That means the next implementation work is breadth, not bootstrap. The recommended next slice is
|
That means the next implementation work is breadth, not bootstrap. The recommended next slice is
|
||||||
honest landing surfaces for one or more of the remaining recovered scalar families, plus broader
|
broader real grouped-descriptor and ordinary condition-id coverage beyond the current access,
|
||||||
real grouped-descriptor and ordinary condition-id coverage beyond the current access, whole-game
|
whole-game toggle, train, player, numeric-threshold, named locomotive availability, named
|
||||||
toggle, train, player, numeric-threshold, named locomotive availability, and named locomotive cost
|
locomotive cost, and world scalar override batches.
|
||||||
batches.
|
|
||||||
Richer runtime ownership should still be added only where a later descriptor or condition family
|
Richer runtime ownership should still be added only where a later descriptor or condition family
|
||||||
needs more than the current event-owned roster.
|
needs more than the current event-owned roster.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"fixture_id": "packed-event-locomotive-availability-missing-catalog-save-slice-fixture",
|
"fixture_id": "packed-event-locomotive-availability-missing-catalog-save-slice-fixture",
|
||||||
"source": {
|
"source": {
|
||||||
"kind": "captured-runtime",
|
"kind": "captured-runtime",
|
||||||
"description": "Fixture backed by a tracked save-slice document that leaves a boolean locomotive availability row blocked until overlay-backed catalog context is supplied."
|
"description": "Fixture backed by a tracked save-slice document that leaves a scalar locomotive availability row blocked until overlay-backed catalog context is supplied."
|
||||||
},
|
},
|
||||||
"state_save_slice_path": "packed-event-locomotive-availability-missing-catalog-save-slice.json",
|
"state_save_slice_path": "packed-event-locomotive-availability-missing-catalog-save-slice.json",
|
||||||
"commands": [
|
"commands": [
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
{
|
{
|
||||||
"descriptor_id": 250,
|
"descriptor_id": 250,
|
||||||
"recovered_locomotive_id": 10,
|
"recovered_locomotive_id": 10,
|
||||||
"semantic_preview": "Set Unknown Loco Available to 1"
|
"semantic_preview": "Set Unknown Loco Available to 42"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
"format_version": 1,
|
"format_version": 1,
|
||||||
"save_slice_id": "packed-event-locomotive-availability-missing-catalog-save-slice",
|
"save_slice_id": "packed-event-locomotive-availability-missing-catalog-save-slice",
|
||||||
"source": {
|
"source": {
|
||||||
"description": "Tracked save-slice document proving boolean locomotive availability rows stay parity-only without overlay-backed locomotive catalog context.",
|
"description": "Tracked save-slice document proving scalar locomotive availability rows stay parity-only without overlay-backed locomotive catalog context.",
|
||||||
"original_save_filename": "captured-locomotive-availability-missing-catalog.gms",
|
"original_save_filename": "captured-locomotive-availability-missing-catalog.gms",
|
||||||
"original_save_sha256": "locomotive-availability-missing-catalog-sample-sha256",
|
"original_save_sha256": "locomotive-availability-missing-catalog-sample-sha256",
|
||||||
"notes": [
|
"notes": [
|
||||||
"tracked as JSON save-slice document rather than raw .smp",
|
"tracked as JSON save-slice document rather than raw .smp",
|
||||||
"locks the explicit missing locomotive catalog frontier for boolean availability rows"
|
"locks the explicit missing locomotive catalog frontier for scalar availability rows"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"save_slice": {
|
"save_slice": {
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
"target_mask_bits": 8,
|
"target_mask_bits": 8,
|
||||||
"parameter_family": "locomotive_availability_scalar",
|
"parameter_family": "locomotive_availability_scalar",
|
||||||
"opcode": 3,
|
"opcode": 3,
|
||||||
"raw_scalar_value": 1,
|
"raw_scalar_value": 42,
|
||||||
"value_byte_0x09": 0,
|
"value_byte_0x09": 0,
|
||||||
"value_dword_0x0d": 0,
|
"value_dword_0x0d": 0,
|
||||||
"value_byte_0x11": 0,
|
"value_byte_0x11": 0,
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
"value_word_0x16": 0,
|
"value_word_0x16": 0,
|
||||||
"row_shape": "scalar_assignment",
|
"row_shape": "scalar_assignment",
|
||||||
"semantic_family": "scalar_assignment",
|
"semantic_family": "scalar_assignment",
|
||||||
"semantic_preview": "Set Unknown Loco Available to 1",
|
"semantic_preview": "Set Unknown Loco Available to 42",
|
||||||
"recovered_locomotive_id": 10,
|
"recovered_locomotive_id": 10,
|
||||||
"locomotive_name": null,
|
"locomotive_name": null,
|
||||||
"notes": []
|
"notes": []
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
"decoded_actions": [],
|
"decoded_actions": [],
|
||||||
"executable_import_ready": false,
|
"executable_import_ready": false,
|
||||||
"notes": [
|
"notes": [
|
||||||
"boolean locomotive availability row still requires overlay-backed locomotive catalog context"
|
"scalar locomotive availability row still requires overlay-backed locomotive catalog context"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"fixture_id": "packed-event-locomotive-availability-overlay-fixture",
|
"fixture_id": "packed-event-locomotive-availability-overlay-fixture",
|
||||||
"source": {
|
"source": {
|
||||||
"kind": "captured-runtime",
|
"kind": "captured-runtime",
|
||||||
"description": "Fixture backed by an overlay import document so boolean locomotive availability descriptors execute against captured catalog context."
|
"description": "Fixture backed by an overlay import document so scalar locomotive availability descriptors execute against captured catalog context."
|
||||||
},
|
},
|
||||||
"state_import_path": "packed-event-locomotive-availability-overlay.json",
|
"state_import_path": "packed-event-locomotive-availability-overlay.json",
|
||||||
"commands": [
|
"commands": [
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
"packed_event_parity_only_record_count": 1,
|
"packed_event_parity_only_record_count": 1,
|
||||||
"event_runtime_record_count": 1,
|
"event_runtime_record_count": 1,
|
||||||
"named_locomotive_availability_count": 2,
|
"named_locomotive_availability_count": 2,
|
||||||
"zero_named_locomotive_availability_count": 1,
|
"zero_named_locomotive_availability_count": 0,
|
||||||
"total_event_record_service_count": 1,
|
"total_event_record_service_count": 1,
|
||||||
"total_trigger_dispatch_count": 1
|
"total_trigger_dispatch_count": 1
|
||||||
},
|
},
|
||||||
|
|
@ -38,8 +38,8 @@
|
||||||
"save_slice.import_projection": "overlay-runtime-restore-v1"
|
"save_slice.import_projection": "overlay-runtime-restore-v1"
|
||||||
},
|
},
|
||||||
"named_locomotive_availability": {
|
"named_locomotive_availability": {
|
||||||
"Locomotive 10": 1,
|
"Locomotive 10": 42,
|
||||||
"Locomotive 112": 0
|
"Locomotive 112": 7
|
||||||
},
|
},
|
||||||
"packed_event_collection": {
|
"packed_event_collection": {
|
||||||
"live_entry_ids": [33],
|
"live_entry_ids": [33],
|
||||||
|
|
@ -67,14 +67,14 @@
|
||||||
"service_count": 1,
|
"service_count": 1,
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"kind": "set_named_locomotive_availability",
|
"kind": "set_named_locomotive_availability_value",
|
||||||
"name": "Locomotive 10",
|
"name": "Locomotive 10",
|
||||||
"value": true
|
"value": 42
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "set_named_locomotive_availability",
|
"kind": "set_named_locomotive_availability_value",
|
||||||
"name": "Locomotive 112",
|
"name": "Locomotive 112",
|
||||||
"value": false
|
"value": 7
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
"format_version": 1,
|
"format_version": 1,
|
||||||
"save_slice_id": "packed-event-locomotive-availability-overlay-save-slice",
|
"save_slice_id": "packed-event-locomotive-availability-overlay-save-slice",
|
||||||
"source": {
|
"source": {
|
||||||
"description": "Tracked save-slice document proving boolean locomotive availability descriptors can import through overlay-backed catalog context.",
|
"description": "Tracked save-slice document proving scalar locomotive availability descriptors can import through overlay-backed catalog context.",
|
||||||
"original_save_filename": "captured-locomotive-availability-overlay.gms",
|
"original_save_filename": "captured-locomotive-availability-overlay.gms",
|
||||||
"original_save_sha256": "locomotive-availability-overlay-sample-sha256",
|
"original_save_sha256": "locomotive-availability-overlay-sample-sha256",
|
||||||
"notes": [
|
"notes": [
|
||||||
"tracked as JSON save-slice document rather than raw .smp",
|
"tracked as JSON save-slice document rather than raw .smp",
|
||||||
"uses synthetic catalog names to prove descriptor-to-id lowering plus overlay-backed resolution"
|
"uses synthetic catalog names to prove descriptor-to-id lowering plus overlay-backed scalar resolution"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"save_slice": {
|
"save_slice": {
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
"target_mask_bits": 8,
|
"target_mask_bits": 8,
|
||||||
"parameter_family": "locomotive_availability_scalar",
|
"parameter_family": "locomotive_availability_scalar",
|
||||||
"opcode": 3,
|
"opcode": 3,
|
||||||
"raw_scalar_value": 1,
|
"raw_scalar_value": 42,
|
||||||
"value_byte_0x09": 0,
|
"value_byte_0x09": 0,
|
||||||
"value_dword_0x0d": 0,
|
"value_dword_0x0d": 0,
|
||||||
"value_byte_0x11": 0,
|
"value_byte_0x11": 0,
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
"value_word_0x16": 0,
|
"value_word_0x16": 0,
|
||||||
"row_shape": "scalar_assignment",
|
"row_shape": "scalar_assignment",
|
||||||
"semantic_family": "scalar_assignment",
|
"semantic_family": "scalar_assignment",
|
||||||
"semantic_preview": "Set Unknown Loco Available to 1",
|
"semantic_preview": "Set Unknown Loco Available to 42",
|
||||||
"recovered_locomotive_id": 10,
|
"recovered_locomotive_id": 10,
|
||||||
"locomotive_name": null,
|
"locomotive_name": null,
|
||||||
"notes": []
|
"notes": []
|
||||||
|
|
@ -93,7 +93,7 @@
|
||||||
"target_mask_bits": 8,
|
"target_mask_bits": 8,
|
||||||
"parameter_family": "locomotive_availability_scalar",
|
"parameter_family": "locomotive_availability_scalar",
|
||||||
"opcode": 3,
|
"opcode": 3,
|
||||||
"raw_scalar_value": 0,
|
"raw_scalar_value": 7,
|
||||||
"value_byte_0x09": 0,
|
"value_byte_0x09": 0,
|
||||||
"value_dword_0x0d": 0,
|
"value_dword_0x0d": 0,
|
||||||
"value_byte_0x11": 0,
|
"value_byte_0x11": 0,
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
"value_word_0x16": 0,
|
"value_word_0x16": 0,
|
||||||
"row_shape": "scalar_assignment",
|
"row_shape": "scalar_assignment",
|
||||||
"semantic_family": "scalar_assignment",
|
"semantic_family": "scalar_assignment",
|
||||||
"semantic_preview": "Set Unknown Loco Available to 0",
|
"semantic_preview": "Set Unknown Loco Available to 7",
|
||||||
"recovered_locomotive_id": 112,
|
"recovered_locomotive_id": 112,
|
||||||
"locomotive_name": null,
|
"locomotive_name": null,
|
||||||
"notes": []
|
"notes": []
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
"decoded_actions": [],
|
"decoded_actions": [],
|
||||||
"executable_import_ready": false,
|
"executable_import_ready": false,
|
||||||
"notes": [
|
"notes": [
|
||||||
"boolean locomotive availability rows use overlay-backed catalog context"
|
"scalar locomotive availability rows use overlay-backed catalog context"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"format_version": 1,
|
"format_version": 1,
|
||||||
"import_id": "packed-event-locomotive-availability-overlay",
|
"import_id": "packed-event-locomotive-availability-overlay",
|
||||||
"source": {
|
"source": {
|
||||||
"description": "Overlay import that combines a captured base snapshot with boolean locomotive availability descriptors.",
|
"description": "Overlay import that combines a captured base snapshot with scalar locomotive availability descriptors.",
|
||||||
"notes": [
|
"notes": [
|
||||||
"used to upgrade descriptor-driven named locomotive availability rows through overlay-backed catalog context"
|
"used to upgrade descriptor-driven named locomotive availability rows through overlay-backed catalog context"
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,12 @@
|
||||||
"packed_event_imported_runtime_record_count": 1,
|
"packed_event_imported_runtime_record_count": 1,
|
||||||
"packed_event_parity_only_record_count": 2,
|
"packed_event_parity_only_record_count": 2,
|
||||||
"packed_event_unsupported_record_count": 0,
|
"packed_event_unsupported_record_count": 0,
|
||||||
|
"packed_event_blocked_missing_locomotive_catalog_context_count": 1,
|
||||||
"packed_event_blocked_missing_condition_context_count": 0,
|
"packed_event_blocked_missing_condition_context_count": 0,
|
||||||
"packed_event_blocked_territory_condition_scope_count": 0,
|
"packed_event_blocked_territory_condition_scope_count": 0,
|
||||||
"packed_event_blocked_missing_compact_control_count": 0,
|
"packed_event_blocked_missing_compact_control_count": 0,
|
||||||
"packed_event_blocked_unmapped_real_descriptor_count": 0,
|
"packed_event_blocked_unmapped_real_descriptor_count": 0,
|
||||||
"packed_event_blocked_unmapped_world_descriptor_count": 1,
|
"packed_event_blocked_unmapped_world_descriptor_count": 0,
|
||||||
"packed_event_blocked_structural_only_count": 0,
|
"packed_event_blocked_structural_only_count": 0,
|
||||||
"event_runtime_record_count": 1,
|
"event_runtime_record_count": 1,
|
||||||
"total_company_cash": 0
|
"total_company_cash": 0
|
||||||
|
|
@ -48,7 +49,7 @@
|
||||||
{
|
{
|
||||||
"decode_status": "parity_only",
|
"decode_status": "parity_only",
|
||||||
"payload_family": "real_packed_v1",
|
"payload_family": "real_packed_v1",
|
||||||
"import_outcome": "blocked_unmapped_world_descriptor",
|
"import_outcome": "blocked_missing_locomotive_catalog_context",
|
||||||
"grouped_effect_rows": [
|
"grouped_effect_rows": [
|
||||||
{
|
{
|
||||||
"descriptor_id": 250,
|
"descriptor_id": 250,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
"original_save_sha256": "parity-sample-sha256",
|
"original_save_sha256": "parity-sample-sha256",
|
||||||
"notes": [
|
"notes": [
|
||||||
"tracked as JSON save-slice document rather than raw .smp",
|
"tracked as JSON save-slice document rather than raw .smp",
|
||||||
"preserves one recovered-but-unmapped locomotive availability row and one semantically decoded-but-parity-only row"
|
"preserves one recovered scalar locomotive-availability row that still needs overlay-backed catalog context and one semantically decoded imported row"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"save_slice": {
|
"save_slice": {
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
"recovered_locomotive_id": 10,
|
"recovered_locomotive_id": 10,
|
||||||
"locomotive_name": null,
|
"locomotive_name": null,
|
||||||
"notes": [
|
"notes": [
|
||||||
"recovered locomotive availability descriptor family remains parity-only until the scalar payload is in the grounded boolean subset"
|
"recovered locomotive availability descriptor family now supports scalar payloads, but standalone save-slice import still needs overlay-backed locomotive catalog context"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
"executable_import_ready": false,
|
"executable_import_ready": false,
|
||||||
"notes": [
|
"notes": [
|
||||||
"decoded from grounded real 0x4e9a row framing",
|
"decoded from grounded real 0x4e9a row framing",
|
||||||
"recovered locomotives-page descriptor band is now checked in, but this scalar family still needs overlay-backed locomotive catalog context and a grounded boolean scalar payload"
|
"recovered locomotives-page descriptor band is now checked in, and this scalar family can import through named locomotive availability overrides once overlay-backed locomotive catalog context is present"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"fixture_id": "packed-event-world-scalar-band-parity-save-slice-fixture",
|
"fixture_id": "packed-event-world-scalar-band-parity-save-slice-fixture",
|
||||||
"source": {
|
"source": {
|
||||||
"kind": "captured-runtime",
|
"kind": "captured-runtime",
|
||||||
"description": "Fixture backed by a tracked save-slice document that pins recovered scalar-band world descriptors as parity-only."
|
"description": "Fixture backed by a tracked save-slice document that mixes executable scalar world descriptors with one remaining missing-catalog frontier."
|
||||||
},
|
},
|
||||||
"state_save_slice_path": "packed-event-world-scalar-band-parity-save-slice.json",
|
"state_save_slice_path": "packed-event-world-scalar-band-parity-save-slice.json",
|
||||||
"commands": [
|
"commands": [
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
"packed_event_collection_present": true,
|
"packed_event_collection_present": true,
|
||||||
"packed_event_record_count": 3,
|
"packed_event_record_count": 3,
|
||||||
"packed_event_decoded_record_count": 3,
|
"packed_event_decoded_record_count": 3,
|
||||||
"packed_event_imported_runtime_record_count": 0,
|
"packed_event_imported_runtime_record_count": 2,
|
||||||
"packed_event_parity_only_record_count": 3,
|
"packed_event_parity_only_record_count": 3,
|
||||||
"packed_event_unsupported_record_count": 0,
|
"packed_event_unsupported_record_count": 0,
|
||||||
"packed_event_blocked_missing_locomotive_catalog_context_count": 1,
|
"packed_event_blocked_missing_locomotive_catalog_context_count": 1,
|
||||||
|
|
@ -31,9 +31,10 @@
|
||||||
"packed_event_blocked_territory_condition_scope_count": 0,
|
"packed_event_blocked_territory_condition_scope_count": 0,
|
||||||
"packed_event_blocked_missing_compact_control_count": 0,
|
"packed_event_blocked_missing_compact_control_count": 0,
|
||||||
"packed_event_blocked_unmapped_real_descriptor_count": 0,
|
"packed_event_blocked_unmapped_real_descriptor_count": 0,
|
||||||
"packed_event_blocked_unmapped_world_descriptor_count": 2,
|
"packed_event_blocked_unmapped_world_descriptor_count": 0,
|
||||||
"packed_event_blocked_structural_only_count": 0,
|
"packed_event_blocked_structural_only_count": 0,
|
||||||
"event_runtime_record_count": 0,
|
"event_runtime_record_count": 2,
|
||||||
|
"cargo_production_override_count": 0,
|
||||||
"total_company_cash": 0
|
"total_company_cash": 0
|
||||||
},
|
},
|
||||||
"expected_state_fragment": {
|
"expected_state_fragment": {
|
||||||
|
|
@ -46,7 +47,7 @@
|
||||||
{
|
{
|
||||||
"decode_status": "parity_only",
|
"decode_status": "parity_only",
|
||||||
"payload_family": "real_packed_v1",
|
"payload_family": "real_packed_v1",
|
||||||
"import_outcome": "blocked_unmapped_world_descriptor",
|
"import_outcome": "imported",
|
||||||
"grouped_effect_rows": [
|
"grouped_effect_rows": [
|
||||||
{
|
{
|
||||||
"descriptor_id": 230,
|
"descriptor_id": 230,
|
||||||
|
|
@ -79,7 +80,7 @@
|
||||||
{
|
{
|
||||||
"decode_status": "parity_only",
|
"decode_status": "parity_only",
|
||||||
"payload_family": "real_packed_v1",
|
"payload_family": "real_packed_v1",
|
||||||
"import_outcome": "blocked_unmapped_world_descriptor",
|
"import_outcome": "imported",
|
||||||
"grouped_effect_rows": [
|
"grouped_effect_rows": [
|
||||||
{
|
{
|
||||||
"descriptor_id": 453,
|
"descriptor_id": 453,
|
||||||
|
|
@ -93,6 +94,27 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"event_runtime_records": [
|
||||||
|
{
|
||||||
|
"record_id": 11,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"kind": "set_cargo_production_slot",
|
||||||
|
"slot": 1,
|
||||||
|
"value": 125
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 13,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"kind": "set_territory_access_cost",
|
||||||
|
"value": 750000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
"format_version": 1,
|
"format_version": 1,
|
||||||
"save_slice_id": "packed-event-world-scalar-band-parity-save-slice",
|
"save_slice_id": "packed-event-world-scalar-band-parity-save-slice",
|
||||||
"source": {
|
"source": {
|
||||||
"description": "Tracked save-slice document pinning recovered locomotives-page scalar families that are still parity-only.",
|
"description": "Tracked save-slice document pinning recovered locomotives-page scalar families across executable and missing-context boundaries.",
|
||||||
"original_save_filename": "captured-world-scalar-band-parity.gms",
|
"original_save_filename": "captured-world-scalar-band-parity.gms",
|
||||||
"original_save_sha256": "world-scalar-band-parity-sample-sha256",
|
"original_save_sha256": "world-scalar-band-parity-sample-sha256",
|
||||||
"notes": [
|
"notes": [
|
||||||
"tracked as JSON save-slice document rather than raw .smp",
|
"tracked as JSON save-slice document rather than raw .smp",
|
||||||
"covers recovered cargo production, locomotive cost, and territory access cost families without claiming executable runtime semantics"
|
"covers recovered cargo production, locomotive cost, and territory access cost families with one remaining missing-catalog frontier"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"save_slice": {
|
"save_slice": {
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
"decoded_actions": [],
|
"decoded_actions": [],
|
||||||
"executable_import_ready": false,
|
"executable_import_ready": false,
|
||||||
"notes": [
|
"notes": [
|
||||||
"recovered cargo production metadata is now checked in, but no runtime landing surface exists yet"
|
"recovered cargo production metadata now imports through world overrides"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -201,7 +201,7 @@
|
||||||
"decoded_actions": [],
|
"decoded_actions": [],
|
||||||
"executable_import_ready": false,
|
"executable_import_ready": false,
|
||||||
"notes": [
|
"notes": [
|
||||||
"recovered territory access cost metadata is now checked in, but execution is still deferred"
|
"recovered territory access cost metadata now imports through world restore"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
{
|
||||||
|
"format_version": 1,
|
||||||
|
"fixture_id": "packed-event-world-scalar-executable-save-slice-fixture",
|
||||||
|
"source": {
|
||||||
|
"kind": "captured-runtime",
|
||||||
|
"description": "Fixture backed by a tracked save-slice document proving recovered cargo-production and territory-access-cost rows execute through world scalar runtime surfaces."
|
||||||
|
},
|
||||||
|
"state_save_slice_path": "packed-event-world-scalar-executable-save-slice.json",
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"kind": "service_trigger_kind",
|
||||||
|
"trigger_kind": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"expected_summary": {
|
||||||
|
"calendar": {
|
||||||
|
"year": 1830,
|
||||||
|
"month_slot": 0,
|
||||||
|
"phase_slot": 0,
|
||||||
|
"tick_slot": 0
|
||||||
|
},
|
||||||
|
"calendar_projection_is_placeholder": true,
|
||||||
|
"packed_event_collection_present": true,
|
||||||
|
"packed_event_record_count": 1,
|
||||||
|
"packed_event_decoded_record_count": 1,
|
||||||
|
"packed_event_imported_runtime_record_count": 1,
|
||||||
|
"packed_event_parity_only_record_count": 1,
|
||||||
|
"packed_event_blocked_unmapped_world_descriptor_count": 0,
|
||||||
|
"event_runtime_record_count": 1,
|
||||||
|
"cargo_production_override_count": 1,
|
||||||
|
"world_restore_territory_access_cost": 750000,
|
||||||
|
"total_event_record_service_count": 1,
|
||||||
|
"total_trigger_dispatch_count": 1
|
||||||
|
},
|
||||||
|
"expected_state_fragment": {
|
||||||
|
"metadata": {
|
||||||
|
"save_slice.import_projection": "partial-runtime-restore-v1"
|
||||||
|
},
|
||||||
|
"cargo_production_overrides": {
|
||||||
|
"1": 125
|
||||||
|
},
|
||||||
|
"world_restore": {
|
||||||
|
"territory_access_cost": 750000
|
||||||
|
},
|
||||||
|
"packed_event_collection": {
|
||||||
|
"live_entry_ids": [41],
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"import_outcome": "imported"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"event_runtime_records": [
|
||||||
|
{
|
||||||
|
"record_id": 41,
|
||||||
|
"service_count": 1,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"kind": "set_cargo_production_slot",
|
||||||
|
"slot": 1,
|
||||||
|
"value": 125
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "set_territory_access_cost",
|
||||||
|
"value": 750000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
{
|
||||||
|
"format_version": 1,
|
||||||
|
"save_slice_id": "packed-event-world-scalar-executable-save-slice",
|
||||||
|
"source": {
|
||||||
|
"description": "Tracked save-slice document proving recovered cargo-production and territory-access-cost rows import through world scalar runtime surfaces.",
|
||||||
|
"original_save_filename": "captured-world-scalar-executable.gms",
|
||||||
|
"original_save_sha256": "world-scalar-executable-sample-sha256",
|
||||||
|
"notes": [
|
||||||
|
"tracked as JSON save-slice document rather than raw .smp",
|
||||||
|
"uses a save-slice-backed proof path because cargo-production and territory-access-cost do not require overlay-backed runtime context"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"save_slice": {
|
||||||
|
"file_extension_hint": "gms",
|
||||||
|
"container_profile_family": "rt3-classic-save-container-v1",
|
||||||
|
"mechanism_family": "classic-save-rehydrate-v1",
|
||||||
|
"mechanism_confidence": "grounded",
|
||||||
|
"trailer_family": null,
|
||||||
|
"bridge_family": null,
|
||||||
|
"profile": null,
|
||||||
|
"candidate_availability_table": null,
|
||||||
|
"named_locomotive_availability_table": null,
|
||||||
|
"special_conditions_table": null,
|
||||||
|
"event_runtime_collection": {
|
||||||
|
"source_kind": "packed-event-runtime-collection",
|
||||||
|
"mechanism_family": "classic-save-rehydrate-v1",
|
||||||
|
"mechanism_confidence": "grounded",
|
||||||
|
"container_profile_family": "rt3-classic-save-container-v1",
|
||||||
|
"metadata_tag_offset": 30976,
|
||||||
|
"records_tag_offset": 31232,
|
||||||
|
"close_tag_offset": 31744,
|
||||||
|
"packed_state_version": 1001,
|
||||||
|
"packed_state_version_hex": "0x000003e9",
|
||||||
|
"live_id_bound": 41,
|
||||||
|
"live_record_count": 1,
|
||||||
|
"live_entry_ids": [41],
|
||||||
|
"decoded_record_count": 1,
|
||||||
|
"imported_runtime_record_count": 0,
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"record_index": 0,
|
||||||
|
"live_entry_id": 41,
|
||||||
|
"payload_offset": 31264,
|
||||||
|
"payload_len": 112,
|
||||||
|
"decode_status": "parity_only",
|
||||||
|
"payload_family": "real_packed_v1",
|
||||||
|
"trigger_kind": 7,
|
||||||
|
"one_shot": false,
|
||||||
|
"compact_control": {
|
||||||
|
"mode_byte_0x7ef": 7,
|
||||||
|
"primary_selector_0x7f0": 0,
|
||||||
|
"grouped_mode_0x7f4": 2,
|
||||||
|
"one_shot_header_0x7f5": 0,
|
||||||
|
"modifier_flag_0x7f9": 0,
|
||||||
|
"modifier_flag_0x7fa": 0,
|
||||||
|
"grouped_target_scope_ordinals_0x7fb": [0, 0, 0, 0],
|
||||||
|
"grouped_scope_checkboxes_0x7ff": [1, 0, 0, 0],
|
||||||
|
"summary_toggle_0x800": 1,
|
||||||
|
"grouped_territory_selectors_0x80f": [-1, -1, -1, -1]
|
||||||
|
},
|
||||||
|
"text_bands": [],
|
||||||
|
"standalone_condition_row_count": 0,
|
||||||
|
"standalone_condition_rows": [],
|
||||||
|
"grouped_effect_row_counts": [2, 0, 0, 0],
|
||||||
|
"grouped_effect_rows": [
|
||||||
|
{
|
||||||
|
"group_index": 0,
|
||||||
|
"row_index": 0,
|
||||||
|
"descriptor_id": 230,
|
||||||
|
"descriptor_label": "Cargo Production Slot 1",
|
||||||
|
"target_mask_bits": 8,
|
||||||
|
"parameter_family": "cargo_production_scalar",
|
||||||
|
"opcode": 3,
|
||||||
|
"raw_scalar_value": 125,
|
||||||
|
"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",
|
||||||
|
"semantic_family": "scalar_assignment",
|
||||||
|
"semantic_preview": "Set Cargo Production Slot 1 to 125",
|
||||||
|
"recovered_locomotive_id": null,
|
||||||
|
"locomotive_name": null,
|
||||||
|
"notes": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_index": 0,
|
||||||
|
"row_index": 1,
|
||||||
|
"descriptor_id": 453,
|
||||||
|
"descriptor_label": "Territory Access Cost",
|
||||||
|
"target_mask_bits": 8,
|
||||||
|
"parameter_family": "territory_access_cost_scalar",
|
||||||
|
"opcode": 3,
|
||||||
|
"raw_scalar_value": 750000,
|
||||||
|
"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",
|
||||||
|
"semantic_family": "scalar_assignment",
|
||||||
|
"semantic_preview": "Set Territory Access Cost to 750000",
|
||||||
|
"recovered_locomotive_id": null,
|
||||||
|
"locomotive_name": null,
|
||||||
|
"notes": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"decoded_actions": [],
|
||||||
|
"executable_import_ready": false,
|
||||||
|
"notes": [
|
||||||
|
"world scalar override record imports without overlay-backed runtime context"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
"world scalar executable sample"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue