pub struct World {
pub meta: WorldMeta,
pub owners: IndexMap<Guid, Owner>,
pub bricks: Vec<Brick>,
pub grids: Vec<(Entity, Vec<Brick>)>,
pub wires: Vec<WireConnection>,
pub entities: Vec<Entity>,
pub microchip_links: Vec<(usize, usize)>,
pub prefabs: IndexMap<String, Vec<u8>>,
pub global_data: BrdbSchemaGlobalData,
pub component_schema: BrdbSchema,
pub entity_schema: BrdbSchema,
}Fields§
§meta: WorldMeta§owners: IndexMap<Guid, Owner>§bricks: Vec<Brick>Bricks on the main grid
grids: Vec<(Entity, Vec<Brick>)>Non-main grids require an entity to be created for them
wires: Vec<WireConnection>§entities: Vec<Entity>§microchip_links: Vec<(usize, usize)>Per-microchip linkage pairs: (brick_id, entity_id) where the brick
is the outer microchip shell and the entity is the inner grid.
prefabs: IndexMap<String, Vec<u8>>Embedded prefab archives (the root Prefabs/ folder), keyed by
root-relative path (Prefabs/Uploads/<BLAKE3>.brz) with raw .brz
bytes as values. Populate via World::add_prefab; the returned
path is what a Prefab component property references.
The game requires the Prefabs/Uploads/<BLAKE3>.brz naming — it
crashes loading a bundle whose embedded prefab has any other filename.
Use World::add_prefab rather than inserting a custom key here.
global_data: BrdbSchemaGlobalData§component_schema: BrdbSchema§entity_schema: BrdbSchemaImplementations§
Source§impl World
impl World
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
19fn brick_world() -> World {
20 // Mirror of examples/write_brz.rs — the historical example_brick world.
21 let mut world = World::new();
22 world.meta.bundle.description = "Example World".to_string();
23 world.bricks.push(Brick {
24 position: (0, 0, 6).into(),
25 color: (255, 0, 0).into(),
26 ..Default::default()
27 });
28 world
29}
30
31fn features_world() -> World {
32 // Single chunk (all coords in [0, 2048)): registries, owners, procedural
33 // size run-length grouping (new/extend/reuse), a basic asset, collision
34 // and visibility variants, orientations, material intensity.
35 let mut world = World::new();
36 world.meta.bundle.description = "Feature fixture".to_string();
37
38 let alice = Guid::from_uuid(uuid::Uuid::parse_str(ALICE_UUID).unwrap());
39 let bob = Guid::from_uuid(uuid::Uuid::parse_str(BOB_UUID).unwrap());
40 world.owners.insert(alice, Owner {
41 user_id: alice,
42 user_name: "alice".to_string(),
43 display_name: "Alice".to_string(),
44 });
45 world.owners.insert(bob, Owner {
46 user_id: bob,
47 user_name: "bob".to_string(),
48 display_name: "Bob".to_string(),
49 });
50
51 let tile = |size: (u16, u16, u16)| BrickType::Procedural {
52 asset: assets::bricks::PB_DEFAULT_TILE, // "PB_DefaultTile"
53 size: BrickSize { x: size.0, y: size.1, z: size.2 },
54 };
55
56 // 1: default brick (PB_DefaultBrick 5x5x6, plastic, intensity 5) — new size slot
57 world.bricks.push(Brick {
58 position: (0, 0, 6).into(),
59 color: (255, 0, 0).into(),
60 owner_index: Some(1),
61 ..Default::default()
62 });
63 // 2: tile 10x10x2, metallic, intensity 7, XPositive/Deg90 — new counter entry
64 world.bricks.push(Brick {
65 asset: tile((10, 10, 2)),
66 position: (20, 0, 2).into(),
67 color: (0, 255, 0).into(),
68 owner_index: Some(1),
69 material: assets::materials::METALLIC, // "BMC_Metallic"
70 material_intensity: 7,
71 direction: Direction::XPositive,
72 rotation: Rotation::Deg90,
73 ..Default::default()
74 });
75 // 3: same tile size — size_index_map reuse
76 world.bricks.push(Brick {
77 asset: tile((10, 10, 2)),
78 position: (40, 0, 2).into(),
79 color: (0, 0, 255).into(),
80 owner_index: Some(2),
81 ..Default::default()
82 });
83 // 4: tile 20x20x2 — extends the tail counter (same asset, new size)
84 world.bricks.push(Brick {
85 asset: tile((20, 20, 2)),
86 position: (80, 0, 2).into(),
87 color: (255, 255, 0).into(),
88 owner_index: Some(2),
89 ..Default::default()
90 });
91 // 5: default brick again — reuses slot from brick 1 (map hit after other asset)
92 world.bricks.push(Brick {
93 position: (100, 0, 6).into(),
94 color: (255, 255, 255).into(),
95 owner_index: Some(1),
96 ..Default::default()
97 });
98 // 6: BASIC asset, PUBLIC owner, glow, partial collision, YNegative/Deg180
99 world.bricks.push(Brick {
100 asset: assets::bricks::B_2X2_OVERHANG, // "B_2x2_Overhang"
101 position: (200, 0, 10).into(),
102 color: (128, 64, 32).into(),
103 material: assets::materials::GLOW, // "BMC_Glow"
104 material_intensity: 3,
105 direction: Direction::YNegative,
106 rotation: Rotation::Deg180,
107 collision: Collision { player: false, ..Default::default() },
108 ..Default::default()
109 });
110 // 7: invisible, all-collision-off, tiny proc brick
111 world.bricks.push(Brick {
112 asset: BrickType::Procedural {
113 asset: assets::bricks::PB_DEFAULT_BRICK,
114 size: BrickSize { x: 2, y: 2, z: 2 },
115 },
116 position: (300, 0, 2).into(),
117 color: (10, 20, 30).into(),
118 owner_index: Some(1),
119 visible: false,
120 collision: Collision {
121 player: false,
122 weapon: false,
123 interact: false,
124 physics: false,
125 ..Default::default()
126 },
127 ..Default::default()
128 });
129 world
130}
131
132fn chunks_world() -> World {
133 // Multi-chunk: euclidean chunking with negative coords, plus chunks
134 // 0_0_0 and 1_0_0 carry byte-identical SoA payloads → blob dedup.
135 // NOTE: multi-chunk Rust output has nondeterministic FILE ORDER
136 // (HashMap iteration), so this fixture is hashes-gate only — never
137 // byte-compare its container.
138 let mut world = World::new();
139 world.meta.bundle.description = "Chunk fixture".to_string();
140 for (pos, color) in [
141 ((0, 0, 0), (1, 2, 3)),
142 ((-1, -1, -1), (4, 5, 6)),
143 ((2048, 0, 0), (1, 2, 3)), // same rel pos + color as brick 1
144 ((-2048, 4096, 10), (10, 11, 12)),
145 ((500, 500, 500), (42, 42, 42)),
146 ((2548, 500, 500), (42, 42, 42)), // same rel pos + color as brick 5
147 ] {
148 world.bricks.push(Brick {
149 position: pos.into(),
150 color: color.into(),
151 ..Default::default()
152 });
153 }
154 world
155}
156
157fn wires_world() -> World {
158 // Mirror of examples/write_wire.rs (single grid, single chunk — fully
159 // deterministic), extended to 3 bricks/2 wires: a boolean NOT gate feeds
160 // one input of an AND gate, whose output feeds a rerouter.
161 let mut world = World::new();
162 world.register_all_components();
163 world.meta.bundle.description = "Wire fixture".to_string();
164
165 let (a, a_id) = Brick {
166 position: (30, 0, 1).into(),
167 color: (255, 0, 0).into(),
168 asset: assets::bricks::B_REROUTE,
169 ..Default::default()
170 }
171 .with_component(assets::components::Rerouter)
172 .with_id_split();
173 let (b, b_id) = Brick {
174 position: (15, 0, 1).into(),
175 color: (0, 255, 0).into(),
176 asset: assets::components::LogicGate::BoolAnd.brick(),
177 ..Default::default()
178 }
179 .with_component(assets::components::LogicGate::BoolAnd.component())
180 .with_id_split();
181 let (c, c_id) = Brick {
182 position: (0, 0, 1).into(),
183 color: (0, 0, 255).into(),
184 asset: assets::components::LogicGate::BoolNot.brick(),
185 ..Default::default()
186 }
187 .with_component(assets::components::LogicGate::BoolNot.component())
188 .with_id_split();
189
190 world.add_bricks([a, b, c]);
191 // Wire 1: NOT.output -> AND.inputA
192 world.add_wire_connection(
193 assets::components::LogicGate::BoolNot.output_of(c_id),
194 assets::components::LogicGate::BoolAnd.input_a_of(b_id),
195 );
196 // Wire 2: AND.output -> Rerouter.input
197 world.add_wire_connection(
198 assets::components::LogicGate::BoolAnd.output_of(b_id),
199 assets::components::Rerouter::input_of(a_id),
200 );
201
202 world
203}
204
205fn components_world() -> World {
206 // Single grid, single chunk (all positions < 2048) — fully deterministic.
207 // register_all_components() embeds the full component catalog so every
208 // type below (light/interact/wiregraph-pseudo/expr) resolves; each
209 // component below carries non-default property values, and #4/#5 exercise
210 // a WireGraphVariant-typed property (BufferTicks' Input/Output, and the
211 // Constant gate's Value).
212 let mut world = World::new();
213 world.register_all_components();
214 world.meta.bundle.description = "Component fixture".to_string();
215
216 // 1: Point light — non-default brightness/radius/color, decoupled from
217 // brick color (bUseBrickColor: false).
218 world.bricks.push(
219 Brick {
220 position: (0, 0, 6).into(),
221 color: (255, 255, 255).into(),
222 ..Default::default()
223 }
224 .with_component(assets::LiteralComponent::new("Component_PointLight").with_data([
225 ("bMatchBrickShape", Box::new(false) as Box<dyn AsBrdbValue>),
226 ("bEnabled", Box::new(true)),
227 ("Brightness", Box::new(500.0f32)),
228 ("Radius", Box::new(800.0f32)),
229 (
230 "Color",
231 Box::new(SavedBrickColor { r: 10, g: 20, b: 30, a: 255 }),
232 ),
233 ("bUseBrickColor", Box::new(false)),
234 ("bCastShadows", Box::new(true)),
235 ])),
236 );
237
238 // 2: Spot light — narrow cone, non-default brightness/color.
239 world.bricks.push(
240 Brick {
241 position: (20, 0, 6).into(),
242 color: (255, 255, 0).into(),
243 ..Default::default()
244 }
245 .with_component(assets::LiteralComponent::new("Component_SpotLight").with_data([
246 ("InnerConeAngle", Box::new(15.0f32) as Box<dyn AsBrdbValue>),
247 ("OuterConeAngle", Box::new(45.0f32)),
248 ("bEnabled", Box::new(true)),
249 ("Brightness", Box::new(300.0f32)),
250 ("Radius", Box::new(600.0f32)),
251 (
252 "Color",
253 Box::new(SavedBrickColor { r: 255, g: 0, b: 0, a: 255 }),
254 ),
255 ("bUseBrickColor", Box::new(false)),
256 ("bCastShadows", Box::new(true)),
257 ])),
258 );
259
260 // 3: Interact — custom prompt text, hidden interaction.
261 world.bricks.push(
262 Brick {
263 position: (40, 0, 6).into(),
264 color: (0, 255, 255).into(),
265 ..Default::default()
266 }
267 .with_component(assets::LiteralComponent::new("Component_Interact").with_data([
268 (
269 "Message",
270 Box::new("You interacted!".to_string()) as Box<dyn AsBrdbValue>,
271 ),
272 ("ConsoleTag", Box::new("fixture_interact".to_string())),
273 ("bAllowNearbyInteraction", Box::new(false)),
274 ("bHiddenInteraction", Box::new(true)),
275 ("PromptCustomLabel", Box::new("Open Door".to_string())),
276 ])),
277 );
278
279 // 4: Buffer (ticks) — WireGraphPseudo component whose Input/Output are
280 // WireGraphVariant; non-default counters plus a Number/Bool variant pair.
281 world.bricks.push(
282 Brick {
283 position: (60, 0, 1).into(),
284 color: (128, 0, 128).into(),
285 asset: assets::components::BufferTicks::default().brick(),
286 ..Default::default()
287 }
288 .with_component(assets::components::BufferTicks {
289 current_ticks: 3,
290 ticks_to_wait: 10,
291 input: WireVariant::Number(2.5),
292 output: WireVariant::Bool(true),
293 }),
294 );
295
296 // 5: Blend gate — WireGraph_Expr_MathBlend's InputA/InputB are each a
297 // WireGraphPrimMathVariant (here an f64 and an i64 tag, showing the
298 // variant is polymorphic per-port); Blend itself is a plain f64.
299 world.bricks.push(
300 Brick {
301 position: (80, 0, 1).into(),
302 color: (0, 128, 0).into(),
303 asset: assets::components::LogicGate::Blend.brick(),
304 ..Default::default()
305 }
306 .with_component(assets::components::LogicGate::Blend.component_with_overrides(
307 HashMap::from([
308 (
309 "InputA".into(),
310 Box::new(WireVariant::Number(10.0)) as Box<dyn AsBrdbValue>,
311 ),
312 ("InputB".into(), Box::new(WireVariant::Int(7))),
313 ("Blend".into(), Box::new(0.75f64)),
314 ]),
315 )),
316 );
317
318 world
319}
320
321fn entities_world() -> World {
322 // Mirror of examples/write_entity.rs's floating sub-grid — the first
323 // grid added after the always-present main grid 1 gets persistent index
324 // 2, so it lands at Grids/2 — plus a couple of main-grid (Grids/1)
325 // bricks. Both grids are single-chunk; note the *outer* Grids/1 vs
326 // Grids/2 folder order comes from a HashMap<usize, UnsavedGrid> in the
327 // writer and is NOT guaranteed stable run-to-run (see stability notes).
328 //
329 // register_all_components() is required here (matching
330 // test_write_entity_save, NOT the plain write_entity.rs example): without
331 // it, Entity_DynamicBrickGrid's class name is never registered and the
332 // write fails with `UnknownType("Entity_DynamicBrickGrid")` — confirmed
333 // by running the crate's own unmodified write_entity example.
334 let mut world = World::new();
335 world.register_all_components();
336 world.meta.bundle.description = "Entity fixture".to_string();
337
338 world.bricks.push(Brick {
339 position: (0, 0, 6).into(),
340 color: (200, 50, 50).into(),
341 ..Default::default()
342 });
343 world.bricks.push(Brick {
344 position: (20, 0, 6).into(),
345 color: (50, 200, 50).into(),
346 ..Default::default()
347 });
348
349 world.add_brick_grid(
350 Entity {
351 frozen: true,
352 location: (0.0, 0.0, 40.0).into(),
353 ..Default::default()
354 },
355 [Brick {
356 position: (0, 0, 3).into(),
357 color: (0, 255, 0).into(),
358 ..Default::default()
359 }],
360 );
361
362 world
363}
364
365fn spawner_world() -> World {
366 // Prefab-embedding fixture: an outer prefab whose spawner gate references
367 // an inner single-brick prefab embedded at Prefabs/Uploads/<BLAKE3>.brz.
368 // Single grid, single chunk, one insertion-ordered prefab map entry —
369 // fully deterministic. The inner archive is written raw (no zstd) so the
370 // embedded bytes are cross-language reproducible.
371 let mut inner = World::new();
372 inner.meta.bundle.description = "Inner prefab".to_string();
373 inner.bricks.push(Brick {
374 position: (0, 0, 6).into(),
375 color: (255, 0, 0).into(),
376 ..Default::default()
377 });
378 inner.make_prefab();
379 let inner_bytes = {
380 let pending = inner.to_unsaved().unwrap().to_pending().unwrap();
381 let mut buf = Vec::new();
382 pending
383 .to_brz_data(None)
384 .unwrap()
385 .write(&mut buf, None)
386 .unwrap();
387 buf
388 };
389
390 let mut world = World::new();
391 world.register_all_components();
392 world.meta.bundle.description = "Spawner fixture".to_string();
393 let prefab_path = world.add_prefab(inner_bytes);
394 world.bricks.push(
395 Brick {
396 asset: brdb::BrickType::str("B_1x1_Gate_Exec_PrefabSpawner"),
397 position: (0, 0, 1).into(),
398 ..Default::default()
399 }
400 .with_component(
401 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner")
402 .with_data([(
403 "Prefab",
404 Box::new(prefab_path) as Box<dyn AsBrdbValue>,
405 )]),
406 ),
407 );
408 world.make_prefab();
409 world
410}More examples
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_brick.brdb");
7
8 let mut world = World::new();
9 world.meta.bundle.description = "Example World".to_string();
10 world.bricks.push(Brick {
11 position: (0, 0, 6).into(),
12 color: (255, 0, 0).into(),
13 ..Default::default()
14 });
15
16 world.write_brdb(&path)?;
17
18 let db = Brdb::new(&path)?.into_reader();
19
20 println!("file structure: {}", db.get_fs()?.render());
21
22 let soa = db.brick_chunk_soa(1, (0, 0, 0).into())?;
23 let color = soa.colors_and_alphas[0];
24 assert_eq!(color.r, 255);
25 assert_eq!(color.g, 0);
26 assert_eq!(color.b, 0);
27 assert_eq!(color.a, 5);
28
29 Ok(())
30}5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_entity.brdb");
7
8 // Ensures the memory db can be created without errors
9 let db = Brdb::new(&path)?.into_reader();
10 let mut world = World::new();
11 world.meta.bundle.description = "Example World".to_string();
12 world.add_brick_grid(
13 Entity {
14 frozen: true,
15 location: (0.0, 0.0, 40.0).into(),
16 ..Default::default()
17 },
18 [Brick {
19 position: (0, 0, 3).into(),
20 color: (0, 255, 0).into(),
21 ..Default::default()
22 }],
23 );
24
25 db.save("example world", &world)?;
26
27 println!("{}", db.get_fs()?.render());
28
29 Ok(())
30}5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_brick.brz");
7
8 let mut world = World::new();
9 world.meta.bundle.description = "Example World".to_string();
10 world.bricks.push(Brick {
11 position: (0, 0, 6).into(),
12 color: (255, 0, 0).into(),
13 ..Default::default()
14 });
15
16 if path.exists() {
17 std::fs::remove_file(&path)?;
18 }
19 world.write_brz(&path)?;
20
21 let db = Brz::new(&path)?.into_reader();
22
23 println!("{}", db.get_fs()?.render());
24
25 let soa = db.brick_chunk_soa(1, (0, 0, 0).into())?;
26 let color = soa.colors_and_alphas[0];
27 assert_eq!(color.r, 255);
28 assert_eq!(color.g, 0);
29 assert_eq!(color.b, 0);
30 assert_eq!(color.a, 5);
31
32 Ok(())
33}5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_prefab.brz");
7
8 let mut world = World::new();
9 // A single 1x1 plate-ish brick (half-extent 5,5,2) at the origin so the
10 // bounds match the hand-captured reference prefab.
11 world.bricks.push(Brick {
12 asset: BrickType::Procedural {
13 asset: assets::bricks::PB_DEFAULT_BRICK.into(),
14 size: BrickSize { x: 5, y: 5, z: 2 },
15 },
16 position: (0, 0, 0).into(),
17 ..Default::default()
18 });
19
20 world.make_prefab();
21 println!(
22 "Prefab.json:\n{}",
23 serde_json::to_string_pretty(world.meta.prefab.as_ref().unwrap())?
24 );
25 println!(
26 "Bundle.json:\n{}",
27 serde_json::to_string_pretty(&world.meta.bundle)?
28 );
29
30 if path.exists() {
31 std::fs::remove_file(&path)?;
32 }
33 world.write_brz(&path)?;
34 println!("wrote {}", path.display());
35 Ok(())
36}5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_wire.brdb");
7
8 // Ensures the memory db can be created without errors
9 let db = Brdb::new(&path)?.into_reader();
10 let mut world = World::new();
11 // Register the built-in component type/struct mappings so the gate and
12 // rerouter component types resolve when writing.
13 world.register_all_components();
14 world.meta.bundle.description = "Example World".to_string();
15
16 let (a, a_id) = Brick {
17 position: (0, 0, 1).into(),
18 color: (255, 0, 0).into(),
19 asset: assets::bricks::B_REROUTE,
20 ..Default::default()
21 }
22 .with_component(assets::components::Rerouter)
23 .with_id_split();
24 let (b, b_id) = Brick {
25 position: (15, 0, 1).into(),
26 color: (255, 0, 0).into(),
27 asset: assets::components::LogicGate::BoolNot.brick(),
28 ..Default::default()
29 }
30 .with_component(assets::components::LogicGate::BoolNot.component())
31 .with_id_split();
32
33 world.add_bricks([a, b]);
34 world.add_wire_connection(
35 assets::components::LogicGate::BoolNot.output_of(b_id),
36 assets::components::Rerouter::input_of(a_id),
37 );
38
39 db.save("example world", &world)?;
40
41 println!("{}", db.get_fs()?.render());
42
43 Ok(())
44}Sourcepub fn write_brdb(&self, path: impl AsRef<Path>) -> Result<(), BrError>
pub fn write_brdb(&self, path: impl AsRef<Path>) -> Result<(), BrError>
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_brick.brdb");
7
8 let mut world = World::new();
9 world.meta.bundle.description = "Example World".to_string();
10 world.bricks.push(Brick {
11 position: (0, 0, 6).into(),
12 color: (255, 0, 0).into(),
13 ..Default::default()
14 });
15
16 world.write_brdb(&path)?;
17
18 let db = Brdb::new(&path)?.into_reader();
19
20 println!("file structure: {}", db.get_fs()?.render());
21
22 let soa = db.brick_chunk_soa(1, (0, 0, 0).into())?;
23 let color = soa.colors_and_alphas[0];
24 assert_eq!(color.r, 255);
25 assert_eq!(color.g, 0);
26 assert_eq!(color.b, 0);
27 assert_eq!(color.a, 5);
28
29 Ok(())
30}Sourcepub fn write_brz(&self, path: impl AsRef<Path>) -> Result<(), BrError>
pub fn write_brz(&self, path: impl AsRef<Path>) -> Result<(), BrError>
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_brick.brz");
7
8 let mut world = World::new();
9 world.meta.bundle.description = "Example World".to_string();
10 world.bricks.push(Brick {
11 position: (0, 0, 6).into(),
12 color: (255, 0, 0).into(),
13 ..Default::default()
14 });
15
16 if path.exists() {
17 std::fs::remove_file(&path)?;
18 }
19 world.write_brz(&path)?;
20
21 let db = Brz::new(&path)?.into_reader();
22
23 println!("{}", db.get_fs()?.render());
24
25 let soa = db.brick_chunk_soa(1, (0, 0, 0).into())?;
26 let color = soa.colors_and_alphas[0];
27 assert_eq!(color.r, 255);
28 assert_eq!(color.g, 0);
29 assert_eq!(color.b, 0);
30 assert_eq!(color.a, 5);
31
32 Ok(())
33}More examples
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_prefab.brz");
7
8 let mut world = World::new();
9 // A single 1x1 plate-ish brick (half-extent 5,5,2) at the origin so the
10 // bounds match the hand-captured reference prefab.
11 world.bricks.push(Brick {
12 asset: BrickType::Procedural {
13 asset: assets::bricks::PB_DEFAULT_BRICK.into(),
14 size: BrickSize { x: 5, y: 5, z: 2 },
15 },
16 position: (0, 0, 0).into(),
17 ..Default::default()
18 });
19
20 world.make_prefab();
21 println!(
22 "Prefab.json:\n{}",
23 serde_json::to_string_pretty(world.meta.prefab.as_ref().unwrap())?
24 );
25 println!(
26 "Bundle.json:\n{}",
27 serde_json::to_string_pretty(&world.meta.bundle)?
28 );
29
30 if path.exists() {
31 std::fs::remove_file(&path)?;
32 }
33 world.write_brz(&path)?;
34 println!("wrote {}", path.display());
35 Ok(())
36}10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 // 1. Build the prefab that gets spawned: a single red brick.
12 let mut prefab = World::new();
13 prefab.meta.bundle.name = "Spawned Brick".to_string();
14 prefab.bricks.push(Brick {
15 position: (0, 0, 6).into(),
16 color: (255, 0, 0).into(),
17 ..Default::default()
18 });
19 prefab.make_prefab();
20 let prefab_bytes = prefab.to_brz_vec()?;
21
22 // 2. Build the outer world holding the button + spawner.
23 let mut world = World::new();
24 // Registers the built-in component/port tables so the Button and
25 // PrefabSpawner component types and their wire ports resolve.
26 world.register_all_components();
27 world.meta.bundle.description = "Button-triggered prefab spawner".to_string();
28
29 // Embed the prefab; the returned path is what the spawner references.
30 let prefab_path = world.add_prefab(prefab_bytes);
31
32 // A pressable button (Component_Button on a 1x1 flat round brick). The
33 // crate exposes brick assets as constants; components it doesn't model as
34 // typed gates (like the button and spawner) are built from string names
35 // via LiteralComponent.
36 let (button, button_id) = Brick {
37 position: (0, 0, 2).into(),
38 color: (0, 255, 0).into(),
39 asset: assets::bricks::B_1X1F_ROUND,
40 ..Default::default()
41 }
42 .with_component(assets::LiteralComponent::new("Component_Button").with_data([(
43 "PromptCustomLabel",
44 Box::new("Spawn Brick".to_string()) as Box<dyn AsBrdbValue>,
45 )]))
46 .with_id_split();
47
48 // The prefab-spawner gate, pointed at the embedded prefab.
49 let (spawner, spawner_id) = Brick {
50 position: (15, 0, 1).into(),
51 color: (0, 0, 255).into(),
52 asset: assets::bricks::B_1X1_GATE_EXEC_PREFAB_SPAWNER,
53 ..Default::default()
54 }
55 .with_component(
56 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner").with_data(
57 [(
58 "Prefab",
59 Box::new(prefab_path.clone()) as Box<dyn AsBrdbValue>,
60 )],
61 ),
62 )
63 .with_id_split();
64
65 world.add_bricks([button, spawner]);
66
67 // Wire the button's held signal into the spawner's Exec input, so a
68 // press fires the spawn.
69 world.add_wire_connection(
70 WirePort::new(button_id, "Component_Button", "bHeld"),
71 WirePort::new(
72 spawner_id,
73 "BrickComponentType_WireGraph_Exec_PrefabSpawner",
74 "Exec",
75 ),
76 );
77
78 // 3. Write it out.
79 let path = PathBuf::from("./example_prefab_spawner.brz");
80 world.write_brz(&path)?;
81 println!("wrote {}", path.display());
82
83 // Read it back to confirm the embedded prefab and wire survived.
84 let reader = Brz::open(&path)?.into_reader();
85 println!("embedded prefab: {}", prefab_path);
86 println!("prefab paths in archive: {:?}", reader.prefab_paths()?);
87 println!("{}", reader.get_fs()?.render());
88
89 Ok(())
90}Sourcepub fn to_brz_vec(&self) -> Result<Vec<u8>, BrError>
pub fn to_brz_vec(&self) -> Result<Vec<u8>, BrError>
Examples found in repository?
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 // 1. Build the prefab that gets spawned: a single red brick.
12 let mut prefab = World::new();
13 prefab.meta.bundle.name = "Spawned Brick".to_string();
14 prefab.bricks.push(Brick {
15 position: (0, 0, 6).into(),
16 color: (255, 0, 0).into(),
17 ..Default::default()
18 });
19 prefab.make_prefab();
20 let prefab_bytes = prefab.to_brz_vec()?;
21
22 // 2. Build the outer world holding the button + spawner.
23 let mut world = World::new();
24 // Registers the built-in component/port tables so the Button and
25 // PrefabSpawner component types and their wire ports resolve.
26 world.register_all_components();
27 world.meta.bundle.description = "Button-triggered prefab spawner".to_string();
28
29 // Embed the prefab; the returned path is what the spawner references.
30 let prefab_path = world.add_prefab(prefab_bytes);
31
32 // A pressable button (Component_Button on a 1x1 flat round brick). The
33 // crate exposes brick assets as constants; components it doesn't model as
34 // typed gates (like the button and spawner) are built from string names
35 // via LiteralComponent.
36 let (button, button_id) = Brick {
37 position: (0, 0, 2).into(),
38 color: (0, 255, 0).into(),
39 asset: assets::bricks::B_1X1F_ROUND,
40 ..Default::default()
41 }
42 .with_component(assets::LiteralComponent::new("Component_Button").with_data([(
43 "PromptCustomLabel",
44 Box::new("Spawn Brick".to_string()) as Box<dyn AsBrdbValue>,
45 )]))
46 .with_id_split();
47
48 // The prefab-spawner gate, pointed at the embedded prefab.
49 let (spawner, spawner_id) = Brick {
50 position: (15, 0, 1).into(),
51 color: (0, 0, 255).into(),
52 asset: assets::bricks::B_1X1_GATE_EXEC_PREFAB_SPAWNER,
53 ..Default::default()
54 }
55 .with_component(
56 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner").with_data(
57 [(
58 "Prefab",
59 Box::new(prefab_path.clone()) as Box<dyn AsBrdbValue>,
60 )],
61 ),
62 )
63 .with_id_split();
64
65 world.add_bricks([button, spawner]);
66
67 // Wire the button's held signal into the spawner's Exec input, so a
68 // press fires the spawn.
69 world.add_wire_connection(
70 WirePort::new(button_id, "Component_Button", "bHeld"),
71 WirePort::new(
72 spawner_id,
73 "BrickComponentType_WireGraph_Exec_PrefabSpawner",
74 "Exec",
75 ),
76 );
77
78 // 3. Write it out.
79 let path = PathBuf::from("./example_prefab_spawner.brz");
80 world.write_brz(&path)?;
81 println!("wrote {}", path.display());
82
83 // Read it back to confirm the embedded prefab and wire survived.
84 let reader = Brz::open(&path)?.into_reader();
85 println!("embedded prefab: {}", prefab_path);
86 println!("prefab paths in archive: {:?}", reader.prefab_paths()?);
87 println!("{}", reader.get_fs()?.render());
88
89 Ok(())
90}Sourcepub fn register_all_components(&mut self)
pub fn register_all_components(&mut self)
Load the full component schema and register all known type→struct mappings and wire port names from the built-in component database.
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_wire.brdb");
7
8 // Ensures the memory db can be created without errors
9 let db = Brdb::new(&path)?.into_reader();
10 let mut world = World::new();
11 // Register the built-in component type/struct mappings so the gate and
12 // rerouter component types resolve when writing.
13 world.register_all_components();
14 world.meta.bundle.description = "Example World".to_string();
15
16 let (a, a_id) = Brick {
17 position: (0, 0, 1).into(),
18 color: (255, 0, 0).into(),
19 asset: assets::bricks::B_REROUTE,
20 ..Default::default()
21 }
22 .with_component(assets::components::Rerouter)
23 .with_id_split();
24 let (b, b_id) = Brick {
25 position: (15, 0, 1).into(),
26 color: (255, 0, 0).into(),
27 asset: assets::components::LogicGate::BoolNot.brick(),
28 ..Default::default()
29 }
30 .with_component(assets::components::LogicGate::BoolNot.component())
31 .with_id_split();
32
33 world.add_bricks([a, b]);
34 world.add_wire_connection(
35 assets::components::LogicGate::BoolNot.output_of(b_id),
36 assets::components::Rerouter::input_of(a_id),
37 );
38
39 db.save("example world", &world)?;
40
41 println!("{}", db.get_fs()?.render());
42
43 Ok(())
44}More examples
157fn wires_world() -> World {
158 // Mirror of examples/write_wire.rs (single grid, single chunk — fully
159 // deterministic), extended to 3 bricks/2 wires: a boolean NOT gate feeds
160 // one input of an AND gate, whose output feeds a rerouter.
161 let mut world = World::new();
162 world.register_all_components();
163 world.meta.bundle.description = "Wire fixture".to_string();
164
165 let (a, a_id) = Brick {
166 position: (30, 0, 1).into(),
167 color: (255, 0, 0).into(),
168 asset: assets::bricks::B_REROUTE,
169 ..Default::default()
170 }
171 .with_component(assets::components::Rerouter)
172 .with_id_split();
173 let (b, b_id) = Brick {
174 position: (15, 0, 1).into(),
175 color: (0, 255, 0).into(),
176 asset: assets::components::LogicGate::BoolAnd.brick(),
177 ..Default::default()
178 }
179 .with_component(assets::components::LogicGate::BoolAnd.component())
180 .with_id_split();
181 let (c, c_id) = Brick {
182 position: (0, 0, 1).into(),
183 color: (0, 0, 255).into(),
184 asset: assets::components::LogicGate::BoolNot.brick(),
185 ..Default::default()
186 }
187 .with_component(assets::components::LogicGate::BoolNot.component())
188 .with_id_split();
189
190 world.add_bricks([a, b, c]);
191 // Wire 1: NOT.output -> AND.inputA
192 world.add_wire_connection(
193 assets::components::LogicGate::BoolNot.output_of(c_id),
194 assets::components::LogicGate::BoolAnd.input_a_of(b_id),
195 );
196 // Wire 2: AND.output -> Rerouter.input
197 world.add_wire_connection(
198 assets::components::LogicGate::BoolAnd.output_of(b_id),
199 assets::components::Rerouter::input_of(a_id),
200 );
201
202 world
203}
204
205fn components_world() -> World {
206 // Single grid, single chunk (all positions < 2048) — fully deterministic.
207 // register_all_components() embeds the full component catalog so every
208 // type below (light/interact/wiregraph-pseudo/expr) resolves; each
209 // component below carries non-default property values, and #4/#5 exercise
210 // a WireGraphVariant-typed property (BufferTicks' Input/Output, and the
211 // Constant gate's Value).
212 let mut world = World::new();
213 world.register_all_components();
214 world.meta.bundle.description = "Component fixture".to_string();
215
216 // 1: Point light — non-default brightness/radius/color, decoupled from
217 // brick color (bUseBrickColor: false).
218 world.bricks.push(
219 Brick {
220 position: (0, 0, 6).into(),
221 color: (255, 255, 255).into(),
222 ..Default::default()
223 }
224 .with_component(assets::LiteralComponent::new("Component_PointLight").with_data([
225 ("bMatchBrickShape", Box::new(false) as Box<dyn AsBrdbValue>),
226 ("bEnabled", Box::new(true)),
227 ("Brightness", Box::new(500.0f32)),
228 ("Radius", Box::new(800.0f32)),
229 (
230 "Color",
231 Box::new(SavedBrickColor { r: 10, g: 20, b: 30, a: 255 }),
232 ),
233 ("bUseBrickColor", Box::new(false)),
234 ("bCastShadows", Box::new(true)),
235 ])),
236 );
237
238 // 2: Spot light — narrow cone, non-default brightness/color.
239 world.bricks.push(
240 Brick {
241 position: (20, 0, 6).into(),
242 color: (255, 255, 0).into(),
243 ..Default::default()
244 }
245 .with_component(assets::LiteralComponent::new("Component_SpotLight").with_data([
246 ("InnerConeAngle", Box::new(15.0f32) as Box<dyn AsBrdbValue>),
247 ("OuterConeAngle", Box::new(45.0f32)),
248 ("bEnabled", Box::new(true)),
249 ("Brightness", Box::new(300.0f32)),
250 ("Radius", Box::new(600.0f32)),
251 (
252 "Color",
253 Box::new(SavedBrickColor { r: 255, g: 0, b: 0, a: 255 }),
254 ),
255 ("bUseBrickColor", Box::new(false)),
256 ("bCastShadows", Box::new(true)),
257 ])),
258 );
259
260 // 3: Interact — custom prompt text, hidden interaction.
261 world.bricks.push(
262 Brick {
263 position: (40, 0, 6).into(),
264 color: (0, 255, 255).into(),
265 ..Default::default()
266 }
267 .with_component(assets::LiteralComponent::new("Component_Interact").with_data([
268 (
269 "Message",
270 Box::new("You interacted!".to_string()) as Box<dyn AsBrdbValue>,
271 ),
272 ("ConsoleTag", Box::new("fixture_interact".to_string())),
273 ("bAllowNearbyInteraction", Box::new(false)),
274 ("bHiddenInteraction", Box::new(true)),
275 ("PromptCustomLabel", Box::new("Open Door".to_string())),
276 ])),
277 );
278
279 // 4: Buffer (ticks) — WireGraphPseudo component whose Input/Output are
280 // WireGraphVariant; non-default counters plus a Number/Bool variant pair.
281 world.bricks.push(
282 Brick {
283 position: (60, 0, 1).into(),
284 color: (128, 0, 128).into(),
285 asset: assets::components::BufferTicks::default().brick(),
286 ..Default::default()
287 }
288 .with_component(assets::components::BufferTicks {
289 current_ticks: 3,
290 ticks_to_wait: 10,
291 input: WireVariant::Number(2.5),
292 output: WireVariant::Bool(true),
293 }),
294 );
295
296 // 5: Blend gate — WireGraph_Expr_MathBlend's InputA/InputB are each a
297 // WireGraphPrimMathVariant (here an f64 and an i64 tag, showing the
298 // variant is polymorphic per-port); Blend itself is a plain f64.
299 world.bricks.push(
300 Brick {
301 position: (80, 0, 1).into(),
302 color: (0, 128, 0).into(),
303 asset: assets::components::LogicGate::Blend.brick(),
304 ..Default::default()
305 }
306 .with_component(assets::components::LogicGate::Blend.component_with_overrides(
307 HashMap::from([
308 (
309 "InputA".into(),
310 Box::new(WireVariant::Number(10.0)) as Box<dyn AsBrdbValue>,
311 ),
312 ("InputB".into(), Box::new(WireVariant::Int(7))),
313 ("Blend".into(), Box::new(0.75f64)),
314 ]),
315 )),
316 );
317
318 world
319}
320
321fn entities_world() -> World {
322 // Mirror of examples/write_entity.rs's floating sub-grid — the first
323 // grid added after the always-present main grid 1 gets persistent index
324 // 2, so it lands at Grids/2 — plus a couple of main-grid (Grids/1)
325 // bricks. Both grids are single-chunk; note the *outer* Grids/1 vs
326 // Grids/2 folder order comes from a HashMap<usize, UnsavedGrid> in the
327 // writer and is NOT guaranteed stable run-to-run (see stability notes).
328 //
329 // register_all_components() is required here (matching
330 // test_write_entity_save, NOT the plain write_entity.rs example): without
331 // it, Entity_DynamicBrickGrid's class name is never registered and the
332 // write fails with `UnknownType("Entity_DynamicBrickGrid")` — confirmed
333 // by running the crate's own unmodified write_entity example.
334 let mut world = World::new();
335 world.register_all_components();
336 world.meta.bundle.description = "Entity fixture".to_string();
337
338 world.bricks.push(Brick {
339 position: (0, 0, 6).into(),
340 color: (200, 50, 50).into(),
341 ..Default::default()
342 });
343 world.bricks.push(Brick {
344 position: (20, 0, 6).into(),
345 color: (50, 200, 50).into(),
346 ..Default::default()
347 });
348
349 world.add_brick_grid(
350 Entity {
351 frozen: true,
352 location: (0.0, 0.0, 40.0).into(),
353 ..Default::default()
354 },
355 [Brick {
356 position: (0, 0, 3).into(),
357 color: (0, 255, 0).into(),
358 ..Default::default()
359 }],
360 );
361
362 world
363}
364
365fn spawner_world() -> World {
366 // Prefab-embedding fixture: an outer prefab whose spawner gate references
367 // an inner single-brick prefab embedded at Prefabs/Uploads/<BLAKE3>.brz.
368 // Single grid, single chunk, one insertion-ordered prefab map entry —
369 // fully deterministic. The inner archive is written raw (no zstd) so the
370 // embedded bytes are cross-language reproducible.
371 let mut inner = World::new();
372 inner.meta.bundle.description = "Inner prefab".to_string();
373 inner.bricks.push(Brick {
374 position: (0, 0, 6).into(),
375 color: (255, 0, 0).into(),
376 ..Default::default()
377 });
378 inner.make_prefab();
379 let inner_bytes = {
380 let pending = inner.to_unsaved().unwrap().to_pending().unwrap();
381 let mut buf = Vec::new();
382 pending
383 .to_brz_data(None)
384 .unwrap()
385 .write(&mut buf, None)
386 .unwrap();
387 buf
388 };
389
390 let mut world = World::new();
391 world.register_all_components();
392 world.meta.bundle.description = "Spawner fixture".to_string();
393 let prefab_path = world.add_prefab(inner_bytes);
394 world.bricks.push(
395 Brick {
396 asset: brdb::BrickType::str("B_1x1_Gate_Exec_PrefabSpawner"),
397 position: (0, 0, 1).into(),
398 ..Default::default()
399 }
400 .with_component(
401 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner")
402 .with_data([(
403 "Prefab",
404 Box::new(prefab_path) as Box<dyn AsBrdbValue>,
405 )]),
406 ),
407 );
408 world.make_prefab();
409 world
410}10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 // 1. Build the prefab that gets spawned: a single red brick.
12 let mut prefab = World::new();
13 prefab.meta.bundle.name = "Spawned Brick".to_string();
14 prefab.bricks.push(Brick {
15 position: (0, 0, 6).into(),
16 color: (255, 0, 0).into(),
17 ..Default::default()
18 });
19 prefab.make_prefab();
20 let prefab_bytes = prefab.to_brz_vec()?;
21
22 // 2. Build the outer world holding the button + spawner.
23 let mut world = World::new();
24 // Registers the built-in component/port tables so the Button and
25 // PrefabSpawner component types and their wire ports resolve.
26 world.register_all_components();
27 world.meta.bundle.description = "Button-triggered prefab spawner".to_string();
28
29 // Embed the prefab; the returned path is what the spawner references.
30 let prefab_path = world.add_prefab(prefab_bytes);
31
32 // A pressable button (Component_Button on a 1x1 flat round brick). The
33 // crate exposes brick assets as constants; components it doesn't model as
34 // typed gates (like the button and spawner) are built from string names
35 // via LiteralComponent.
36 let (button, button_id) = Brick {
37 position: (0, 0, 2).into(),
38 color: (0, 255, 0).into(),
39 asset: assets::bricks::B_1X1F_ROUND,
40 ..Default::default()
41 }
42 .with_component(assets::LiteralComponent::new("Component_Button").with_data([(
43 "PromptCustomLabel",
44 Box::new("Spawn Brick".to_string()) as Box<dyn AsBrdbValue>,
45 )]))
46 .with_id_split();
47
48 // The prefab-spawner gate, pointed at the embedded prefab.
49 let (spawner, spawner_id) = Brick {
50 position: (15, 0, 1).into(),
51 color: (0, 0, 255).into(),
52 asset: assets::bricks::B_1X1_GATE_EXEC_PREFAB_SPAWNER,
53 ..Default::default()
54 }
55 .with_component(
56 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner").with_data(
57 [(
58 "Prefab",
59 Box::new(prefab_path.clone()) as Box<dyn AsBrdbValue>,
60 )],
61 ),
62 )
63 .with_id_split();
64
65 world.add_bricks([button, spawner]);
66
67 // Wire the button's held signal into the spawner's Exec input, so a
68 // press fires the spawn.
69 world.add_wire_connection(
70 WirePort::new(button_id, "Component_Button", "bHeld"),
71 WirePort::new(
72 spawner_id,
73 "BrickComponentType_WireGraph_Exec_PrefabSpawner",
74 "Exec",
75 ),
76 );
77
78 // 3. Write it out.
79 let path = PathBuf::from("./example_prefab_spawner.brz");
80 world.write_brz(&path)?;
81 println!("wrote {}", path.display());
82
83 // Read it back to confirm the embedded prefab and wire survived.
84 let reader = Brz::open(&path)?.into_reader();
85 println!("embedded prefab: {}", prefab_path);
86 println!("prefab paths in archive: {:?}", reader.prefab_paths()?);
87 println!("{}", reader.get_fs()?.render());
88
89 Ok(())
90}Sourcepub fn register_used_components(&mut self)
pub fn register_used_components(&mut self)
Register only the components actually used by this world’s bricks,
mirroring how the game embeds a bundle: ComponentsShared.schema and the
global-data component tables carry only the data structs that appear,
not the full catalog (which [register_all_components] embeds).
Call this AFTER all bricks/grids have been added. The component schema starts from the minimal SoA scaffolding and gains each used component’s data struct plus its transitive type dependencies; global-data component type/struct/port tables are rebuilt to match. Entity types are registered in full (the catalog is a single microchip-grid entry).
This keeps generated bundles byte-compatible with what the current game build writes — embedding the stale full catalog can make the game reject the schema (“while building schema: while reading struct count”).
Sourcepub fn register_component_schema(&mut self, schema_str: &str)
pub fn register_component_schema(&mut self, schema_str: &str)
Parse a schema string and merge its definitions.
Sourcepub fn register_component(&mut self, struct_name: &str)
pub fn register_component(&mut self, struct_name: &str)
Pull a single struct from the max schema.
Sourcepub fn brick_bounds(&self) -> Option<(Position, Position)>
pub fn brick_bounds(&self) -> Option<(Position, Position)>
Inclusive axis-aligned bounding box over the main-grid bricks, in brick
units, as (min, max). Returns None if there are no main-grid bricks.
Non-main grids (microchips) are excluded — their bricks live inside an
entity and are offset to the chunk center.
Sourcepub fn make_prefab(&mut self)
pub fn make_prefab(&mut self)
Mark this world’s metadata as a prefab: sets the bundle type to
"Prefab" and fills Meta/Prefab.json with pivots/bounds computed from
the main-grid brick bounding box (see World::brick_bounds). The
write path then emits a prefab bundle (Bundle.json + Prefab.json, plus
the optional Screenshot/Thumbnail; no World.json).
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_prefab.brz");
7
8 let mut world = World::new();
9 // A single 1x1 plate-ish brick (half-extent 5,5,2) at the origin so the
10 // bounds match the hand-captured reference prefab.
11 world.bricks.push(Brick {
12 asset: BrickType::Procedural {
13 asset: assets::bricks::PB_DEFAULT_BRICK.into(),
14 size: BrickSize { x: 5, y: 5, z: 2 },
15 },
16 position: (0, 0, 0).into(),
17 ..Default::default()
18 });
19
20 world.make_prefab();
21 println!(
22 "Prefab.json:\n{}",
23 serde_json::to_string_pretty(world.meta.prefab.as_ref().unwrap())?
24 );
25 println!(
26 "Bundle.json:\n{}",
27 serde_json::to_string_pretty(&world.meta.bundle)?
28 );
29
30 if path.exists() {
31 std::fs::remove_file(&path)?;
32 }
33 world.write_brz(&path)?;
34 println!("wrote {}", path.display());
35 Ok(())
36}More examples
365fn spawner_world() -> World {
366 // Prefab-embedding fixture: an outer prefab whose spawner gate references
367 // an inner single-brick prefab embedded at Prefabs/Uploads/<BLAKE3>.brz.
368 // Single grid, single chunk, one insertion-ordered prefab map entry —
369 // fully deterministic. The inner archive is written raw (no zstd) so the
370 // embedded bytes are cross-language reproducible.
371 let mut inner = World::new();
372 inner.meta.bundle.description = "Inner prefab".to_string();
373 inner.bricks.push(Brick {
374 position: (0, 0, 6).into(),
375 color: (255, 0, 0).into(),
376 ..Default::default()
377 });
378 inner.make_prefab();
379 let inner_bytes = {
380 let pending = inner.to_unsaved().unwrap().to_pending().unwrap();
381 let mut buf = Vec::new();
382 pending
383 .to_brz_data(None)
384 .unwrap()
385 .write(&mut buf, None)
386 .unwrap();
387 buf
388 };
389
390 let mut world = World::new();
391 world.register_all_components();
392 world.meta.bundle.description = "Spawner fixture".to_string();
393 let prefab_path = world.add_prefab(inner_bytes);
394 world.bricks.push(
395 Brick {
396 asset: brdb::BrickType::str("B_1x1_Gate_Exec_PrefabSpawner"),
397 position: (0, 0, 1).into(),
398 ..Default::default()
399 }
400 .with_component(
401 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner")
402 .with_data([(
403 "Prefab",
404 Box::new(prefab_path) as Box<dyn AsBrdbValue>,
405 )]),
406 ),
407 );
408 world.make_prefab();
409 world
410}10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 // 1. Build the prefab that gets spawned: a single red brick.
12 let mut prefab = World::new();
13 prefab.meta.bundle.name = "Spawned Brick".to_string();
14 prefab.bricks.push(Brick {
15 position: (0, 0, 6).into(),
16 color: (255, 0, 0).into(),
17 ..Default::default()
18 });
19 prefab.make_prefab();
20 let prefab_bytes = prefab.to_brz_vec()?;
21
22 // 2. Build the outer world holding the button + spawner.
23 let mut world = World::new();
24 // Registers the built-in component/port tables so the Button and
25 // PrefabSpawner component types and their wire ports resolve.
26 world.register_all_components();
27 world.meta.bundle.description = "Button-triggered prefab spawner".to_string();
28
29 // Embed the prefab; the returned path is what the spawner references.
30 let prefab_path = world.add_prefab(prefab_bytes);
31
32 // A pressable button (Component_Button on a 1x1 flat round brick). The
33 // crate exposes brick assets as constants; components it doesn't model as
34 // typed gates (like the button and spawner) are built from string names
35 // via LiteralComponent.
36 let (button, button_id) = Brick {
37 position: (0, 0, 2).into(),
38 color: (0, 255, 0).into(),
39 asset: assets::bricks::B_1X1F_ROUND,
40 ..Default::default()
41 }
42 .with_component(assets::LiteralComponent::new("Component_Button").with_data([(
43 "PromptCustomLabel",
44 Box::new("Spawn Brick".to_string()) as Box<dyn AsBrdbValue>,
45 )]))
46 .with_id_split();
47
48 // The prefab-spawner gate, pointed at the embedded prefab.
49 let (spawner, spawner_id) = Brick {
50 position: (15, 0, 1).into(),
51 color: (0, 0, 255).into(),
52 asset: assets::bricks::B_1X1_GATE_EXEC_PREFAB_SPAWNER,
53 ..Default::default()
54 }
55 .with_component(
56 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner").with_data(
57 [(
58 "Prefab",
59 Box::new(prefab_path.clone()) as Box<dyn AsBrdbValue>,
60 )],
61 ),
62 )
63 .with_id_split();
64
65 world.add_bricks([button, spawner]);
66
67 // Wire the button's held signal into the spawner's Exec input, so a
68 // press fires the spawn.
69 world.add_wire_connection(
70 WirePort::new(button_id, "Component_Button", "bHeld"),
71 WirePort::new(
72 spawner_id,
73 "BrickComponentType_WireGraph_Exec_PrefabSpawner",
74 "Exec",
75 ),
76 );
77
78 // 3. Write it out.
79 let path = PathBuf::from("./example_prefab_spawner.brz");
80 world.write_brz(&path)?;
81 println!("wrote {}", path.display());
82
83 // Read it back to confirm the embedded prefab and wire survived.
84 let reader = Brz::open(&path)?.into_reader();
85 println!("embedded prefab: {}", prefab_path);
86 println!("prefab paths in archive: {:?}", reader.prefab_paths()?);
87 println!("{}", reader.get_fs()?.render());
88
89 Ok(())
90}Sourcepub fn add_prefab(&mut self, brz_bytes: impl Into<Vec<u8>>) -> String
pub fn add_prefab(&mut self, brz_bytes: impl Into<Vec<u8>>) -> String
Embed a prefab archive, content-addressed the way the game does:
Prefabs/Uploads/<BLAKE3-uppercase-hex>.brz. Returns that path — the
exact string to store in a Prefab component property
(bundle_path_ref), e.g. on BrickComponentType_PrefabSpawn or
BrickComponentType_WireGraph_Exec_PrefabSpawner.
Examples found in repository?
365fn spawner_world() -> World {
366 // Prefab-embedding fixture: an outer prefab whose spawner gate references
367 // an inner single-brick prefab embedded at Prefabs/Uploads/<BLAKE3>.brz.
368 // Single grid, single chunk, one insertion-ordered prefab map entry —
369 // fully deterministic. The inner archive is written raw (no zstd) so the
370 // embedded bytes are cross-language reproducible.
371 let mut inner = World::new();
372 inner.meta.bundle.description = "Inner prefab".to_string();
373 inner.bricks.push(Brick {
374 position: (0, 0, 6).into(),
375 color: (255, 0, 0).into(),
376 ..Default::default()
377 });
378 inner.make_prefab();
379 let inner_bytes = {
380 let pending = inner.to_unsaved().unwrap().to_pending().unwrap();
381 let mut buf = Vec::new();
382 pending
383 .to_brz_data(None)
384 .unwrap()
385 .write(&mut buf, None)
386 .unwrap();
387 buf
388 };
389
390 let mut world = World::new();
391 world.register_all_components();
392 world.meta.bundle.description = "Spawner fixture".to_string();
393 let prefab_path = world.add_prefab(inner_bytes);
394 world.bricks.push(
395 Brick {
396 asset: brdb::BrickType::str("B_1x1_Gate_Exec_PrefabSpawner"),
397 position: (0, 0, 1).into(),
398 ..Default::default()
399 }
400 .with_component(
401 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner")
402 .with_data([(
403 "Prefab",
404 Box::new(prefab_path) as Box<dyn AsBrdbValue>,
405 )]),
406 ),
407 );
408 world.make_prefab();
409 world
410}More examples
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 // 1. Build the prefab that gets spawned: a single red brick.
12 let mut prefab = World::new();
13 prefab.meta.bundle.name = "Spawned Brick".to_string();
14 prefab.bricks.push(Brick {
15 position: (0, 0, 6).into(),
16 color: (255, 0, 0).into(),
17 ..Default::default()
18 });
19 prefab.make_prefab();
20 let prefab_bytes = prefab.to_brz_vec()?;
21
22 // 2. Build the outer world holding the button + spawner.
23 let mut world = World::new();
24 // Registers the built-in component/port tables so the Button and
25 // PrefabSpawner component types and their wire ports resolve.
26 world.register_all_components();
27 world.meta.bundle.description = "Button-triggered prefab spawner".to_string();
28
29 // Embed the prefab; the returned path is what the spawner references.
30 let prefab_path = world.add_prefab(prefab_bytes);
31
32 // A pressable button (Component_Button on a 1x1 flat round brick). The
33 // crate exposes brick assets as constants; components it doesn't model as
34 // typed gates (like the button and spawner) are built from string names
35 // via LiteralComponent.
36 let (button, button_id) = Brick {
37 position: (0, 0, 2).into(),
38 color: (0, 255, 0).into(),
39 asset: assets::bricks::B_1X1F_ROUND,
40 ..Default::default()
41 }
42 .with_component(assets::LiteralComponent::new("Component_Button").with_data([(
43 "PromptCustomLabel",
44 Box::new("Spawn Brick".to_string()) as Box<dyn AsBrdbValue>,
45 )]))
46 .with_id_split();
47
48 // The prefab-spawner gate, pointed at the embedded prefab.
49 let (spawner, spawner_id) = Brick {
50 position: (15, 0, 1).into(),
51 color: (0, 0, 255).into(),
52 asset: assets::bricks::B_1X1_GATE_EXEC_PREFAB_SPAWNER,
53 ..Default::default()
54 }
55 .with_component(
56 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner").with_data(
57 [(
58 "Prefab",
59 Box::new(prefab_path.clone()) as Box<dyn AsBrdbValue>,
60 )],
61 ),
62 )
63 .with_id_split();
64
65 world.add_bricks([button, spawner]);
66
67 // Wire the button's held signal into the spawner's Exec input, so a
68 // press fires the spawn.
69 world.add_wire_connection(
70 WirePort::new(button_id, "Component_Button", "bHeld"),
71 WirePort::new(
72 spawner_id,
73 "BrickComponentType_WireGraph_Exec_PrefabSpawner",
74 "Exec",
75 ),
76 );
77
78 // 3. Write it out.
79 let path = PathBuf::from("./example_prefab_spawner.brz");
80 world.write_brz(&path)?;
81 println!("wrote {}", path.display());
82
83 // Read it back to confirm the embedded prefab and wire survived.
84 let reader = Brz::open(&path)?.into_reader();
85 println!("embedded prefab: {}", prefab_path);
86 println!("prefab paths in archive: {:?}", reader.prefab_paths()?);
87 println!("{}", reader.get_fs()?.render());
88
89 Ok(())
90}Sourcepub fn add_prefab_world(&mut self, world: &World) -> Result<String, BrError>
pub fn add_prefab_world(&mut self, world: &World) -> Result<String, BrError>
Serialize world to an in-memory .brz and embed it as a prefab.
Sourcepub fn to_unsaved(&self) -> Result<UnsavedFs, BrError>
pub fn to_unsaved(&self) -> Result<UnsavedFs, BrError>
Examples found in repository?
365fn spawner_world() -> World {
366 // Prefab-embedding fixture: an outer prefab whose spawner gate references
367 // an inner single-brick prefab embedded at Prefabs/Uploads/<BLAKE3>.brz.
368 // Single grid, single chunk, one insertion-ordered prefab map entry —
369 // fully deterministic. The inner archive is written raw (no zstd) so the
370 // embedded bytes are cross-language reproducible.
371 let mut inner = World::new();
372 inner.meta.bundle.description = "Inner prefab".to_string();
373 inner.bricks.push(Brick {
374 position: (0, 0, 6).into(),
375 color: (255, 0, 0).into(),
376 ..Default::default()
377 });
378 inner.make_prefab();
379 let inner_bytes = {
380 let pending = inner.to_unsaved().unwrap().to_pending().unwrap();
381 let mut buf = Vec::new();
382 pending
383 .to_brz_data(None)
384 .unwrap()
385 .write(&mut buf, None)
386 .unwrap();
387 buf
388 };
389
390 let mut world = World::new();
391 world.register_all_components();
392 world.meta.bundle.description = "Spawner fixture".to_string();
393 let prefab_path = world.add_prefab(inner_bytes);
394 world.bricks.push(
395 Brick {
396 asset: brdb::BrickType::str("B_1x1_Gate_Exec_PrefabSpawner"),
397 position: (0, 0, 1).into(),
398 ..Default::default()
399 }
400 .with_component(
401 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner")
402 .with_data([(
403 "Prefab",
404 Box::new(prefab_path) as Box<dyn AsBrdbValue>,
405 )]),
406 ),
407 );
408 world.make_prefab();
409 world
410}
411
412fn hash_archive(path: &PathBuf) -> Result<BTreeMap<String, serde_json::Value>, Box<dyn std::error::Error>> {
413 fn collect(fs: &BrFs, prefix: &str, out: &mut Vec<(String, Option<i64>)>) {
414 match fs {
415 BrFs::Root(children) => for (n, c) in children { collect(c, n, out); },
416 BrFs::Folder(_, children) => for (n, c) in children {
417 collect(c, &format!("{prefix}/{n}"), out);
418 },
419 BrFs::File(f) => out.push((prefix.to_string(), f.content_id)),
420 }
421 }
422 let reader = Brz::open(path)?.into_reader();
423 let reader = &*reader;
424 let mut files = Vec::new();
425 collect(&reader.get_fs()?, "", &mut files);
426 let mut out = BTreeMap::new();
427 for (p, content_id) in files {
428 let content = match content_id {
429 Some(id) => reader.find_blob(id)?.read()?,
430 None => Vec::new(),
431 };
432 out.insert(p, serde_json::json!({
433 "blake3": blake3::hash(&content).to_hex().to_string(),
434 "len": content.len(),
435 }));
436 }
437 Ok(out)
438}
439
440fn main() -> Result<(), Box<dyn std::error::Error>> {
441 let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fixtures");
442 fs::create_dir_all(dir.join("schemas"))?;
443
444 let mut hashes = BTreeMap::new();
445 for (name, world) in [
446 ("brick", brick_world()),
447 ("features", features_world()),
448 ("chunks", chunks_world()),
449 ("wires", wires_world()),
450 ("components", components_world()),
451 ("entities", entities_world()),
452 ("spawner", spawner_world()),
453 ] {
454 let pending = world.to_unsaved()?.to_pending()?;
455 // raw variant: no zstd anywhere — byte-comparable across languages
456 let raw_path = dir.join(format!("{name}_raw.brz"));
457 let mut f = fs::File::create(&raw_path)?;
458 pending.clone().to_brz_data(None)?.write(&mut f, None)?;
459 // compressed variant: zstd level 14 (matches Brz::save)
460 let mut f = fs::File::create(dir.join(format!("{name}.brz")))?;
461 pending.to_brz_data(Some(14))?.write(&mut f, Some(14))?;
462
463 // .brdb variant: content parity only (the .brdb container is not
464 // byte-deterministic across runs).
465 let db_path = dir.join(format!("{name}.brdb"));
466 let _ = fs::remove_file(&db_path);
467 Brdb::create(&db_path)?.save("Fixture", &world)?;
468
469 hashes.insert(name.to_string(), hash_archive(&raw_path)?);
470 }
471 fs::write(dir.join("hashes.json"), serde_json::to_string_pretty(&hashes)?)?;
472
473 // The nine embedded schemas as binary msgpack (the exact bytes the
474 // writer embeds as *.schema files inside archives).
475 for (name, schema) in [
476 ("BRSavedGlobalDataSoA", schemas::global_data_schema()),
477 ("BRSavedOwnerTableSoA", schemas::owners_schema()),
478 ("BRSavedBrickChunkIndexSoA", schemas::bricks_chunk_index_schema()),
479 ("BRSavedBrickChunkSoA", schemas::bricks_chunks_schema()),
480 ("BRSavedWireChunkSoA", schemas::bricks_wires_schema()),
481 ("BRSavedComponentChunkSoA", schemas::bricks_components_schema_min()),
482 ("BRSavedComponentChunkSoA_max", schemas::bricks_components_schema_max()),
483 ("BRSavedEntityChunkIndexSoA", schemas::entities_chunk_index_schema()),
484 ("BRSavedEntityChunkSoA", schemas::entities_chunks_schema()),
485 ] {
486 fs::write(dir.join(format!("schemas/{name}.bin")), schema.to_bytes()?)?;
487 }
488 eprintln!("fixtures written to {}", dir.display());
489 Ok(())
490}Sourcepub fn add_bricks(&mut self, bricks: impl IntoIterator<Item = Brick>)
pub fn add_bricks(&mut self, bricks: impl IntoIterator<Item = Brick>)
Add multiple bricks to the world
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_wire.brdb");
7
8 // Ensures the memory db can be created without errors
9 let db = Brdb::new(&path)?.into_reader();
10 let mut world = World::new();
11 // Register the built-in component type/struct mappings so the gate and
12 // rerouter component types resolve when writing.
13 world.register_all_components();
14 world.meta.bundle.description = "Example World".to_string();
15
16 let (a, a_id) = Brick {
17 position: (0, 0, 1).into(),
18 color: (255, 0, 0).into(),
19 asset: assets::bricks::B_REROUTE,
20 ..Default::default()
21 }
22 .with_component(assets::components::Rerouter)
23 .with_id_split();
24 let (b, b_id) = Brick {
25 position: (15, 0, 1).into(),
26 color: (255, 0, 0).into(),
27 asset: assets::components::LogicGate::BoolNot.brick(),
28 ..Default::default()
29 }
30 .with_component(assets::components::LogicGate::BoolNot.component())
31 .with_id_split();
32
33 world.add_bricks([a, b]);
34 world.add_wire_connection(
35 assets::components::LogicGate::BoolNot.output_of(b_id),
36 assets::components::Rerouter::input_of(a_id),
37 );
38
39 db.save("example world", &world)?;
40
41 println!("{}", db.get_fs()?.render());
42
43 Ok(())
44}More examples
157fn wires_world() -> World {
158 // Mirror of examples/write_wire.rs (single grid, single chunk — fully
159 // deterministic), extended to 3 bricks/2 wires: a boolean NOT gate feeds
160 // one input of an AND gate, whose output feeds a rerouter.
161 let mut world = World::new();
162 world.register_all_components();
163 world.meta.bundle.description = "Wire fixture".to_string();
164
165 let (a, a_id) = Brick {
166 position: (30, 0, 1).into(),
167 color: (255, 0, 0).into(),
168 asset: assets::bricks::B_REROUTE,
169 ..Default::default()
170 }
171 .with_component(assets::components::Rerouter)
172 .with_id_split();
173 let (b, b_id) = Brick {
174 position: (15, 0, 1).into(),
175 color: (0, 255, 0).into(),
176 asset: assets::components::LogicGate::BoolAnd.brick(),
177 ..Default::default()
178 }
179 .with_component(assets::components::LogicGate::BoolAnd.component())
180 .with_id_split();
181 let (c, c_id) = Brick {
182 position: (0, 0, 1).into(),
183 color: (0, 0, 255).into(),
184 asset: assets::components::LogicGate::BoolNot.brick(),
185 ..Default::default()
186 }
187 .with_component(assets::components::LogicGate::BoolNot.component())
188 .with_id_split();
189
190 world.add_bricks([a, b, c]);
191 // Wire 1: NOT.output -> AND.inputA
192 world.add_wire_connection(
193 assets::components::LogicGate::BoolNot.output_of(c_id),
194 assets::components::LogicGate::BoolAnd.input_a_of(b_id),
195 );
196 // Wire 2: AND.output -> Rerouter.input
197 world.add_wire_connection(
198 assets::components::LogicGate::BoolAnd.output_of(b_id),
199 assets::components::Rerouter::input_of(a_id),
200 );
201
202 world
203}10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 // 1. Build the prefab that gets spawned: a single red brick.
12 let mut prefab = World::new();
13 prefab.meta.bundle.name = "Spawned Brick".to_string();
14 prefab.bricks.push(Brick {
15 position: (0, 0, 6).into(),
16 color: (255, 0, 0).into(),
17 ..Default::default()
18 });
19 prefab.make_prefab();
20 let prefab_bytes = prefab.to_brz_vec()?;
21
22 // 2. Build the outer world holding the button + spawner.
23 let mut world = World::new();
24 // Registers the built-in component/port tables so the Button and
25 // PrefabSpawner component types and their wire ports resolve.
26 world.register_all_components();
27 world.meta.bundle.description = "Button-triggered prefab spawner".to_string();
28
29 // Embed the prefab; the returned path is what the spawner references.
30 let prefab_path = world.add_prefab(prefab_bytes);
31
32 // A pressable button (Component_Button on a 1x1 flat round brick). The
33 // crate exposes brick assets as constants; components it doesn't model as
34 // typed gates (like the button and spawner) are built from string names
35 // via LiteralComponent.
36 let (button, button_id) = Brick {
37 position: (0, 0, 2).into(),
38 color: (0, 255, 0).into(),
39 asset: assets::bricks::B_1X1F_ROUND,
40 ..Default::default()
41 }
42 .with_component(assets::LiteralComponent::new("Component_Button").with_data([(
43 "PromptCustomLabel",
44 Box::new("Spawn Brick".to_string()) as Box<dyn AsBrdbValue>,
45 )]))
46 .with_id_split();
47
48 // The prefab-spawner gate, pointed at the embedded prefab.
49 let (spawner, spawner_id) = Brick {
50 position: (15, 0, 1).into(),
51 color: (0, 0, 255).into(),
52 asset: assets::bricks::B_1X1_GATE_EXEC_PREFAB_SPAWNER,
53 ..Default::default()
54 }
55 .with_component(
56 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner").with_data(
57 [(
58 "Prefab",
59 Box::new(prefab_path.clone()) as Box<dyn AsBrdbValue>,
60 )],
61 ),
62 )
63 .with_id_split();
64
65 world.add_bricks([button, spawner]);
66
67 // Wire the button's held signal into the spawner's Exec input, so a
68 // press fires the spawn.
69 world.add_wire_connection(
70 WirePort::new(button_id, "Component_Button", "bHeld"),
71 WirePort::new(
72 spawner_id,
73 "BrickComponentType_WireGraph_Exec_PrefabSpawner",
74 "Exec",
75 ),
76 );
77
78 // 3. Write it out.
79 let path = PathBuf::from("./example_prefab_spawner.brz");
80 world.write_brz(&path)?;
81 println!("wrote {}", path.display());
82
83 // Read it back to confirm the embedded prefab and wire survived.
84 let reader = Brz::open(&path)?.into_reader();
85 println!("embedded prefab: {}", prefab_path);
86 println!("prefab paths in archive: {:?}", reader.prefab_paths()?);
87 println!("{}", reader.get_fs()?.render());
88
89 Ok(())
90}pub fn add_entity(&mut self, entity: Entity)
Sourcepub fn add_brick_grid(
&mut self,
entity: Entity,
bricks: impl IntoIterator<Item = Brick>,
)
pub fn add_brick_grid( &mut self, entity: Entity, bricks: impl IntoIterator<Item = Brick>, )
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_entity.brdb");
7
8 // Ensures the memory db can be created without errors
9 let db = Brdb::new(&path)?.into_reader();
10 let mut world = World::new();
11 world.meta.bundle.description = "Example World".to_string();
12 world.add_brick_grid(
13 Entity {
14 frozen: true,
15 location: (0.0, 0.0, 40.0).into(),
16 ..Default::default()
17 },
18 [Brick {
19 position: (0, 0, 3).into(),
20 color: (0, 255, 0).into(),
21 ..Default::default()
22 }],
23 );
24
25 db.save("example world", &world)?;
26
27 println!("{}", db.get_fs()?.render());
28
29 Ok(())
30}More examples
321fn entities_world() -> World {
322 // Mirror of examples/write_entity.rs's floating sub-grid — the first
323 // grid added after the always-present main grid 1 gets persistent index
324 // 2, so it lands at Grids/2 — plus a couple of main-grid (Grids/1)
325 // bricks. Both grids are single-chunk; note the *outer* Grids/1 vs
326 // Grids/2 folder order comes from a HashMap<usize, UnsavedGrid> in the
327 // writer and is NOT guaranteed stable run-to-run (see stability notes).
328 //
329 // register_all_components() is required here (matching
330 // test_write_entity_save, NOT the plain write_entity.rs example): without
331 // it, Entity_DynamicBrickGrid's class name is never registered and the
332 // write fails with `UnknownType("Entity_DynamicBrickGrid")` — confirmed
333 // by running the crate's own unmodified write_entity example.
334 let mut world = World::new();
335 world.register_all_components();
336 world.meta.bundle.description = "Entity fixture".to_string();
337
338 world.bricks.push(Brick {
339 position: (0, 0, 6).into(),
340 color: (200, 50, 50).into(),
341 ..Default::default()
342 });
343 world.bricks.push(Brick {
344 position: (20, 0, 6).into(),
345 color: (50, 200, 50).into(),
346 ..Default::default()
347 });
348
349 world.add_brick_grid(
350 Entity {
351 frozen: true,
352 location: (0.0, 0.0, 40.0).into(),
353 ..Default::default()
354 },
355 [Brick {
356 position: (0, 0, 3).into(),
357 color: (0, 255, 0).into(),
358 ..Default::default()
359 }],
360 );
361
362 world
363}Sourcepub fn add_wire(&mut self, conn: WireConnection)
pub fn add_wire(&mut self, conn: WireConnection)
Add a single wire connection to the world
Sourcepub fn add_wires(&mut self, wires: impl IntoIterator<Item = WireConnection>)
pub fn add_wires(&mut self, wires: impl IntoIterator<Item = WireConnection>)
Add multiple wire connections to the world
Sourcepub fn add_wire_connection(&mut self, source: WirePort, target: WirePort)
pub fn add_wire_connection(&mut self, source: WirePort, target: WirePort)
Add a wire connection from one port to another
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let path = PathBuf::from("./example_wire.brdb");
7
8 // Ensures the memory db can be created without errors
9 let db = Brdb::new(&path)?.into_reader();
10 let mut world = World::new();
11 // Register the built-in component type/struct mappings so the gate and
12 // rerouter component types resolve when writing.
13 world.register_all_components();
14 world.meta.bundle.description = "Example World".to_string();
15
16 let (a, a_id) = Brick {
17 position: (0, 0, 1).into(),
18 color: (255, 0, 0).into(),
19 asset: assets::bricks::B_REROUTE,
20 ..Default::default()
21 }
22 .with_component(assets::components::Rerouter)
23 .with_id_split();
24 let (b, b_id) = Brick {
25 position: (15, 0, 1).into(),
26 color: (255, 0, 0).into(),
27 asset: assets::components::LogicGate::BoolNot.brick(),
28 ..Default::default()
29 }
30 .with_component(assets::components::LogicGate::BoolNot.component())
31 .with_id_split();
32
33 world.add_bricks([a, b]);
34 world.add_wire_connection(
35 assets::components::LogicGate::BoolNot.output_of(b_id),
36 assets::components::Rerouter::input_of(a_id),
37 );
38
39 db.save("example world", &world)?;
40
41 println!("{}", db.get_fs()?.render());
42
43 Ok(())
44}More examples
157fn wires_world() -> World {
158 // Mirror of examples/write_wire.rs (single grid, single chunk — fully
159 // deterministic), extended to 3 bricks/2 wires: a boolean NOT gate feeds
160 // one input of an AND gate, whose output feeds a rerouter.
161 let mut world = World::new();
162 world.register_all_components();
163 world.meta.bundle.description = "Wire fixture".to_string();
164
165 let (a, a_id) = Brick {
166 position: (30, 0, 1).into(),
167 color: (255, 0, 0).into(),
168 asset: assets::bricks::B_REROUTE,
169 ..Default::default()
170 }
171 .with_component(assets::components::Rerouter)
172 .with_id_split();
173 let (b, b_id) = Brick {
174 position: (15, 0, 1).into(),
175 color: (0, 255, 0).into(),
176 asset: assets::components::LogicGate::BoolAnd.brick(),
177 ..Default::default()
178 }
179 .with_component(assets::components::LogicGate::BoolAnd.component())
180 .with_id_split();
181 let (c, c_id) = Brick {
182 position: (0, 0, 1).into(),
183 color: (0, 0, 255).into(),
184 asset: assets::components::LogicGate::BoolNot.brick(),
185 ..Default::default()
186 }
187 .with_component(assets::components::LogicGate::BoolNot.component())
188 .with_id_split();
189
190 world.add_bricks([a, b, c]);
191 // Wire 1: NOT.output -> AND.inputA
192 world.add_wire_connection(
193 assets::components::LogicGate::BoolNot.output_of(c_id),
194 assets::components::LogicGate::BoolAnd.input_a_of(b_id),
195 );
196 // Wire 2: AND.output -> Rerouter.input
197 world.add_wire_connection(
198 assets::components::LogicGate::BoolAnd.output_of(b_id),
199 assets::components::Rerouter::input_of(a_id),
200 );
201
202 world
203}10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 // 1. Build the prefab that gets spawned: a single red brick.
12 let mut prefab = World::new();
13 prefab.meta.bundle.name = "Spawned Brick".to_string();
14 prefab.bricks.push(Brick {
15 position: (0, 0, 6).into(),
16 color: (255, 0, 0).into(),
17 ..Default::default()
18 });
19 prefab.make_prefab();
20 let prefab_bytes = prefab.to_brz_vec()?;
21
22 // 2. Build the outer world holding the button + spawner.
23 let mut world = World::new();
24 // Registers the built-in component/port tables so the Button and
25 // PrefabSpawner component types and their wire ports resolve.
26 world.register_all_components();
27 world.meta.bundle.description = "Button-triggered prefab spawner".to_string();
28
29 // Embed the prefab; the returned path is what the spawner references.
30 let prefab_path = world.add_prefab(prefab_bytes);
31
32 // A pressable button (Component_Button on a 1x1 flat round brick). The
33 // crate exposes brick assets as constants; components it doesn't model as
34 // typed gates (like the button and spawner) are built from string names
35 // via LiteralComponent.
36 let (button, button_id) = Brick {
37 position: (0, 0, 2).into(),
38 color: (0, 255, 0).into(),
39 asset: assets::bricks::B_1X1F_ROUND,
40 ..Default::default()
41 }
42 .with_component(assets::LiteralComponent::new("Component_Button").with_data([(
43 "PromptCustomLabel",
44 Box::new("Spawn Brick".to_string()) as Box<dyn AsBrdbValue>,
45 )]))
46 .with_id_split();
47
48 // The prefab-spawner gate, pointed at the embedded prefab.
49 let (spawner, spawner_id) = Brick {
50 position: (15, 0, 1).into(),
51 color: (0, 0, 255).into(),
52 asset: assets::bricks::B_1X1_GATE_EXEC_PREFAB_SPAWNER,
53 ..Default::default()
54 }
55 .with_component(
56 assets::LiteralComponent::new("BrickComponentType_WireGraph_Exec_PrefabSpawner").with_data(
57 [(
58 "Prefab",
59 Box::new(prefab_path.clone()) as Box<dyn AsBrdbValue>,
60 )],
61 ),
62 )
63 .with_id_split();
64
65 world.add_bricks([button, spawner]);
66
67 // Wire the button's held signal into the spawner's Exec input, so a
68 // press fires the spawn.
69 world.add_wire_connection(
70 WirePort::new(button_id, "Component_Button", "bHeld"),
71 WirePort::new(
72 spawner_id,
73 "BrickComponentType_WireGraph_Exec_PrefabSpawner",
74 "Exec",
75 ),
76 );
77
78 // 3. Write it out.
79 let path = PathBuf::from("./example_prefab_spawner.brz");
80 world.write_brz(&path)?;
81 println!("wrote {}", path.display());
82
83 // Read it back to confirm the embedded prefab and wire survived.
84 let reader = Brz::open(&path)?.into_reader();
85 println!("embedded prefab: {}", prefab_path);
86 println!("prefab paths in archive: {:?}", reader.prefab_paths()?);
87 println!("{}", reader.get_fs()?.render());
88
89 Ok(())
90}Sourcepub fn register_microchip_link(&mut self, brick_id: usize, entity_id: usize)
pub fn register_microchip_link(&mut self, brick_id: usize, entity_id: usize)
Register an outer-microchip-brick ↔ inner-grid-entity pairing.
The write path consumes this into
ComponentChunkSoA.microchip_brick_indices /
microchip_brick_grid_references. Most callers get this for free by
going through add_microchip; use this directly only when
constructing the pair manually.
Sourcepub fn add_microchip(
&mut self,
position: Position,
entity_location: Vector3f,
plane_extent: IntVector,
collapsed: bool,
) -> (usize, usize, (Entity, Vec<Brick>))
pub fn add_microchip( &mut self, position: Position, entity_location: Vector3f, plane_extent: IntVector, collapsed: bool, ) -> (usize, usize, (Entity, Vec<Brick>))
Build a microchip: spawns the outer microchip brick on the main grid,
calls register_microchip_link with the pairing, and returns the
outer brick’s id, the grid entity’s id, and the
(Entity, Vec<Brick>) pair the caller populates before pushing to
world.grids.
Typical usage:
let (chip_brick_id, chip_entity_id, mut inner) = world.add_microchip(
Position { x: 0, y: 0, z: 6 },
Vector3f { x: 0.0, y: 0.0, z: 40.0 },
IntVector { x: 14, y: 14, z: 2 },
true, // collapsed
);
inner.1.push(some_gate_brick);
world.grids.push(inner);