Probe raw save selection context
This commit is contained in:
parent
bd9e1421a1
commit
40c0e94ad5
9 changed files with 581 additions and 137 deletions
|
|
@ -29,7 +29,10 @@ chairman ordinals remain explicit frontier. Checked-in save-slice
|
|||
documents can now also carry explicit company rosters and chairman-profile tables, so the current
|
||||
company-targeted and chairman-targeted descriptor and condition batches can execute from standalone
|
||||
save-slice fixtures without overlay snapshots when that context is present; raw `.gms` inspection
|
||||
still does not reconstruct those company/chairman collections automatically. A checked-in
|
||||
still does not reconstruct those company/chairman collections automatically, but it now does
|
||||
reconstruct selection-only company/chairman context from the fixed save-side `0x32c8` world block.
|
||||
Those raw selected ids can flow through save-slice export/import and override overlay-backed base
|
||||
selection even while the full raw rosters remain absent. A checked-in
|
||||
`EventEffects` export now exists too in
|
||||
`artifacts/exports/rt3-1.06/event-effects-table.json`, and a checked-in semantic closure layer now
|
||||
exists beside it in `artifacts/exports/rt3-1.06/event-effects-semantic-catalog.json`. Recovered
|
||||
|
|
@ -55,7 +58,9 @@ runtime landing surfaces too: descriptor `105` `All Cargo Prices` plus descripto
|
|||
event-owned cargo override state, and the grounded named cargo-production strip `180..229` now
|
||||
imports into named cargo production overrides too. The named cargo-price strip `106..176`
|
||||
remains explicit `blocked_evidence_blocked_descriptor` parity until descriptor ordering is pinned
|
||||
more strongly. The add-building strip `503..519` is now explicitly classified as recovered
|
||||
more strongly, but the semantic catalog now gives that band stable `Named Cargo Price Slot N`
|
||||
labels instead of anonymous `Unknown Cargo Price` residue. The add-building strip `503..519` is
|
||||
now explicitly classified as recovered
|
||||
shell-owned descriptor parity rather than generic unresolved residue. The first grounded
|
||||
condition-side unlock now exists for negative-sentinel `raw_condition_id = -1` company scopes, and
|
||||
the first ordinary nonnegative condition batch now executes too: numeric-threshold company
|
||||
|
|
|
|||
|
|
@ -959,7 +959,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 106,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 1",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -968,7 +968,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 107,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 2",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -977,7 +977,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 108,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 3",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -986,7 +986,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 109,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 4",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -995,7 +995,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 110,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 5",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1004,7 +1004,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 111,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 6",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1013,7 +1013,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 112,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 7",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1022,7 +1022,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 113,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 8",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1031,7 +1031,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 114,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 9",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1040,7 +1040,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 115,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 10",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1049,7 +1049,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 116,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 11",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1058,7 +1058,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 117,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 12",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1067,7 +1067,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 118,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 13",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1076,7 +1076,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 119,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 14",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1085,7 +1085,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 120,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 15",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1094,7 +1094,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 121,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 16",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1103,7 +1103,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 122,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 17",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1112,7 +1112,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 123,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 18",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1121,7 +1121,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 124,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 19",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1130,7 +1130,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 125,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 20",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1139,7 +1139,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 126,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 21",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1148,7 +1148,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 127,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 22",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1157,7 +1157,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 128,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 23",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1166,7 +1166,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 129,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 24",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1175,7 +1175,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 130,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 25",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1184,7 +1184,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 131,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 26",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1193,7 +1193,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 132,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 27",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1202,7 +1202,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 133,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 28",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1211,7 +1211,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 134,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 29",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1220,7 +1220,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 135,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 30",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1229,7 +1229,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 136,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 31",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1238,7 +1238,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 137,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 32",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1247,7 +1247,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 138,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 33",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1256,7 +1256,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 139,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 34",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1265,7 +1265,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 140,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 35",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1274,7 +1274,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 141,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 36",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1283,7 +1283,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 142,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 37",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1292,7 +1292,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 143,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 38",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1301,7 +1301,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 144,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 39",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1310,7 +1310,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 145,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 40",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1319,7 +1319,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 146,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 41",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1328,7 +1328,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 147,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 42",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1337,7 +1337,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 148,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 43",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1346,7 +1346,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 149,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 44",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1355,7 +1355,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 150,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 45",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1364,7 +1364,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 151,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 46",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1373,7 +1373,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 152,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 47",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1382,7 +1382,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 153,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 48",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1391,7 +1391,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 154,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 49",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1400,7 +1400,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 155,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 50",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1409,7 +1409,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 156,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 51",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1418,7 +1418,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 157,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 52",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1427,7 +1427,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 158,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 53",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1436,7 +1436,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 159,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 54",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1445,7 +1445,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 160,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 55",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1454,7 +1454,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 161,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 56",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1463,7 +1463,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 162,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 57",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1472,7 +1472,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 163,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 58",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1481,7 +1481,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 164,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 59",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1490,7 +1490,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 165,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 60",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1499,7 +1499,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 166,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 61",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1508,7 +1508,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 167,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 62",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1517,7 +1517,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 168,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 63",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1526,7 +1526,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 169,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 64",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1535,7 +1535,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 170,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 65",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1544,7 +1544,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 171,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 66",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1553,7 +1553,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 172,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 67",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1562,7 +1562,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 173,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 68",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1571,7 +1571,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 174,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 69",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1580,7 +1580,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 175,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 70",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
@ -1589,7 +1589,7 @@
|
|||
},
|
||||
{
|
||||
"descriptor_id": 176,
|
||||
"label": "Unknown Cargo Price",
|
||||
"label": "Named Cargo Price Slot 71",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
|
|
|
|||
|
|
@ -97,9 +97,11 @@ struct SaveSliceProjection {
|
|||
event_runtime_records: Vec<RuntimeEventRecord>,
|
||||
companies: Vec<RuntimeCompany>,
|
||||
has_company_projection: bool,
|
||||
has_company_selection_override: bool,
|
||||
selected_company_id: Option<u32>,
|
||||
chairman_profiles: Vec<RuntimeChairmanProfile>,
|
||||
has_chairman_projection: bool,
|
||||
has_chairman_selection_override: bool,
|
||||
selected_chairman_profile_id: Option<u32>,
|
||||
candidate_availability: BTreeMap<String, u32>,
|
||||
named_locomotive_availability: BTreeMap<String, u32>,
|
||||
|
|
@ -269,11 +271,19 @@ pub fn project_save_slice_to_runtime_state_import(
|
|||
world_restore: projection.world_restore,
|
||||
metadata: projection.metadata,
|
||||
companies: projection.companies,
|
||||
selected_company_id: projection.selected_company_id,
|
||||
selected_company_id: if projection.has_company_projection {
|
||||
projection.selected_company_id
|
||||
} else {
|
||||
None
|
||||
},
|
||||
players: Vec::new(),
|
||||
selected_player_id: None,
|
||||
chairman_profiles: projection.chairman_profiles,
|
||||
selected_chairman_profile_id: projection.selected_chairman_profile_id,
|
||||
selected_chairman_profile_id: if projection.has_chairman_projection {
|
||||
projection.selected_chairman_profile_id
|
||||
} else {
|
||||
None
|
||||
},
|
||||
trains: Vec::new(),
|
||||
locomotive_catalog: projection.locomotive_catalog.unwrap_or_default(),
|
||||
cargo_catalog: projection.cargo_catalog.unwrap_or_default(),
|
||||
|
|
@ -349,7 +359,9 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
|||
} else {
|
||||
base_state.companies.clone()
|
||||
},
|
||||
selected_company_id: if projection.has_company_projection {
|
||||
selected_company_id: if projection.has_company_projection
|
||||
|| projection.has_company_selection_override
|
||||
{
|
||||
projection.selected_company_id
|
||||
} else {
|
||||
base_state.selected_company_id
|
||||
|
|
@ -361,7 +373,9 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
|||
} else {
|
||||
base_state.chairman_profiles.clone()
|
||||
},
|
||||
selected_chairman_profile_id: if projection.has_chairman_projection {
|
||||
selected_chairman_profile_id: if projection.has_chairman_projection
|
||||
|| projection.has_chairman_selection_override
|
||||
{
|
||||
projection.selected_chairman_profile_id
|
||||
} else {
|
||||
base_state.selected_chairman_profile_id
|
||||
|
|
@ -809,7 +823,7 @@ fn project_save_slice_components(
|
|||
None
|
||||
};
|
||||
|
||||
let (companies, has_company_projection, selected_company_id) =
|
||||
let (companies, has_company_projection, has_company_selection_override, selected_company_id) =
|
||||
if let Some(roster) = &save_slice.company_roster {
|
||||
metadata.insert(
|
||||
"save_slice.company_roster_source_kind".to_string(),
|
||||
|
|
@ -829,55 +843,77 @@ fn project_save_slice_components(
|
|||
selected_company_id.to_string(),
|
||||
);
|
||||
}
|
||||
(
|
||||
roster
|
||||
.entries
|
||||
.iter()
|
||||
.map(|entry| RuntimeCompany {
|
||||
company_id: entry.company_id,
|
||||
current_cash: entry.current_cash,
|
||||
debt: entry.debt,
|
||||
credit_rating_score: entry.credit_rating_score,
|
||||
prime_rate: entry.prime_rate,
|
||||
active: entry.active,
|
||||
available_track_laying_capacity: entry.available_track_laying_capacity,
|
||||
controller_kind: entry.controller_kind,
|
||||
linked_chairman_profile_id: entry.linked_chairman_profile_id,
|
||||
book_value_per_share: entry.book_value_per_share,
|
||||
investor_confidence: entry.investor_confidence,
|
||||
management_attitude: entry.management_attitude,
|
||||
takeover_cooldown_year: entry.takeover_cooldown_year,
|
||||
merger_cooldown_year: entry.merger_cooldown_year,
|
||||
track_piece_counts: entry.track_piece_counts,
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
true,
|
||||
roster.selected_company_id,
|
||||
)
|
||||
if roster.entries.is_empty() {
|
||||
(
|
||||
Vec::new(),
|
||||
false,
|
||||
roster.selected_company_id.is_some(),
|
||||
roster.selected_company_id,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
roster
|
||||
.entries
|
||||
.iter()
|
||||
.map(|entry| RuntimeCompany {
|
||||
company_id: entry.company_id,
|
||||
current_cash: entry.current_cash,
|
||||
debt: entry.debt,
|
||||
credit_rating_score: entry.credit_rating_score,
|
||||
prime_rate: entry.prime_rate,
|
||||
active: entry.active,
|
||||
available_track_laying_capacity: entry.available_track_laying_capacity,
|
||||
controller_kind: entry.controller_kind,
|
||||
linked_chairman_profile_id: entry.linked_chairman_profile_id,
|
||||
book_value_per_share: entry.book_value_per_share,
|
||||
investor_confidence: entry.investor_confidence,
|
||||
management_attitude: entry.management_attitude,
|
||||
takeover_cooldown_year: entry.takeover_cooldown_year,
|
||||
merger_cooldown_year: entry.merger_cooldown_year,
|
||||
track_piece_counts: entry.track_piece_counts,
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
true,
|
||||
roster.selected_company_id.is_some(),
|
||||
roster.selected_company_id,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
(Vec::new(), false, None)
|
||||
(Vec::new(), false, false, None)
|
||||
};
|
||||
|
||||
let (chairman_profiles, has_chairman_projection, selected_chairman_profile_id) =
|
||||
if let Some(table) = &save_slice.chairman_profile_table {
|
||||
let (
|
||||
chairman_profiles,
|
||||
has_chairman_projection,
|
||||
has_chairman_selection_override,
|
||||
selected_chairman_profile_id,
|
||||
) = if let Some(table) = &save_slice.chairman_profile_table {
|
||||
metadata.insert(
|
||||
"save_slice.chairman_profile_table_source_kind".to_string(),
|
||||
table.source_kind.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.chairman_profile_table_semantic_family".to_string(),
|
||||
table.semantic_family.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.chairman_profile_table_entry_count".to_string(),
|
||||
table.observed_entry_count.to_string(),
|
||||
);
|
||||
if let Some(selected_chairman_profile_id) = table.selected_chairman_profile_id {
|
||||
metadata.insert(
|
||||
"save_slice.chairman_profile_table_source_kind".to_string(),
|
||||
table.source_kind.clone(),
|
||||
"save_slice.selected_chairman_profile_id".to_string(),
|
||||
selected_chairman_profile_id.to_string(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.chairman_profile_table_semantic_family".to_string(),
|
||||
table.semantic_family.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.chairman_profile_table_entry_count".to_string(),
|
||||
table.observed_entry_count.to_string(),
|
||||
);
|
||||
if let Some(selected_chairman_profile_id) = table.selected_chairman_profile_id {
|
||||
metadata.insert(
|
||||
"save_slice.selected_chairman_profile_id".to_string(),
|
||||
selected_chairman_profile_id.to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
if table.entries.is_empty() {
|
||||
(
|
||||
Vec::new(),
|
||||
false,
|
||||
table.selected_chairman_profile_id.is_some(),
|
||||
table.selected_chairman_profile_id,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
table
|
||||
.entries
|
||||
|
|
@ -895,11 +931,13 @@ fn project_save_slice_components(
|
|||
})
|
||||
.collect::<Vec<_>>(),
|
||||
true,
|
||||
table.selected_chairman_profile_id.is_some(),
|
||||
table.selected_chairman_profile_id,
|
||||
)
|
||||
} else {
|
||||
(Vec::new(), false, None)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
(Vec::new(), false, false, None)
|
||||
};
|
||||
|
||||
let named_locomotive_cost = BTreeMap::new();
|
||||
let all_cargo_price_override = None;
|
||||
|
|
@ -920,6 +958,8 @@ fn project_save_slice_components(
|
|||
&& companies
|
||||
.iter()
|
||||
.all(|company| company.controller_kind != RuntimeCompanyControllerKind::Unknown);
|
||||
} else if has_company_selection_override {
|
||||
packed_event_context.selected_company_id = selected_company_id;
|
||||
}
|
||||
if has_chairman_projection {
|
||||
packed_event_context.known_chairman_profile_ids = chairman_profiles
|
||||
|
|
@ -927,6 +967,8 @@ fn project_save_slice_components(
|
|||
.map(|profile| profile.profile_id)
|
||||
.collect();
|
||||
packed_event_context.selected_chairman_profile_id = selected_chairman_profile_id;
|
||||
} else if has_chairman_selection_override {
|
||||
packed_event_context.selected_chairman_profile_id = selected_chairman_profile_id;
|
||||
}
|
||||
if let Some(catalog) = &locomotive_catalog {
|
||||
packed_event_context.locomotive_catalog_names_by_id = catalog
|
||||
|
|
@ -976,9 +1018,11 @@ fn project_save_slice_components(
|
|||
event_runtime_records,
|
||||
companies,
|
||||
has_company_projection,
|
||||
has_company_selection_override,
|
||||
selected_company_id,
|
||||
chairman_profiles,
|
||||
has_chairman_projection,
|
||||
has_chairman_selection_override,
|
||||
selected_chairman_profile_id,
|
||||
candidate_availability,
|
||||
named_locomotive_availability,
|
||||
|
|
@ -4918,11 +4962,12 @@ mod tests {
|
|||
descriptor_id: u32,
|
||||
value: i32,
|
||||
) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
let slot = descriptor_id.saturating_sub(105);
|
||||
crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
group_index: 0,
|
||||
row_index: 0,
|
||||
descriptor_id,
|
||||
descriptor_label: Some("Unknown Cargo Price".to_string()),
|
||||
descriptor_label: Some(format!("Named Cargo Price Slot {slot}")),
|
||||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("cargo_price_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
|
|
@ -4937,7 +4982,7 @@ mod tests {
|
|||
value_word_0x16: 0,
|
||||
row_shape: "scalar_assignment".to_string(),
|
||||
semantic_family: Some("scalar_assignment".to_string()),
|
||||
semantic_preview: Some(format!("Set Unknown Cargo Price to {value}")),
|
||||
semantic_preview: Some(format!("Set Named Cargo Price Slot {slot} to {value}")),
|
||||
recovered_cargo_slot: None,
|
||||
recovered_cargo_class: None,
|
||||
recovered_cargo_label: None,
|
||||
|
|
@ -5874,6 +5919,118 @@ mod tests {
|
|||
assert_eq!(import.state.territories, base_state.territories);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overlay_applies_selection_only_company_and_chairman_context_from_save_slice() {
|
||||
let base_state = RuntimeState {
|
||||
companies: vec![
|
||||
crate::RuntimeCompany {
|
||||
company_id: 1,
|
||||
current_cash: 100,
|
||||
debt: 0,
|
||||
credit_rating_score: None,
|
||||
prime_rate: None,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
linked_chairman_profile_id: Some(1),
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
track_piece_counts: RuntimeTrackPieceCounts::default(),
|
||||
},
|
||||
crate::RuntimeCompany {
|
||||
company_id: 42,
|
||||
current_cash: 200,
|
||||
debt: 0,
|
||||
credit_rating_score: None,
|
||||
prime_rate: None,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
linked_chairman_profile_id: Some(9),
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
track_piece_counts: RuntimeTrackPieceCounts::default(),
|
||||
},
|
||||
],
|
||||
selected_company_id: Some(42),
|
||||
chairman_profiles: vec![
|
||||
crate::RuntimeChairmanProfile {
|
||||
profile_id: 1,
|
||||
name: "Selected".to_string(),
|
||||
active: true,
|
||||
current_cash: 0,
|
||||
linked_company_id: Some(1),
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
},
|
||||
crate::RuntimeChairmanProfile {
|
||||
profile_id: 9,
|
||||
name: "Base".to_string(),
|
||||
active: true,
|
||||
current_cash: 0,
|
||||
linked_company_id: Some(42),
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
},
|
||||
],
|
||||
selected_chairman_profile_id: Some(9),
|
||||
..state()
|
||||
};
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-105-save-container-v1".to_string()),
|
||||
mechanism_family: "rt3-105-save-post-span-bridge-v1".to_string(),
|
||||
mechanism_confidence: "mixed".to_string(),
|
||||
trailer_family: Some("rt3-105-save-trailer-v1".to_string()),
|
||||
bridge_family: Some("rt3-105-save-post-span-bridge-v1".to_string()),
|
||||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
cargo_catalog: None,
|
||||
company_roster: Some(crate::SmpLoadedCompanyRoster {
|
||||
source_kind: "save-direct-world-block-company-selection-only".to_string(),
|
||||
semantic_family: "scenario-selected-company-context".to_string(),
|
||||
observed_entry_count: 0,
|
||||
selected_company_id: Some(1),
|
||||
entries: Vec::new(),
|
||||
}),
|
||||
chairman_profile_table: Some(crate::SmpLoadedChairmanProfileTable {
|
||||
source_kind: "save-direct-world-block-chairman-selection-only".to_string(),
|
||||
semantic_family: "scenario-selected-chairman-context".to_string(),
|
||||
observed_entry_count: 0,
|
||||
selected_chairman_profile_id: Some(1),
|
||||
entries: Vec::new(),
|
||||
}),
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: None,
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let import = project_save_slice_overlay_to_runtime_state_import(
|
||||
&base_state,
|
||||
&save_slice,
|
||||
"overlay-save-selection-only-context",
|
||||
None,
|
||||
)
|
||||
.expect("overlay import should project");
|
||||
|
||||
assert_eq!(import.state.companies, base_state.companies);
|
||||
assert_eq!(import.state.selected_company_id, Some(1));
|
||||
assert_eq!(import.state.chairman_profiles, base_state.chairman_profiles);
|
||||
assert_eq!(import.state.selected_chairman_profile_id, Some(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn projects_executable_packed_records_into_runtime_and_services_follow_on() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
|
|
|
|||
|
|
@ -90,6 +90,11 @@ const RECIPE_BOOK_LINE_STRIDE: usize = 0x30;
|
|||
const RECIPE_BOOK_LINE_AREA_LEN: usize = RECIPE_BOOK_LINE_COUNT * RECIPE_BOOK_LINE_STRIDE;
|
||||
const RECIPE_BOOK_SUMMARY_END_OFFSET: usize =
|
||||
RECIPE_BOOK_ROOT_OFFSET + RECIPE_BOOK_COUNT * RECIPE_BOOK_STRIDE;
|
||||
const RT3_SAVE_WORLD_BLOCK_CHUNK_TAG: u32 = 0x000032c8;
|
||||
const RT3_SAVE_WORLD_BLOCK_NEXT_CHUNK_TAG: u32 = 0x000032c9;
|
||||
const RT3_SAVE_WORLD_BLOCK_LEN: usize = 0x4f2c;
|
||||
const RT3_SAVE_WORLD_BLOCK_SELECTED_COMPANY_ID_RELATIVE_OFFSET: usize = 0x1d;
|
||||
const RT3_SAVE_WORLD_BLOCK_SELECTED_CHAIRMAN_PROFILE_ID_RELATIVE_OFFSET: usize = 0x21;
|
||||
const EVENT_RUNTIME_COLLECTION_METADATA_TAG: u16 = 0x4e99;
|
||||
const EVENT_RUNTIME_COLLECTION_RECORDS_TAG: u16 = 0x4e9a;
|
||||
const EVENT_RUNTIME_COLLECTION_CLOSE_TAG: u16 = 0x4e9b;
|
||||
|
|
@ -1444,6 +1449,24 @@ pub struct SmpRt3105SaveBridgePayloadProbe {
|
|||
pub evidence: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SmpSaveWorldSelectionContextProbe {
|
||||
pub profile_family: String,
|
||||
pub source_kind: String,
|
||||
pub semantic_family: String,
|
||||
pub chunk_tag_offset: usize,
|
||||
pub payload_offset: usize,
|
||||
pub payload_len: usize,
|
||||
pub payload_len_hex: String,
|
||||
pub selected_company_id_offset: usize,
|
||||
pub selected_company_id: u32,
|
||||
pub selected_company_id_hex: String,
|
||||
pub selected_chairman_profile_id_offset: usize,
|
||||
pub selected_chairman_profile_id: u32,
|
||||
pub selected_chairman_profile_id_hex: String,
|
||||
pub evidence: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SmpRt3105SaveNameTableProbe {
|
||||
pub profile_family: String,
|
||||
|
|
@ -2362,6 +2385,7 @@ pub struct SmpInspectionReport {
|
|||
pub runtime_post_span_probe: Option<SmpRuntimePostSpanProbe>,
|
||||
pub rt3_105_post_span_bridge_probe: Option<SmpRt3105PostSpanBridgeProbe>,
|
||||
pub rt3_105_save_bridge_payload_probe: Option<SmpRt3105SaveBridgePayloadProbe>,
|
||||
pub save_world_selection_context_probe: Option<SmpSaveWorldSelectionContextProbe>,
|
||||
pub rt3_105_save_name_table_probe: Option<SmpRt3105SaveNameTableProbe>,
|
||||
pub rt3_105_save_named_locomotive_availability_probe:
|
||||
Option<SmpRt3105SaveNamedLocomotiveAvailabilityProbe>,
|
||||
|
|
@ -2497,6 +2521,14 @@ pub fn load_save_slice_from_report(
|
|||
.recipe_book_summary_probe
|
||||
.as_ref()
|
||||
.and_then(derive_cargo_catalog_from_recipe_book_probe);
|
||||
let company_roster = report
|
||||
.save_world_selection_context_probe
|
||||
.as_ref()
|
||||
.and_then(derive_selection_only_company_roster_from_save_world_probe);
|
||||
let chairman_profile_table = report
|
||||
.save_world_selection_context_probe
|
||||
.as_ref()
|
||||
.and_then(derive_selection_only_chairman_profile_table_from_save_world_probe);
|
||||
let special_conditions_table =
|
||||
report
|
||||
.special_conditions_probe
|
||||
|
|
@ -2509,6 +2541,21 @@ pub fn load_save_slice_from_report(
|
|||
enabled_visible_labels: probe.enabled_visible_labels.clone(),
|
||||
entries: probe.entries.clone(),
|
||||
});
|
||||
let mut notes = summary.notes.clone();
|
||||
if let Some(probe) = &report.save_world_selection_context_probe {
|
||||
notes.push(format!(
|
||||
"Raw save fixed world block exposes selected_company_id={} at file offset 0x{:x}.",
|
||||
probe.selected_company_id, probe.selected_company_id_offset
|
||||
));
|
||||
notes.push(format!(
|
||||
"Raw save fixed world block exposes selected_chairman_profile_id={} at file offset 0x{:x}.",
|
||||
probe.selected_chairman_profile_id, probe.selected_chairman_profile_id_offset
|
||||
));
|
||||
notes.push(
|
||||
"Raw save inspection still does not reconstruct full company_roster or chairman_profile_table payloads; the grounded package-save path only proves selection ids and header-level collection state for those families."
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(SmpLoadedSaveSlice {
|
||||
file_extension_hint: summary.file_extension_hint.clone(),
|
||||
|
|
@ -2522,11 +2569,11 @@ pub fn load_save_slice_from_report(
|
|||
named_locomotive_availability_table,
|
||||
locomotive_catalog,
|
||||
cargo_catalog,
|
||||
company_roster: None,
|
||||
chairman_profile_table: None,
|
||||
company_roster,
|
||||
chairman_profile_table,
|
||||
special_conditions_table,
|
||||
event_runtime_collection: report.event_runtime_collection_summary.clone(),
|
||||
notes: summary.notes.clone(),
|
||||
notes,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -2609,6 +2656,30 @@ fn derive_cargo_catalog_from_recipe_book_probe(
|
|||
})
|
||||
}
|
||||
|
||||
fn derive_selection_only_company_roster_from_save_world_probe(
|
||||
probe: &SmpSaveWorldSelectionContextProbe,
|
||||
) -> Option<SmpLoadedCompanyRoster> {
|
||||
Some(SmpLoadedCompanyRoster {
|
||||
source_kind: format!("{}-company-selection-only", probe.source_kind),
|
||||
semantic_family: "scenario-selected-company-context".to_string(),
|
||||
observed_entry_count: 0,
|
||||
selected_company_id: Some(probe.selected_company_id),
|
||||
entries: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
fn derive_selection_only_chairman_profile_table_from_save_world_probe(
|
||||
probe: &SmpSaveWorldSelectionContextProbe,
|
||||
) -> Option<SmpLoadedChairmanProfileTable> {
|
||||
Some(SmpLoadedChairmanProfileTable {
|
||||
source_kind: format!("{}-chairman-selection-only", probe.source_kind),
|
||||
semantic_family: "scenario-selected-chairman-context".to_string(),
|
||||
observed_entry_count: 0,
|
||||
selected_chairman_profile_id: Some(probe.selected_chairman_profile_id),
|
||||
entries: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
fn known_cargo_slot_definition(slot_id: u32) -> Option<KnownCargoSlotDefinition> {
|
||||
KNOWN_CARGO_SLOT_DEFINITIONS
|
||||
.iter()
|
||||
|
|
@ -5264,6 +5335,11 @@ fn inspect_bundle_bytes(bytes: &[u8], file_extension_hint: Option<String>) -> Sm
|
|||
);
|
||||
let rt3_105_save_bridge_payload_probe =
|
||||
parse_rt3_105_save_bridge_payload_probe(bytes, rt3_105_post_span_bridge_probe.as_ref());
|
||||
let save_world_selection_context_probe = parse_save_world_selection_context_probe(
|
||||
bytes,
|
||||
file_extension_hint.as_deref(),
|
||||
container_profile.as_ref(),
|
||||
);
|
||||
let rt3_105_save_name_table_probe = parse_rt3_105_save_name_table_probe(
|
||||
bytes,
|
||||
file_extension_hint.as_deref(),
|
||||
|
|
@ -5410,6 +5486,7 @@ fn inspect_bundle_bytes(bytes: &[u8], file_extension_hint: Option<String>) -> Sm
|
|||
runtime_post_span_probe,
|
||||
rt3_105_post_span_bridge_probe,
|
||||
rt3_105_save_bridge_payload_probe,
|
||||
save_world_selection_context_probe,
|
||||
rt3_105_save_name_table_probe,
|
||||
rt3_105_save_named_locomotive_availability_probe,
|
||||
special_conditions_probe,
|
||||
|
|
@ -6826,6 +6903,74 @@ fn parse_rt3_105_save_bridge_payload_probe(
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_save_world_selection_context_probe(
|
||||
bytes: &[u8],
|
||||
file_extension_hint: Option<&str>,
|
||||
container_profile: Option<&SmpContainerProfile>,
|
||||
) -> Option<SmpSaveWorldSelectionContextProbe> {
|
||||
if file_extension_hint != Some("gms") {
|
||||
return None;
|
||||
}
|
||||
let profile = container_profile?;
|
||||
let supported = matches!(
|
||||
profile.profile_family.as_str(),
|
||||
"rt3-classic-save-container-v1"
|
||||
| "rt3-105-save-container-v1"
|
||||
| "rt3-105-scenario-save-container-v1"
|
||||
| "rt3-105-alt-save-container-v1"
|
||||
);
|
||||
if !supported {
|
||||
return None;
|
||||
}
|
||||
|
||||
for chunk_tag_offset in find_u32_le_offsets(bytes, RT3_SAVE_WORLD_BLOCK_CHUNK_TAG) {
|
||||
let payload_offset = chunk_tag_offset + 4;
|
||||
let next_chunk_tag_offset = payload_offset.checked_add(RT3_SAVE_WORLD_BLOCK_LEN)?;
|
||||
if read_u32_at(bytes, next_chunk_tag_offset) != Some(RT3_SAVE_WORLD_BLOCK_NEXT_CHUNK_TAG) {
|
||||
continue;
|
||||
}
|
||||
let selected_company_id_offset =
|
||||
payload_offset + RT3_SAVE_WORLD_BLOCK_SELECTED_COMPANY_ID_RELATIVE_OFFSET;
|
||||
let selected_chairman_profile_id_offset =
|
||||
payload_offset + RT3_SAVE_WORLD_BLOCK_SELECTED_CHAIRMAN_PROFILE_ID_RELATIVE_OFFSET;
|
||||
let selected_company_id = read_u32_at(bytes, selected_company_id_offset)?;
|
||||
let selected_chairman_profile_id = read_u32_at(bytes, selected_chairman_profile_id_offset)?;
|
||||
return Some(SmpSaveWorldSelectionContextProbe {
|
||||
profile_family: profile.profile_family.clone(),
|
||||
source_kind: "save-direct-world-block".to_string(),
|
||||
semantic_family: "scenario-selected-company-and-chairman-context".to_string(),
|
||||
chunk_tag_offset,
|
||||
payload_offset,
|
||||
payload_len: RT3_SAVE_WORLD_BLOCK_LEN,
|
||||
payload_len_hex: format!("0x{:x}", RT3_SAVE_WORLD_BLOCK_LEN),
|
||||
selected_company_id_offset,
|
||||
selected_company_id,
|
||||
selected_company_id_hex: format!("0x{selected_company_id:08x}"),
|
||||
selected_chairman_profile_id_offset,
|
||||
selected_chairman_profile_id,
|
||||
selected_chairman_profile_id_hex: format!("0x{selected_chairman_profile_id:08x}"),
|
||||
evidence: vec![
|
||||
format!(
|
||||
"chunk tag 0x32c8 at 0x{chunk_tag_offset:x} matches the fixed [world+0x04] save block"
|
||||
),
|
||||
format!(
|
||||
"next chunk tag 0x32c9 appears at 0x{next_chunk_tag_offset:x}, matching the documented 0x4f2c payload span"
|
||||
),
|
||||
format!(
|
||||
"selected company id comes from payload +0x{:x} ([world+0x21])",
|
||||
RT3_SAVE_WORLD_BLOCK_SELECTED_COMPANY_ID_RELATIVE_OFFSET
|
||||
),
|
||||
format!(
|
||||
"selected chairman profile id comes from payload +0x{:x} ([world+0x25])",
|
||||
RT3_SAVE_WORLD_BLOCK_SELECTED_CHAIRMAN_PROFILE_ID_RELATIVE_OFFSET
|
||||
),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn parse_rt3_105_save_name_table_probe(
|
||||
bytes: &[u8],
|
||||
file_extension_hint: Option<&str>,
|
||||
|
|
@ -8619,6 +8764,15 @@ fn find_u16_le_offsets(bytes: &[u8], needle: u16) -> Vec<usize> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn find_u32_le_offsets(bytes: &[u8], needle: u32) -> Vec<usize> {
|
||||
let pattern = needle.to_le_bytes();
|
||||
bytes
|
||||
.windows(pattern.len())
|
||||
.enumerate()
|
||||
.filter_map(|(offset, window)| (window == pattern).then_some(offset))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn find_next_nonzero_offset(bytes: &[u8], start: usize) -> Option<usize> {
|
||||
bytes
|
||||
.iter()
|
||||
|
|
@ -13025,6 +13179,114 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_save_world_selection_context_probe_from_fixed_world_block() {
|
||||
let mut bytes = vec![0u8; 0x8000];
|
||||
let chunk_tag_offset = 0x3ceusize;
|
||||
let payload_offset = chunk_tag_offset + 4;
|
||||
bytes[chunk_tag_offset..chunk_tag_offset + 4]
|
||||
.copy_from_slice(&RT3_SAVE_WORLD_BLOCK_CHUNK_TAG.to_le_bytes());
|
||||
bytes[payload_offset + RT3_SAVE_WORLD_BLOCK_SELECTED_COMPANY_ID_RELATIVE_OFFSET
|
||||
..payload_offset + RT3_SAVE_WORLD_BLOCK_SELECTED_COMPANY_ID_RELATIVE_OFFSET + 4]
|
||||
.copy_from_slice(&7u32.to_le_bytes());
|
||||
bytes[payload_offset + RT3_SAVE_WORLD_BLOCK_SELECTED_CHAIRMAN_PROFILE_ID_RELATIVE_OFFSET
|
||||
..payload_offset
|
||||
+ RT3_SAVE_WORLD_BLOCK_SELECTED_CHAIRMAN_PROFILE_ID_RELATIVE_OFFSET
|
||||
+ 4]
|
||||
.copy_from_slice(&9u32.to_le_bytes());
|
||||
let next_chunk_offset = payload_offset + RT3_SAVE_WORLD_BLOCK_LEN;
|
||||
bytes[next_chunk_offset..next_chunk_offset + 4]
|
||||
.copy_from_slice(&RT3_SAVE_WORLD_BLOCK_NEXT_CHUNK_TAG.to_le_bytes());
|
||||
|
||||
let probe = parse_save_world_selection_context_probe(
|
||||
&bytes,
|
||||
Some("gms"),
|
||||
Some(&SmpContainerProfile {
|
||||
profile_family: "rt3-105-save-container-v1".to_string(),
|
||||
profile_evidence: vec![],
|
||||
is_known_profile: true,
|
||||
}),
|
||||
)
|
||||
.expect("selection-context probe should parse");
|
||||
|
||||
assert_eq!(probe.chunk_tag_offset, chunk_tag_offset);
|
||||
assert_eq!(probe.payload_offset, payload_offset);
|
||||
assert_eq!(probe.selected_company_id, 7);
|
||||
assert_eq!(probe.selected_chairman_profile_id, 9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_selection_only_company_and_chairman_context_from_save_world_probe() {
|
||||
let mut report = inspect_smp_bytes(&[]);
|
||||
report.save_load_summary = Some(SmpSaveLoadSummary {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-105-save-container-v1".to_string()),
|
||||
mechanism_family: "rt3-105-save-post-span-bridge-v1".to_string(),
|
||||
mechanism_confidence: "mixed".to_string(),
|
||||
packed_profile_kind: None,
|
||||
packed_profile_family: None,
|
||||
packed_profile_offset: None,
|
||||
packed_profile_len: None,
|
||||
map_path: None,
|
||||
display_name: None,
|
||||
profile_byte_0x77: None,
|
||||
profile_byte_0x77_hex: None,
|
||||
profile_byte_0x82: None,
|
||||
profile_byte_0x82_hex: None,
|
||||
profile_byte_0x97: None,
|
||||
profile_byte_0x97_hex: None,
|
||||
profile_byte_0xc5: None,
|
||||
profile_byte_0xc5_hex: None,
|
||||
trailer_family: Some("rt3-105-save-trailer-v1".to_string()),
|
||||
bridge_family: Some("rt3-105-save-post-span-bridge-v1".to_string()),
|
||||
candidate_table: None,
|
||||
notes: vec![],
|
||||
});
|
||||
report.save_world_selection_context_probe = Some(SmpSaveWorldSelectionContextProbe {
|
||||
profile_family: "rt3-105-save-container-v1".to_string(),
|
||||
source_kind: "save-direct-world-block".to_string(),
|
||||
semantic_family: "scenario-selected-company-and-chairman-context".to_string(),
|
||||
chunk_tag_offset: 0x3ce,
|
||||
payload_offset: 0x3d2,
|
||||
payload_len: RT3_SAVE_WORLD_BLOCK_LEN,
|
||||
payload_len_hex: format!("0x{:x}", RT3_SAVE_WORLD_BLOCK_LEN),
|
||||
selected_company_id_offset: 0x3ef,
|
||||
selected_company_id: 1,
|
||||
selected_company_id_hex: "0x00000001".to_string(),
|
||||
selected_chairman_profile_id_offset: 0x3f3,
|
||||
selected_chairman_profile_id: 9,
|
||||
selected_chairman_profile_id_hex: "0x00000009".to_string(),
|
||||
evidence: vec![],
|
||||
});
|
||||
|
||||
let slice = load_save_slice_from_report(&report).expect("save slice");
|
||||
|
||||
let company_roster = slice.company_roster.expect("selection-only company roster");
|
||||
assert_eq!(company_roster.observed_entry_count, 0);
|
||||
assert_eq!(company_roster.selected_company_id, Some(1));
|
||||
assert!(company_roster.entries.is_empty());
|
||||
|
||||
let chairman_table = slice
|
||||
.chairman_profile_table
|
||||
.expect("selection-only chairman table");
|
||||
assert_eq!(chairman_table.observed_entry_count, 0);
|
||||
assert_eq!(chairman_table.selected_chairman_profile_id, Some(9));
|
||||
assert!(chairman_table.entries.is_empty());
|
||||
|
||||
assert!(
|
||||
slice
|
||||
.notes
|
||||
.iter()
|
||||
.any(|note| note.contains("selected_company_id=1"))
|
||||
);
|
||||
assert!(
|
||||
slice
|
||||
.notes
|
||||
.iter()
|
||||
.any(|note| note.contains("selected_chairman_profile_id=9"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn classifies_rt3_105_post_span_bridge_variants() {
|
||||
let base_trailer = SmpRuntimeTrailerBlock {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,10 @@ The highest-value next passes are now:
|
|||
- checked-in save-slice documents can now carry explicit company rosters and chairman profile
|
||||
tables too, so the current company-targeted and chairman-targeted descriptor/condition batches
|
||||
can execute from standalone save-slice fixtures without overlay snapshots when that context is
|
||||
present; raw `.gms` inspection/export still does not reconstruct those company/chairman surfaces
|
||||
present; raw `.gms` inspection/export still does not reconstruct full company/chairman rosters,
|
||||
but it now does reconstruct selection-only company/chairman context from the fixed save-side
|
||||
`0x32c8` world block, so overlay imports can reuse base rosters while honoring raw save-native
|
||||
selected company/chairman ids
|
||||
- a checked-in `EventEffects` export now exists at
|
||||
`artifacts/exports/rt3-1.06/event-effects-table.json`, and a checked-in semantic closure layer
|
||||
now exists at `artifacts/exports/rt3-1.06/event-effects-semantic-catalog.json`
|
||||
|
|
@ -122,7 +125,9 @@ The highest-value next passes are now:
|
|||
/ `All Farm/Mine Production` land on bounded event-owned cargo override state, and the grounded
|
||||
named cargo-production strip `180..229` now lands on named cargo production overrides too
|
||||
- the named cargo-price strip `106..176` remains explicit
|
||||
`blocked_evidence_blocked_descriptor` parity until descriptor ordering is pinned more strongly
|
||||
`blocked_evidence_blocked_descriptor` parity until descriptor ordering is pinned more strongly,
|
||||
but the checked-in semantic catalog now gives that band stable `Named Cargo Price Slot N`
|
||||
labels instead of anonymous `Unknown Cargo Price` residue
|
||||
- the add-building strip `503..519` is now explicitly classified as recovered shell-owned parity,
|
||||
with tracked fixture coverage, instead of generic unresolved descriptor residue
|
||||
- widen real packed-event executable coverage descriptor by descriptor after identity, target mask,
|
||||
|
|
|
|||
|
|
@ -59,7 +59,9 @@ Implemented today:
|
|||
those save-owned surfaces; that lets the currently supported company-targeted and
|
||||
chairman-targeted descriptor/condition batches execute from standalone save-slice fixtures
|
||||
without overlay snapshots when the checked-in documents include that context, while raw `.gms`
|
||||
inspection/export still leaves those company/chairman surfaces absent
|
||||
inspection/export still leaves full company/chairman rosters absent; the grounded raw-save
|
||||
tranche now covers only selection-only company/chairman context from the fixed `0x32c8` world
|
||||
block, which overlay import can use to replace selected ids while preserving base rosters
|
||||
- a checked-in `EventEffects` export now exists too at
|
||||
`artifacts/exports/rt3-1.06/event-effects-table.json`, and a checked-in semantic closure layer
|
||||
now exists at `artifacts/exports/rt3-1.06/event-effects-semantic-catalog.json`
|
||||
|
|
@ -84,7 +86,9 @@ Implemented today:
|
|||
/ `All Farm/Mine Production` import through bounded cargo override surfaces, and the grounded
|
||||
named cargo-production strip `180..229` now imports through named cargo production overrides too
|
||||
- the named cargo-price strip `106..176` now sits on explicit
|
||||
`blocked_evidence_blocked_descriptor` parity instead of generic unmapped-descriptor frontier
|
||||
`blocked_evidence_blocked_descriptor` parity instead of generic unmapped-descriptor frontier;
|
||||
the checked-in semantic catalog now at least gives that band stable `Named Cargo Price Slot N`
|
||||
labels instead of anonymous `Unknown Cargo Price` residue
|
||||
- the add-building strip `503..519` is now explicitly classified as recovered shell-owned parity
|
||||
with tracked fixture coverage, not generic unresolved descriptor residue
|
||||
- a minimal event-owned train surface and an opaque economic-status lane now exist in runtime
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
"grouped_effect_rows": [
|
||||
{
|
||||
"descriptor_id": 106,
|
||||
"descriptor_label": "Unknown Cargo Price",
|
||||
"descriptor_label": "Named Cargo Price Slot 1",
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"semantic_family": "scalar_assignment"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@
|
|||
"group_index": 0,
|
||||
"row_index": 0,
|
||||
"descriptor_id": 106,
|
||||
"descriptor_label": "Unknown Cargo Price",
|
||||
"descriptor_label": "Named Cargo Price Slot 1",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"opcode": 3,
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
"value_word_0x16": 0,
|
||||
"row_shape": "scalar_assignment",
|
||||
"semantic_family": "scalar_assignment",
|
||||
"semantic_preview": "Set Unknown Cargo Price to 140",
|
||||
"semantic_preview": "Set Named Cargo Price Slot 1 to 140",
|
||||
"recovered_cargo_slot": null,
|
||||
"recovered_cargo_class": null,
|
||||
"recovered_locomotive_id": null,
|
||||
|
|
|
|||
|
|
@ -98,6 +98,12 @@ def locomotive_cost_label(locomotive_id: int) -> str:
|
|||
return f"Lower-Band Locomotive Cost Slot {locomotive_id}"
|
||||
|
||||
|
||||
def cargo_price_label(descriptor_id: int, binding: dict[str, object] | None) -> str:
|
||||
if binding is not None:
|
||||
return f"{binding['cargo_name']} Price"
|
||||
return f"Named Cargo Price Slot {descriptor_id - 105}"
|
||||
|
||||
|
||||
def load_cargo_bindings(raw_table_path: Path) -> dict[int, dict[str, object]]:
|
||||
bindings_path = raw_table_path.parent / "event-effects-cargo-bindings.json"
|
||||
if not bindings_path.exists():
|
||||
|
|
@ -152,6 +158,11 @@ def classify(
|
|||
executable_in_runtime = True
|
||||
elif 106 <= descriptor_id <= 176:
|
||||
parameter_family = "cargo_price_scalar"
|
||||
binding = cargo_bindings.get(descriptor_id)
|
||||
label = cargo_price_label(descriptor_id, binding)
|
||||
if binding is not None:
|
||||
runtime_status = "executable"
|
||||
executable_in_runtime = True
|
||||
elif 177 <= descriptor_id <= 179:
|
||||
parameter_family = "cargo_production_scalar"
|
||||
runtime_status = "executable"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue