Expose add-building dispatch rows in map summaries

This commit is contained in:
Jan Petykiewicz 2026-04-19 10:06:54 -07:00
commit 8828d510fb
3 changed files with 435 additions and 0 deletions

View file

@ -3980,6 +3980,14 @@ pub struct SmpLoadedEventRuntimeCollectionSummary {
#[serde(default)]
pub trigger_kinds_present: Vec<u8>,
#[serde(default)]
pub add_building_dispatch_strip_record_indexes: Vec<usize>,
#[serde(default)]
pub add_building_dispatch_strip_descriptor_labels: Vec<String>,
#[serde(default)]
pub add_building_dispatch_strip_records_with_trigger_kind: usize,
#[serde(default)]
pub add_building_dispatch_strip_records_missing_trigger_kind: usize,
#[serde(default)]
pub control_lane_notes: Vec<String>,
#[serde(default)]
pub records: Vec<SmpLoadedPackedEventRecordSummary>,
@ -9928,6 +9936,38 @@ fn parse_event_runtime_collection_summary_with_tag_width(
.collect::<Vec<_>>();
opcode_0x08_record_indexes.sort_unstable();
opcode_0x08_record_indexes.dedup();
let mut add_building_dispatch_strip_record_indexes = records
.iter()
.filter(|record| {
record.grouped_effect_rows.iter().any(|row| {
opcode_reaches_world_apply_compact_runtime_effect_dispatch_strip(row.opcode)
&& compact_event_dispatch_add_building_descriptor_id(row.descriptor_id)
})
})
.map(|record| record.record_index)
.collect::<Vec<_>>();
add_building_dispatch_strip_record_indexes.sort_unstable();
add_building_dispatch_strip_record_indexes.dedup();
let add_building_dispatch_strip_records_with_trigger_kind = records
.iter()
.filter(|record| {
record.trigger_kind.is_some()
&& record.grouped_effect_rows.iter().any(|row| {
opcode_reaches_world_apply_compact_runtime_effect_dispatch_strip(row.opcode)
&& compact_event_dispatch_add_building_descriptor_id(row.descriptor_id)
})
})
.count();
let add_building_dispatch_strip_records_missing_trigger_kind = records
.iter()
.filter(|record| {
record.trigger_kind.is_none()
&& record.grouped_effect_rows.iter().any(|row| {
opcode_reaches_world_apply_compact_runtime_effect_dispatch_strip(row.opcode)
&& compact_event_dispatch_add_building_descriptor_id(row.descriptor_id)
})
})
.count();
let mut mutation_candidate_descriptor_labels = records
.iter()
.flat_map(|record| record.grouped_effect_rows.iter())
@ -9938,6 +9978,17 @@ fn parse_event_runtime_collection_summary_with_tag_width(
.collect::<Vec<_>>();
mutation_candidate_descriptor_labels.sort_unstable();
mutation_candidate_descriptor_labels.dedup();
let mut add_building_dispatch_strip_descriptor_labels = records
.iter()
.flat_map(|record| record.grouped_effect_rows.iter())
.filter(|row| {
opcode_reaches_world_apply_compact_runtime_effect_dispatch_strip(row.opcode)
&& compact_event_dispatch_add_building_descriptor_id(row.descriptor_id)
})
.filter_map(|row| row.descriptor_label.clone())
.collect::<Vec<_>>();
add_building_dispatch_strip_descriptor_labels.sort_unstable();
add_building_dispatch_strip_descriptor_labels.dedup();
let mut mutation_candidate_unknown_descriptor_ids = records
.iter()
.flat_map(|record| record.grouped_effect_rows.iter())
@ -10060,6 +10111,21 @@ fn parse_event_runtime_collection_summary_with_tag_width(
"checked-in function-map evidence currently grounds opcode 0x08 on the 0x00426d60 company_deactivate_and_clear_chairman_share_links branch".to_string(),
);
}
if !add_building_dispatch_strip_record_indexes.is_empty() {
control_lane_notes.push(format!(
"records with Add Building descriptors in the 0x00431b20 dispatch strip = {:?}",
add_building_dispatch_strip_record_indexes
));
control_lane_notes.push(format!(
"decoded Add Building descriptor labels present in the 0x00431b20 dispatch strip = {:?}",
add_building_dispatch_strip_descriptor_labels
));
if add_building_dispatch_strip_records_with_trigger_kind == 0 {
control_lane_notes.push(
"every currently decoded Add Building dispatch-strip row still has null trigger kind, so the missing control-lane mapping remains the blocker above the already-grounded add-building descriptor bridge".to_string(),
);
}
}
}
return Some(SmpLoadedEventRuntimeCollectionSummary {
@ -10087,6 +10153,10 @@ fn parse_event_runtime_collection_summary_with_tag_width(
nondirect_compact_record_count,
nondirect_compact_records_missing_trigger_kind,
trigger_kinds_present,
add_building_dispatch_strip_record_indexes,
add_building_dispatch_strip_descriptor_labels,
add_building_dispatch_strip_records_with_trigger_kind,
add_building_dispatch_strip_records_missing_trigger_kind,
control_lane_notes,
records,
});
@ -10099,6 +10169,10 @@ fn opcode_reaches_world_apply_compact_runtime_effect_dispatch_strip(opcode: u8)
matches!(opcode, 0x04..=0x08 | 0x0d | 0x10..=0x13 | 0x16)
}
fn compact_event_dispatch_add_building_descriptor_id(descriptor_id: u32) -> bool {
(503..=613).contains(&descriptor_id)
}
fn known_special_condition_label_for_compact_descriptor_id(
descriptor_id: u32,
) -> Option<&'static str> {
@ -22669,6 +22743,16 @@ mod tests {
assert_eq!(summary.records_with_trigger_kind, 0);
assert_eq!(summary.records_missing_trigger_kind, 3);
assert_eq!(summary.nondirect_compact_record_count, 0);
assert!(
summary
.add_building_dispatch_strip_record_indexes
.is_empty()
);
assert!(
summary
.add_building_dispatch_strip_descriptor_labels
.is_empty()
);
assert_eq!(summary.records.len(), 3);
assert_eq!(summary.records[0].decode_status, "unsupported_framing");
}
@ -22707,6 +22791,16 @@ mod tests {
assert_eq!(summary.records_with_trigger_kind, 0);
assert_eq!(summary.records_missing_trigger_kind, 3);
assert_eq!(summary.nondirect_compact_record_count, 0);
assert!(
summary
.add_building_dispatch_strip_record_indexes
.is_empty()
);
assert!(
summary
.add_building_dispatch_strip_descriptor_labels
.is_empty()
);
assert_eq!(summary.records.len(), 3);
assert_eq!(summary.records[0].decode_status, "unsupported_framing");
}
@ -22805,6 +22899,16 @@ mod tests {
assert_eq!(summary.records_missing_trigger_kind, 1);
assert_eq!(summary.nondirect_compact_record_count, 1);
assert_eq!(summary.nondirect_compact_records_missing_trigger_kind, 1);
assert!(
summary
.add_building_dispatch_strip_record_indexes
.is_empty()
);
assert!(
summary
.add_building_dispatch_strip_descriptor_labels
.is_empty()
);
assert!(summary.control_lane_notes.iter().any(|line| {
line.contains("all compact non-direct rows currently decode row bodies only")
}));
@ -22913,6 +23017,82 @@ mod tests {
);
}
#[test]
fn summarizes_add_building_dispatch_strip_rows_from_nondirect_compact_records() {
let mut bytes = Vec::new();
bytes.extend_from_slice(&(EVENT_RUNTIME_COLLECTION_METADATA_TAG as u32).to_le_bytes());
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_PACKED_STATE_VERSION.to_le_bytes());
let header_words = [
0u32, 6, 10, 20, 30, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 23, 0, 0, 0,
];
for word in header_words {
bytes.extend_from_slice(&word.to_le_bytes());
}
bytes.extend_from_slice(&[0u8; 18]);
bytes.extend_from_slice(&(EVENT_RUNTIME_COLLECTION_RECORDS_TAG as u32).to_le_bytes());
bytes.extend_from_slice(&(PACKED_EVENT_REAL_CONDITION_MARKER as u32).to_le_bytes());
bytes.extend_from_slice(&1u32.to_le_bytes());
bytes.extend_from_slice(&u32::MAX.to_le_bytes());
bytes.push(4);
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.push(2);
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&(PACKED_EVENT_REAL_GROUPED_EFFECT_MARKER as u32).to_le_bytes());
bytes.extend_from_slice(&1u32.to_le_bytes());
bytes.extend_from_slice(&548u32.to_le_bytes());
bytes.extend_from_slice(&1u32.to_le_bytes());
bytes.push(8);
bytes.extend_from_slice(&u32::MAX.to_le_bytes());
bytes.extend_from_slice(&u32::MAX.to_le_bytes());
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&[0u8; 12]);
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&0u32.to_le_bytes());
bytes.extend_from_slice(&(PACKED_EVENT_REAL_RECORD_TERMINATOR_MARKER as u32).to_le_bytes());
bytes.extend_from_slice(&(EVENT_RUNTIME_COLLECTION_CLOSE_TAG as u32).to_le_bytes());
let report = inspect_smp_bytes(&bytes);
let summary = report
.event_runtime_collection_summary
.as_ref()
.expect("non-direct event runtime collection summary should parse");
assert_eq!(summary.add_building_dispatch_strip_record_indexes, vec![0]);
assert_eq!(
summary.add_building_dispatch_strip_descriptor_labels,
vec!["Add Building Port01".to_string()]
);
assert_eq!(
summary.add_building_dispatch_strip_records_with_trigger_kind,
0
);
assert_eq!(
summary.add_building_dispatch_strip_records_missing_trigger_kind,
1
);
assert!(summary.control_lane_notes.iter().any(|line| {
line.contains(
"records with Add Building descriptors in the 0x00431b20 dispatch strip = [0]",
)
}));
assert!(summary.control_lane_notes.iter().any(|line| {
line.contains(
"decoded Add Building descriptor labels present in the 0x00431b20 dispatch strip = [\"Add Building Port01\"]",
)
}));
assert!(summary.control_lane_notes.iter().any(|line| {
line.contains("every currently decoded Add Building dispatch-strip row still has null trigger kind")
}));
}
fn encode_len_prefixed_string(text: &str) -> Vec<u8> {
let mut bytes = Vec::with_capacity(1 + text.len());
bytes.push(text.len() as u8);
@ -25688,6 +25868,10 @@ mod tests {
nondirect_compact_record_count: 0,
nondirect_compact_records_missing_trigger_kind: 0,
trigger_kinds_present: vec![],
add_building_dispatch_strip_record_indexes: vec![],
add_building_dispatch_strip_descriptor_labels: vec![],
add_building_dispatch_strip_records_with_trigger_kind: 0,
add_building_dispatch_strip_records_missing_trigger_kind: 0,
control_lane_notes: vec![],
records: build_unsupported_event_runtime_record_summaries(&[1, 3, 5], "test summary"),
});