From 6f7006fcb9a99bb6216c669e72d0e9e749e616e6 Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Thu, 27 Nov 2025 18:44:14 +0100 Subject: [PATCH] improve block to_props --- pumpkin-data/build/block.rs | 61 ++++++++----------- pumpkin-data/src/block_state.rs | 23 +++---- pumpkin-world/src/block/mod.rs | 21 ++++--- pumpkin-world/src/chunk/palette.rs | 9 ++- .../generation/feature/features/coral/mod.rs | 6 +- .../feature/features/tree/trunk/fancy.rs | 8 +-- pumpkin/src/block/fluid/flowing.rs | 2 +- pumpkin/src/item/items/bucket.rs | 4 +- pumpkin/src/item/items/ender_eye.rs | 6 +- pumpkin/src/item/items/ignite/ignition.rs | 13 ++-- pumpkin/src/world/loot.rs | 2 +- pumpkin/src/world/mod.rs | 4 +- 12 files changed, 73 insertions(+), 86 deletions(-) diff --git a/pumpkin-data/build/block.rs b/pumpkin-data/build/block.rs index e96c48349..f1e916427 100644 --- a/pumpkin-data/build/block.rs +++ b/pumpkin-data/build/block.rs @@ -154,7 +154,7 @@ impl ToTokens for PropertyStruct { } } - fn to_value(&self) -> &str { + fn to_value(&self) -> &'static str { match self { #(#to_values),* } @@ -200,26 +200,16 @@ impl ToTokens for BlockPropertyStruct { .map(|(_, id)| *id) .collect::>(); - let to_index_body = self - .data - .variant_mappings - .iter() - .rev() - .map(|entry| { - let field_name = Ident::new_raw(&entry.original_name, Span::call_site()); - match &entry.property_type { - PropertyType::Bool => quote! { - (!self.#field_name as u16, 2) - }, - PropertyType::Enum { name } => { - let enum_ident = Ident::new(name, Span::call_site()); - quote! { - (self.#field_name.to_index(), #enum_ident::variant_count()) - } - } + let to_index_logic = self.data.variant_mappings.iter().rev().map(|entry| { + let field = Ident::new_raw(&entry.original_name, Span::call_site()); + match &entry.property_type { + PropertyType::Bool => quote! { (!self.#field as u16, 2) }, + PropertyType::Enum { name } => { + let ty = Ident::new(name, Span::call_site()); + quote! { (self.#field.to_index(), #ty::variant_count()) } } - }) - .collect::>(); + } + }); let from_index_body = self .data @@ -250,15 +240,15 @@ impl ToTokens for BlockPropertyStruct { }) .collect::>(); - let to_props_values = self.data.variant_mappings.iter().map(|entry| { - let key = &entry.original_name; - let field_name = Ident::new_raw(&entry.original_name, Span::call_site()); + let to_props_entries = self.data.variant_mappings.iter().map(|entry| { + let key_str = &entry.original_name; + let field = Ident::new_raw(&entry.original_name, Span::call_site()); match &entry.property_type { PropertyType::Bool => quote! { - (#key.to_string(), self.#field_name.to_string()), + (#key_str, if self.#field { "true" } else { "false" }) }, - PropertyType::Enum { name: _ } => quote! { - (#key.to_string(), self.#field_name.to_value().to_string()), + PropertyType::Enum { .. } => quote! { + (#key_str, self.#field.to_value()) }, } }); @@ -290,12 +280,10 @@ impl ToTokens for BlockPropertyStruct { } impl BlockProperties for #name { - fn to_index(&self) -> u16 { - let (index, _) = [#(#to_index_body),*] - .iter() - .fold((0, 1), |(current_index, multiplier), &(value, count)| { - (current_index + value * multiplier, multiplier * count) - }); + fn to_index(&self) -> u16 { + let (index, _) = [#(#to_index_logic),*] + .iter() + .fold((0, 1), |(curr, mul), &(val, count)| (curr + val * mul, mul * count)); index } @@ -337,9 +325,10 @@ impl ToTokens for BlockPropertyStruct { Self::from_state_id(block.default_state.id, block) } - fn to_props(&self) -> Box<[(String, String)]> { - [#(#to_props_values)*].into() + fn to_props(&self) -> Vec<(&'static str, &'static str)> { + vec![ #(#to_props_entries),* ] } + fn from_props(props: &[(&str, &str)], block: &Block) -> Self { if ![#(#block_ids),*].contains(&block.id) { panic!("{} is not a valid block for {}", &block.name, #struct_name); @@ -939,7 +928,7 @@ pub(crate) fn build() -> TokenStream { fn default(block: &Block) -> Self where Self: Sized; // Convert properties to a `Vec` of `(name, value)` - fn to_props(&self) -> Box<[(String, String)]>; + fn to_props(&self) -> Vec<(&'static str, &'static str)>; // Convert properties to a block state, and add them onto the default state. fn from_props(props: &[(&str, &str)], block: &Block) -> Self where Self: Sized; @@ -949,7 +938,7 @@ pub(crate) fn build() -> TokenStream { fn variant_count() -> u16; fn to_index(&self) -> u16; fn from_index(index: u16) -> Self; - fn to_value(&self) -> &str; + fn to_value(&self) -> &'static str; fn from_value(value: &str) -> Self; } diff --git a/pumpkin-data/src/block_state.rs b/pumpkin-data/src/block_state.rs index 818e12da1..aaa63bc4c 100644 --- a/pumpkin-data/src/block_state.rs +++ b/pumpkin-data/src/block_state.rs @@ -117,19 +117,20 @@ impl BlockState { .iter() .map(|&id| COLLISION_SHAPES[id as usize]) .collect(); + let block = Block::from_state_id(self.id); - if block.properties(self.id).and_then(|properties| { - properties + if let Some(props) = block.properties(self.id) { + let is_waterlogged = props .to_props() - .into_iter() - .find(|p| p.0 == "waterlogged") - .map(|(_, value)| value == true.to_string()) - }) == Some(true) - { - // If the block is waterlogged, add a water shape - let shape = - &CollisionShape::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 0.875, 1.0)); - shapes.push(*shape); + .iter() + .any(|(k, v)| *k == "waterlogged" && *v == "true"); + + if is_waterlogged { + shapes.push(CollisionShape::new( + Vector3::new(0.0, 0.0, 0.0), + Vector3::new(1.0, 0.875, 1.0), + )); + } } Some(shapes) diff --git a/pumpkin-world/src/block/mod.rs b/pumpkin-world/src/block/mod.rs index f03ec1010..5edc07eb5 100644 --- a/pumpkin-world/src/block/mod.rs +++ b/pumpkin-world/src/block/mod.rs @@ -51,17 +51,18 @@ impl BlockStateCodec { pub fn get_state_id(&self) -> BlockStateId { let block = self.name; - let mut state_id = block.default_state.id; + let properties_map = match &self.properties { + Some(map) => map, + None => return block.default_state.id, + }; - if let Some(properties) = &self.properties { - let props: Vec<(&str, &str)> = properties - .iter() - .map(|(k, v)| (k.as_str(), v.as_str())) - .collect(); - let block_properties = block.from_properties(&props); - state_id = block_properties.to_state_id(block); - } - state_id + let props_iter = properties_map + .iter() + .map(|(k, v)| (k.as_str(), v.as_str())) + .collect::>(); + + let block_properties = block.from_properties(&props_iter); + block_properties.to_state_id(block) } } diff --git a/pumpkin-world/src/chunk/palette.rs b/pumpkin-world/src/chunk/palette.rs index d69e48857..4e8d41126 100644 --- a/pumpkin-world/src/chunk/palette.rs +++ b/pumpkin-world/src/chunk/palette.rs @@ -527,9 +527,12 @@ impl BlockPalette { BlockStateCodec { name: block, - properties: block - .properties(registry_id) - .map(|p| p.to_props().into_iter().collect()), + properties: block.properties(registry_id).map(|p| { + p.to_props() + .into_iter() + .map(|(k, v)| (k.to_owned(), v.to_owned())) + .collect() + }), } } } diff --git a/pumpkin-world/src/generation/feature/features/coral/mod.rs b/pumpkin-world/src/generation/feature/features/coral/mod.rs index 107fcd5c3..339ecaca0 100644 --- a/pumpkin-world/src/generation/feature/features/coral/mod.rs +++ b/pumpkin-world/src/generation/feature/features/coral/mod.rs @@ -62,10 +62,10 @@ impl CoralFeature { let props: Vec<(&str, &str)> = original_props .iter() .map(|(key, value)| { - if key == "facing" { - (key.as_str(), facing.to_value()) + if *key == "facing" { + (*key, facing.to_value()) } else { - (key.as_str(), value.as_str()) + (*key, *value) } }) .collect(); diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/fancy.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/fancy.rs index 5b5eb8864..42ef1b799 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/fancy.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/fancy.rs @@ -150,13 +150,13 @@ impl FancyTrunkPlacer { let original_props = &block.properties(trunk_provider.id).unwrap().to_props(); let axis = axis.to_value(); // Set the right Axis - let props: Vec<(&str, &str)> = original_props + let props: Vec<(&'static str, &'static str)> = original_props .iter() .map(|(key, value)| { - if key == "axis" { - (key.as_str(), axis) + if *key == "axis" { + (*key, axis) } else { - (key.as_str(), value.as_str()) + (*key, *value) } }) .collect(); diff --git a/pumpkin/src/block/fluid/flowing.rs b/pumpkin/src/block/fluid/flowing.rs index 6ea158883..129033be9 100644 --- a/pumpkin/src/block/fluid/flowing.rs +++ b/pumpkin/src/block/fluid/flowing.rs @@ -95,7 +95,7 @@ pub trait FlowingFluid { && properties .to_props() .iter() - .any(|(key, value)| key == "waterlogged" && value == "true") + .any(|(key, value)| *key == "waterlogged" && *value == "true") { return Some(state_id); } diff --git a/pumpkin/src/item/items/bucket.rs b/pumpkin/src/item/items/bucket.rs index b5a6d847c..8c0ea5078 100644 --- a/pumpkin/src/item/items/bucket.rs +++ b/pumpkin/src/item/items/bucket.rs @@ -84,10 +84,10 @@ fn set_waterlogged(block: &Block, state: u16, waterlogged: bool) -> u16 { let props: Vec<(&str, &str)> = original_props .iter() .map(|(key, value)| { - if key == "waterlogged" { + if *key == "waterlogged" { ("waterlogged", waterlogged.as_str()) } else { - (key.as_str(), value.as_str()) + (*key, *value) } }) .collect(); diff --git a/pumpkin/src/item/items/ender_eye.rs b/pumpkin/src/item/items/ender_eye.rs index f6c59646a..d3a1ab821 100644 --- a/pumpkin/src/item/items/ender_eye.rs +++ b/pumpkin/src/item/items/ender_eye.rs @@ -40,10 +40,10 @@ impl ItemBehaviour for EnderEyeItem { let props: Vec<(&str, &str)> = original_props .iter() .map(|(key, value)| { - if key == "eye" { - (key.as_str(), "true") + if *key == "eye" { + (*key, "true") } else { - (key.as_str(), value.as_str()) + (*key, *value) } }) .collect(); diff --git a/pumpkin/src/item/items/ignite/ignition.rs b/pumpkin/src/item/items/ignite/ignition.rs index e3b9d3367..70ef52646 100644 --- a/pumpkin/src/item/items/ignite/ignition.rs +++ b/pumpkin/src/item/items/ignite/ignition.rs @@ -52,19 +52,14 @@ fn can_be_lit(block: &Block, state_id: u16) -> Option { None => return None, }; - if let Some((_, value)) = props.iter_mut().find(|(k, _)| k == "extinguished") { - *value = "false".into(); - } else if let Some((_, value)) = props.iter_mut().find(|(k, _)| k == "lit") { - *value = "true".into(); + if let Some((_, value)) = props.iter_mut().find(|(k, _)| *k == "extinguished") { + *value = "false"; + } else if let Some((_, value)) = props.iter_mut().find(|(k, _)| *k == "lit") { + *value = "true"; } else { return None; } - let props: Vec<(&str, &str)> = props - .iter() - .map(|(k, v)| (k.as_str(), v.as_str())) - .collect(); - let new_state_id = block.from_properties(&props).to_state_id(block); (new_state_id != state_id).then_some(new_state_id) diff --git a/pumpkin/src/world/loot.rs b/pumpkin/src/world/loot.rs index 95b2825cd..e13b62363 100644 --- a/pumpkin/src/world/loot.rs +++ b/pumpkin/src/world/loot.rs @@ -177,7 +177,7 @@ impl LootConditionExt for LootCondition { properties, } => { if let Some(state) = ¶ms.block_state { - let block_actual_properties: Box<[(String, String)]> = + let block_actual_properties = match Block::properties(Block::from_state_id(state.id), state.id) { Some(props_data) => props_data.to_props(), // Assuming to_props() returns HashMap None => { diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 69bf87565..258819360 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -2723,12 +2723,10 @@ impl World { let block = Block::from_state_id(id); if let Some(properties) = block.properties(id) { for (name, value) in properties.to_props() { - if name == *"waterlogged" { + if name == "waterlogged" { if value == true.to_string() { let fluid = Fluid::FLOWING_WATER; - let state = fluid.states[0].clone(); - return (fluid, state); }