Skip to main content

dump_fixture/
dump_fixture.rs

1//! Scratch dump tool for inspecting the new brs-js fixtures (wires,
2//! components, entities). Mirrors examples/read_brz.rs (global data, brick
3//! chunk SoA, component chunk SoA + per-instance component list, wire chunk
4//! SoA), generalized to accept any grid id and either a .brz or .brdb path,
5//! plus (for entities) the entity chunk index/SoA dump from
6//! examples/read_entities.rs. Not part of the committed example set — purely
7//! a debugging aid for writing the report's ground-truth dumps.
8use brdb::{BrFsReader, Brdb, BrReader, Brz, IntoReader, WireChunkSoA};
9use std::path::PathBuf;
10
11fn run<T: BrFsReader>(db: &BrReader<T>) -> Result<(), Box<dyn std::error::Error>> {
12    let data = db.global_data()?;
13    println!("Basic Brick assets: {:?}", data.basic_brick_asset_names);
14    println!("Procedural Brick assets: {:?}", data.procedural_brick_asset_names);
15    // register_all_components() embeds the FULL catalog (hundreds of wire
16    // ports/component types), so only print counts for those — the fixture's
17    // OWN types/ports are visible per-brick below via the type-name lookups.
18    println!(
19        "Wire port count: {} (registered catalog)",
20        data.component_wire_port_names.len()
21    );
22    println!(
23        "Component type count: {} (registered catalog)",
24        data.component_type_names.len()
25    );
26    println!("Entity types: {:?}", data.entity_type_names);
27    println!("Entity classes: {:?}", data.entity_data_class_names);
28
29    // Probe grid ids 1.. until one is missing (grid 1 is always the main
30    // grid; higher ids are sub-grids / microchip inner grids).
31    for gid in 1..32 {
32        let chunks = match db.brick_chunk_index(gid) {
33            Ok(c) => c,
34            Err(_) => break,
35        };
36        println!("=== grid {gid} ===");
37        println!("Brick chunks: {chunks:?}");
38        for chunk in &chunks {
39            let soa = db.brick_chunk_soa(gid, chunk.index)?;
40            println!("Brick soa: {soa:?}");
41            let asset_names: Vec<String> = soa
42                .brick_type_indices
43                .iter()
44                .map(|&t| {
45                    if (t as usize) < soa.procedural_brick_starting_index as usize {
46                        data.basic_brick_asset_names
47                            .get_index(t as usize)
48                            .cloned()
49                            .unwrap_or_default()
50                    } else {
51                        "<procedural>".to_string()
52                    }
53                })
54                .collect();
55            println!("Brick asset names (by index in chunk): {asset_names:?}");
56
57            if chunk.num_components > 0 {
58                let (soa, components) = db.component_chunk_soa(gid, chunk.index)?;
59                let type_names: Vec<String> = soa
60                    .component_type_counters
61                    .iter()
62                    .flat_map(|c| {
63                        let name = data
64                            .component_type_names
65                            .get_index(c.type_index as usize)
66                            .cloned()
67                            .unwrap_or_default();
68                        (0..c.num_instances).map(move |_| name.clone())
69                    })
70                    .collect();
71                println!(
72                    "Component chunk soa: component_brick_indices={:?} microchip_brick_indices={:?} microchip_brick_grid_references={:?}",
73                    soa.component_brick_indices,
74                    soa.microchip_brick_indices,
75                    soa.microchip_brick_grid_references
76                );
77                println!("Component type names (parallel to ComponentBrickIndices): {type_names:?}");
78                for c in components {
79                    println!("Component: {c}");
80                }
81            }
82            if chunk.num_wires > 0 {
83                let raw = db.wire_chunk_soa(gid, chunk.index)?;
84                println!("Wire chunk soa (raw struct): {raw}");
85                let value = raw.to_value();
86                let soa: WireChunkSoA = (&value).try_into()?;
87                let port_name = |i: u16| {
88                    data.component_wire_port_names
89                        .get_index(i as usize)
90                        .cloned()
91                        .unwrap_or_default()
92                };
93                let type_name = |i: u16| {
94                    data.component_type_names
95                        .get_index(i as usize)
96                        .cloned()
97                        .unwrap_or_default()
98                };
99                for s in &soa.local_wire_sources {
100                    println!(
101                        "  local source: brick_in_chunk={} type={} port={}",
102                        s.brick_index_in_chunk,
103                        type_name(s.component_type_index),
104                        port_name(s.port_index)
105                    );
106                }
107                for t in &soa.local_wire_targets {
108                    println!(
109                        "  local target: brick_in_chunk={} type={} port={}",
110                        t.brick_index_in_chunk,
111                        type_name(t.component_type_index),
112                        port_name(t.port_index)
113                    );
114                }
115                for s in &soa.remote_wire_sources {
116                    println!(
117                        "  remote source: grid_persistent_index={} chunk={} brick_in_chunk={} type={} port={}",
118                        s.grid_persistent_index,
119                        s.chunk_index,
120                        s.brick_index_in_chunk,
121                        type_name(s.component_type_index),
122                        port_name(s.port_index)
123                    );
124                }
125                for t in &soa.remote_wire_targets {
126                    println!(
127                        "  remote target: brick_in_chunk={} type={} port={}",
128                        t.brick_index_in_chunk,
129                        type_name(t.component_type_index),
130                        port_name(t.port_index)
131                    );
132                }
133            }
134        }
135    }
136
137    // Entity chunks (present whenever the world has any grids/entities).
138    let entity_chunk_indices = db.entity_chunk_index()?;
139    println!("=== entities ===");
140    println!("Entity chunk indices: {entity_chunk_indices:?}");
141    for chunk_index in entity_chunk_indices {
142        let (soa, entity_data) = db.entity_chunk_soa(chunk_index)?;
143        println!("--- Chunk {chunk_index} (SoA) ---");
144        println!("Type counters: {:?}", soa.type_counters);
145        let type_names: Vec<String> = soa
146            .type_counters
147            .iter()
148            .flat_map(|c| {
149                let name = data
150                    .entity_type_names
151                    .get_index(c.type_index as usize)
152                    .cloned()
153                    .unwrap_or_default();
154                (0..c.num_entities).map(move |_| name.clone())
155            })
156            .collect();
157        println!("Entity type names (parallel to PersistentIndices): {type_names:?}");
158        println!("Persistent indices: {:?}", soa.persistent_indices);
159        println!("Locations: {:?}", soa.locations);
160        println!("Rotations: {:?}", soa.rotations);
161        println!("Physics locked (frozen): {:?}", soa.physics_locked_flags);
162        println!("Physics sleeping: {:?}", soa.physics_sleeping_flags);
163        for (i, data) in entity_data.iter().enumerate() {
164            match data {
165                Some(struct_data) => println!("  Entity {i} struct: {struct_data}"),
166                None => println!("  Entity {i}: None"),
167            }
168        }
169    }
170
171    println!("Files: {}", db.get_fs()?.render());
172
173    Ok(())
174}
175
176fn main() -> Result<(), Box<dyn std::error::Error>> {
177    let p = PathBuf::from(std::env::args().nth(1).unwrap());
178    if p.extension().and_then(|e| e.to_str()) == Some("brdb") {
179        run(&Brdb::open(&p)?.into_reader())
180    } else {
181        run(&Brz::open(&p)?.into_reader())
182    }
183}