pub struct Guid {
pub a: u32,
pub b: u32,
pub c: u32,
pub d: u32,
}Fields§
§a: u32§b: u32§c: u32§d: u32Implementations§
Source§impl Guid
impl Guid
Sourcepub fn uuid(self) -> Uuid
pub fn uuid(self) -> Uuid
Examples found in repository?
examples/world_owner_counts.rs (line 52)
21fn main() -> Result<(), Box<dyn std::error::Error>> {
22 let mut args = std::env::args().into_iter();
23 args.next();
24 let Some(file) = args.next() else {
25 eprintln!("missing world file arg");
26 process::exit(1);
27 };
28
29 let dst = env::current_dir()?.join(PathBuf::from(&file));
30 if !dst.exists() {
31 eprintln!("file {} does not exist", dst.display());
32 process::exit(1);
33 }
34
35 eprintln!("Opening world: {}", path::absolute(&dst)?.display());
36
37 let db = Brdb::open(dst)?.into_reader();
38
39 let owners_soa = db.owners_soa()?.to_value();
40 let owners = OwnerTableSoA::try_from(&owners_soa)?;
41
42 let rows = (0..owners.user_ids.len())
43 .map(|i| {
44 let user_id = &owners.user_ids[i];
45 let display_name = &owners.display_names[i];
46 let user_name = &owners.user_names[i];
47 let entity_count = owners.entity_counts[i];
48 let brick_count = owners.brick_counts[i];
49 let component_count = owners.component_counts[i];
50 let wire_count = owners.wire_counts[i];
51 Row {
52 user_id: user_id.uuid().to_string(),
53 user_name: user_name.clone(),
54 display_name: display_name.clone(),
55 entity_counts: entity_count,
56 brick_counts: brick_count,
57 component_counts: component_count,
58 wire_counts: wire_count,
59 }
60 })
61 .collect::<Vec<_>>();
62 print!("{}", serde_json::to_string_pretty(&rows)?);
63
64 Ok(())
65}More examples
examples/world_owner_tool.rs (line 56)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut args = std::env::args().into_iter().peekable();
8 let cmd = args.next().unwrap();
9 if !args.peek().is_some() {
10 println!("usage: {cmd} show world.brdb");
11 println!("usage: {cmd} apply world.brdb owners.csv");
12 println!(
13 "owners.csv must be `display_name,user_name,user_id,old_user_id` where old_user_id is the one to replace."
14 );
15 process::exit(0);
16 }
17
18 let command = args.next().unwrap();
19 if command != "show" && command != "apply" {
20 eprintln!("unknown command. expected `show` or `apply`");
21 process::exit(1);
22 }
23
24 let Some(file) = args.next() else {
25 eprintln!("missing world file arg");
26 process::exit(1);
27 };
28
29 let dst = PathBuf::from(&file);
30 if !dst.exists() {
31 eprintln!("file {file} does not exist");
32 process::exit(1);
33 }
34
35 let db = Brdb::open(dst)?.into_reader();
36
37 let owners = db.owners_soa()?;
38
39 if command == "show" {
40 if args.peek().is_some() {
41 eprintln!("too many arguments!");
42 process::exit(1);
43 }
44
45 let owners_csv = owners
46 .prop("DisplayNames")?
47 .as_array()?
48 .iter()
49 .zip(owners.prop("UserNames")?.as_array()?.iter())
50 .zip(owners.prop("UserIds")?.as_array()?.iter())
51 .map(|((display_name, user_name), user_id)| {
52 format!(
53 "{},{},{}",
54 display_name.as_str().unwrap(),
55 user_name.as_str().unwrap(),
56 Guid::try_from(user_id).unwrap().uuid(),
57 )
58 })
59 .collect::<Vec<_>>();
60 println!("display_name,user_name,user_id\n{}", owners_csv.join("\n"));
61 } else if command == "apply" {
62 let Some(apply_file) = args.next() else {
63 eprintln!("missing owners csv file arg");
64 process::exit(1);
65 };
66 if args.peek().is_some() {
67 eprintln!("too many arguments!");
68 process::exit(1);
69 }
70
71 let apply_path = PathBuf::from(&apply_file);
72 if !apply_path.exists() {
73 eprintln!("file {apply_file} does not exist");
74 process::exit(1);
75 }
76
77 let mut display_name_index = None;
78 let mut user_name_index = None;
79 let mut user_id_index = None;
80 let mut old_user_id_index = None;
81 let mut apply_data = String::new();
82 File::open(apply_path)?.read_to_string(&mut apply_data)?;
83 let Some((header, rows)) = apply_data.split_once("\n") else {
84 eprintln!("file {apply_file} does not have any rows");
85 process::exit(1);
86 };
87 for (i, key) in header.split(",").enumerate() {
88 match key.trim().to_ascii_lowercase().as_ref() {
89 "display_name" => {
90 display_name_index = Some(i);
91 }
92 "user_name" => {
93 user_name_index = Some(i);
94 }
95 "user_id" => {
96 user_id_index = Some(i);
97 }
98 "old_user_id" => old_user_id_index = Some(i),
99 other => {
100 eprintln!("unknown column {other} in {apply_file}");
101 process::exit(1);
102 }
103 }
104 }
105
106 let missing = [
107 ("display_name", display_name_index.is_none()),
108 ("user_name", user_name_index.is_none()),
109 ("user_id", user_id_index.is_none()),
110 ("old_user_id", old_user_id_index.is_none()),
111 ]
112 .into_iter()
113 .filter_map(|(k, cond)| cond.then_some(k.to_owned()))
114 .collect::<Vec<_>>();
115 if !missing.is_empty() {
116 eprintln!("missing columns: {}", missing.join(","));
117 process::exit(1);
118 }
119
120 let display_name_index = display_name_index.unwrap();
121 let user_name_index = user_name_index.unwrap();
122 let user_id_index = user_id_index.unwrap();
123 let old_user_id_index = old_user_id_index.unwrap();
124
125 // Parse the owners from BrdbValues
126 let mut new_soa = OwnerTableSoA::try_from(&owners.to_value())?;
127 let owners_lut = rows
128 .trim()
129 .split("\n")
130 .map(|r| r.trim().split(",").collect::<Vec<&str>>())
131 .map(|cols| {
132 let user_name = cols[user_name_index];
133 let display_name = cols[display_name_index];
134 let user_id = Uuid::parse_str(&cols[user_id_index])
135 .expect(&format!("invalid uuid: {}", cols[user_id_index]));
136 let old_user_id = Uuid::parse_str(&cols[old_user_id_index])
137 .expect(&format!("invalid old uuid: {}", cols[old_user_id_index]));
138 (old_user_id, (user_name, display_name, user_id))
139 })
140 .collect::<HashMap<_, _>>();
141 println!("{owners_lut:?}");
142
143 let mut changes = 0;
144
145 for i in 0..new_soa.user_ids.len() {
146 let old_id = new_soa.user_ids[i].uuid();
147 let Some((user_name, display_name, user_id)) = owners_lut.get(&old_id) else {
148 println!("missing old id for {old_id} - ignoring");
149 continue;
150 };
151 println!("replacing {old_id} with {user_id} - {user_name} ({display_name})");
152 new_soa.user_names[i] = (*user_name).to_owned();
153 new_soa.display_names[i] = (*display_name).to_owned();
154 new_soa.user_ids[i] = Guid::from_uuid((*user_id).clone());
155 changes += 1;
156 }
157
158 if changes == 0 {
159 println!("world left unchanged");
160 std::process::exit(0);
161 }
162
163 // convert the owners struct of arrays into bytes using the owners schema
164 let content = db.owners_schema()?.write_brdb(OWNER_TABLE_SOA, &new_soa)?;
165
166 let patch = BrPendingFs::Root(vec![(
167 "World".to_owned(),
168 BrPendingFs::Folder(Some(vec![(
169 "0".to_string(),
170 BrPendingFs::Folder(Some(vec![(
171 "Owners.mps".to_string(),
172 BrPendingFs::File(Some(content)),
173 )])),
174 )])),
175 )]);
176 db.write_pending("Replace owners", db.to_pending_patch()?.with_patch(patch)?)?;
177 println!("revision created")
178 }
179
180 Ok(())
181}Sourcepub fn from_uuid(uuid: Uuid) -> Self
pub fn from_uuid(uuid: Uuid) -> Self
Examples found in repository?
examples/write_fixtures.rs (line 38)
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}More examples
examples/world_owner_tool.rs (line 154)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut args = std::env::args().into_iter().peekable();
8 let cmd = args.next().unwrap();
9 if !args.peek().is_some() {
10 println!("usage: {cmd} show world.brdb");
11 println!("usage: {cmd} apply world.brdb owners.csv");
12 println!(
13 "owners.csv must be `display_name,user_name,user_id,old_user_id` where old_user_id is the one to replace."
14 );
15 process::exit(0);
16 }
17
18 let command = args.next().unwrap();
19 if command != "show" && command != "apply" {
20 eprintln!("unknown command. expected `show` or `apply`");
21 process::exit(1);
22 }
23
24 let Some(file) = args.next() else {
25 eprintln!("missing world file arg");
26 process::exit(1);
27 };
28
29 let dst = PathBuf::from(&file);
30 if !dst.exists() {
31 eprintln!("file {file} does not exist");
32 process::exit(1);
33 }
34
35 let db = Brdb::open(dst)?.into_reader();
36
37 let owners = db.owners_soa()?;
38
39 if command == "show" {
40 if args.peek().is_some() {
41 eprintln!("too many arguments!");
42 process::exit(1);
43 }
44
45 let owners_csv = owners
46 .prop("DisplayNames")?
47 .as_array()?
48 .iter()
49 .zip(owners.prop("UserNames")?.as_array()?.iter())
50 .zip(owners.prop("UserIds")?.as_array()?.iter())
51 .map(|((display_name, user_name), user_id)| {
52 format!(
53 "{},{},{}",
54 display_name.as_str().unwrap(),
55 user_name.as_str().unwrap(),
56 Guid::try_from(user_id).unwrap().uuid(),
57 )
58 })
59 .collect::<Vec<_>>();
60 println!("display_name,user_name,user_id\n{}", owners_csv.join("\n"));
61 } else if command == "apply" {
62 let Some(apply_file) = args.next() else {
63 eprintln!("missing owners csv file arg");
64 process::exit(1);
65 };
66 if args.peek().is_some() {
67 eprintln!("too many arguments!");
68 process::exit(1);
69 }
70
71 let apply_path = PathBuf::from(&apply_file);
72 if !apply_path.exists() {
73 eprintln!("file {apply_file} does not exist");
74 process::exit(1);
75 }
76
77 let mut display_name_index = None;
78 let mut user_name_index = None;
79 let mut user_id_index = None;
80 let mut old_user_id_index = None;
81 let mut apply_data = String::new();
82 File::open(apply_path)?.read_to_string(&mut apply_data)?;
83 let Some((header, rows)) = apply_data.split_once("\n") else {
84 eprintln!("file {apply_file} does not have any rows");
85 process::exit(1);
86 };
87 for (i, key) in header.split(",").enumerate() {
88 match key.trim().to_ascii_lowercase().as_ref() {
89 "display_name" => {
90 display_name_index = Some(i);
91 }
92 "user_name" => {
93 user_name_index = Some(i);
94 }
95 "user_id" => {
96 user_id_index = Some(i);
97 }
98 "old_user_id" => old_user_id_index = Some(i),
99 other => {
100 eprintln!("unknown column {other} in {apply_file}");
101 process::exit(1);
102 }
103 }
104 }
105
106 let missing = [
107 ("display_name", display_name_index.is_none()),
108 ("user_name", user_name_index.is_none()),
109 ("user_id", user_id_index.is_none()),
110 ("old_user_id", old_user_id_index.is_none()),
111 ]
112 .into_iter()
113 .filter_map(|(k, cond)| cond.then_some(k.to_owned()))
114 .collect::<Vec<_>>();
115 if !missing.is_empty() {
116 eprintln!("missing columns: {}", missing.join(","));
117 process::exit(1);
118 }
119
120 let display_name_index = display_name_index.unwrap();
121 let user_name_index = user_name_index.unwrap();
122 let user_id_index = user_id_index.unwrap();
123 let old_user_id_index = old_user_id_index.unwrap();
124
125 // Parse the owners from BrdbValues
126 let mut new_soa = OwnerTableSoA::try_from(&owners.to_value())?;
127 let owners_lut = rows
128 .trim()
129 .split("\n")
130 .map(|r| r.trim().split(",").collect::<Vec<&str>>())
131 .map(|cols| {
132 let user_name = cols[user_name_index];
133 let display_name = cols[display_name_index];
134 let user_id = Uuid::parse_str(&cols[user_id_index])
135 .expect(&format!("invalid uuid: {}", cols[user_id_index]));
136 let old_user_id = Uuid::parse_str(&cols[old_user_id_index])
137 .expect(&format!("invalid old uuid: {}", cols[old_user_id_index]));
138 (old_user_id, (user_name, display_name, user_id))
139 })
140 .collect::<HashMap<_, _>>();
141 println!("{owners_lut:?}");
142
143 let mut changes = 0;
144
145 for i in 0..new_soa.user_ids.len() {
146 let old_id = new_soa.user_ids[i].uuid();
147 let Some((user_name, display_name, user_id)) = owners_lut.get(&old_id) else {
148 println!("missing old id for {old_id} - ignoring");
149 continue;
150 };
151 println!("replacing {old_id} with {user_id} - {user_name} ({display_name})");
152 new_soa.user_names[i] = (*user_name).to_owned();
153 new_soa.display_names[i] = (*display_name).to_owned();
154 new_soa.user_ids[i] = Guid::from_uuid((*user_id).clone());
155 changes += 1;
156 }
157
158 if changes == 0 {
159 println!("world left unchanged");
160 std::process::exit(0);
161 }
162
163 // convert the owners struct of arrays into bytes using the owners schema
164 let content = db.owners_schema()?.write_brdb(OWNER_TABLE_SOA, &new_soa)?;
165
166 let patch = BrPendingFs::Root(vec![(
167 "World".to_owned(),
168 BrPendingFs::Folder(Some(vec![(
169 "0".to_string(),
170 BrPendingFs::Folder(Some(vec![(
171 "Owners.mps".to_string(),
172 BrPendingFs::File(Some(content)),
173 )])),
174 )])),
175 )]);
176 db.write_pending("Replace owners", db.to_pending_patch()?.with_patch(patch)?)?;
177 println!("revision created")
178 }
179
180 Ok(())
181}Trait Implementations§
Source§impl AsBrdbValue for Guid
impl AsBrdbValue for Guid
Source§fn as_brdb_struct_prop_value(
&self,
schema: &BrdbSchema,
_struct_name: BrdbInterned,
prop_name: BrdbInterned,
) -> Result<&dyn AsBrdbValue, BrdbSchemaError>
fn as_brdb_struct_prop_value( &self, schema: &BrdbSchema, _struct_name: BrdbInterned, prop_name: BrdbInterned, ) -> Result<&dyn AsBrdbValue, BrdbSchemaError>
Read a specific struct property value from the schema.
fn as_brdb_bool(&self) -> Result<bool, BrdbSchemaError>
fn as_brdb_u8(&self) -> Result<u8, BrdbSchemaError>
fn as_brdb_u16(&self) -> Result<u16, BrdbSchemaError>
fn as_brdb_u32(&self) -> Result<u32, BrdbSchemaError>
fn as_brdb_u64(&self) -> Result<u64, BrdbSchemaError>
fn as_brdb_i8(&self) -> Result<i8, BrdbSchemaError>
fn as_brdb_i16(&self) -> Result<i16, BrdbSchemaError>
fn as_brdb_i32(&self) -> Result<i32, BrdbSchemaError>
fn as_brdb_i64(&self) -> Result<i64, BrdbSchemaError>
fn as_brdb_f32(&self) -> Result<f32, BrdbSchemaError>
fn as_brdb_f64(&self) -> Result<f64, BrdbSchemaError>
fn as_brdb_str(&self) -> Result<&str, BrdbSchemaError>
fn as_brdb_asset( &self, _schema: &BrdbSchema, _ty: &str, ) -> Result<Option<usize>, BrdbSchemaError>
fn as_brdb_enum( &self, _schema: &BrdbSchema, _def: &BrdbSchemaEnum, ) -> Result<i32, BrdbSchemaError>
fn as_brdb_wire_variant(&self) -> Result<WireVariant, BrdbSchemaError>
fn as_brdb_wire_array_variant( &self, ) -> Result<WireArrayVariant, BrdbSchemaError>
fn as_brdb_wire_map_variant(&self) -> Result<WireMapVariant, BrdbSchemaError>
Source§fn as_brdb_variant_member(&self) -> Option<&str>
fn as_brdb_variant_member(&self) -> Option<&str>
When this value should encode as a named member of a schema
variant
(a tagged union whose members are structs, e.g. BRInventoryEntryVariant
-> BRInventoryEntryNothing), return the member struct’s name. The
writer emits uint(tag) + <that struct>. None (the default) means
“not a struct-member variant” and the writer falls back to the wire
map/array/scalar variant paths.Source§fn has_brdb_struct_prop(
&self,
_schema: &BrdbSchema,
_struct_name: BrdbInterned,
_prop_name: BrdbInterned,
) -> bool
fn has_brdb_struct_prop( &self, _schema: &BrdbSchema, _struct_name: BrdbInterned, _prop_name: BrdbInterned, ) -> bool
Cheap presence probe for a struct property. When this returns
false, the schema writer takes the default/zero path directly
instead of paying for a MissingStructField error (two String
allocations) per unset field. Implementations that can’t answer
cheaply keep the default true; the writer then falls back to
the erroring accessors below.Source§fn as_brdb_struct_prop_array(
&self,
_schema: &BrdbSchema,
_struct_name: BrdbInterned,
_prop_name: BrdbInterned,
) -> Result<BrdbArrayIter<'_>, BrdbSchemaError>
fn as_brdb_struct_prop_array( &self, _schema: &BrdbSchema, _struct_name: BrdbInterned, _prop_name: BrdbInterned, ) -> Result<BrdbArrayIter<'_>, BrdbSchemaError>
Get the the number of entries in a struct property.
Source§fn as_brdb_struct_prop_map(
&self,
_schema: &BrdbSchema,
_struct_name: BrdbInterned,
_prop_name: BrdbInterned,
) -> Result<BrdbMapIter<'_>, BrdbSchemaError>
fn as_brdb_struct_prop_map( &self, _schema: &BrdbSchema, _struct_name: BrdbInterned, _prop_name: BrdbInterned, ) -> Result<BrdbMapIter<'_>, BrdbSchemaError>
Get the the number of entries in a struct property.
impl Copy for Guid
impl Eq for Guid
impl StructuralPartialEq for Guid
Auto Trait Implementations§
impl Freeze for Guid
impl RefUnwindSafe for Guid
impl Send for Guid
impl Sync for Guid
impl Unpin for Guid
impl UnsafeUnpin for Guid
impl UnwindSafe for Guid
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Compare self to
key and return true if they are equal.