Less Allocations more Fun

this made things faster
This commit is contained in:
Alexander Medvedev 2025-06-26 00:10:56 +02:00
parent bed8d5419d
commit 03c71fc9f4
11 changed files with 81 additions and 102 deletions

View File

@ -182,14 +182,12 @@ impl ToTokens for BlockPropertyStruct {
let field_name = Ident::new_raw(&entry.original_name, Span::call_site()); let field_name = Ident::new_raw(&entry.original_name, Span::call_site());
match &entry.property_type { match &entry.property_type {
PropertyType::Bool => quote! { PropertyType::Bool => quote! {
index += !self.#field_name as u16 * multiplier; (!self.#field_name as u16, 2)
multiplier *= 2;
}, },
PropertyType::Enum { name } => { PropertyType::Enum { name } => {
let enum_ident = Ident::new(name, Span::call_site()); let enum_ident = Ident::new(name, Span::call_site());
quote! { quote! {
index += self.#field_name.to_index() * multiplier; (self.#field_name.to_index(), #enum_ident::variant_count())
multiplier *= #enum_ident::variant_count();
} }
} }
} }
@ -230,10 +228,10 @@ impl ToTokens for BlockPropertyStruct {
let field_name = Ident::new_raw(&entry.original_name, Span::call_site()); let field_name = Ident::new_raw(&entry.original_name, Span::call_site());
match &entry.property_type { match &entry.property_type {
PropertyType::Bool => quote! { PropertyType::Bool => quote! {
props.push((#key.to_string(), self.#field_name.to_string())); (#key.to_string(), self.#field_name.to_string()),
}, },
PropertyType::Enum { name: _ } => quote! { PropertyType::Enum { name: _ } => quote! {
props.push((#key.to_string(), self.#field_name.to_value().to_string())); (#key.to_string(), self.#field_name.to_value().to_string()),
}, },
} }
}); });
@ -265,11 +263,12 @@ impl ToTokens for BlockPropertyStruct {
} }
impl BlockProperties for #name { impl BlockProperties for #name {
#[allow(unused_assignments)]
fn to_index(&self) -> u16 { fn to_index(&self) -> u16 {
let mut index = 0; let (index, _) = [#(#to_index_body),*]
let mut multiplier = 1; .iter()
#(#to_index_body)* .fold((0, 1), |(current_index, multiplier), &(value, count)| {
(current_index + value * multiplier, multiplier * count)
});
index index
} }
@ -311,13 +310,10 @@ impl ToTokens for BlockPropertyStruct {
Self::from_state_id(block.default_state.id, block) Self::from_state_id(block.default_state.id, block)
} }
#[allow(clippy::vec_init_then_push)] fn to_props(&self) -> HashMap<String, String> {
fn to_props(&self) -> Vec<(String, String)> { HashMap::from([#(#to_props_values)*])
let mut props = vec![];
#(#to_props_values)*
props
} }
fn from_props(props: Vec<(&str, &str)>, block: &Block) -> Self { fn from_props(props: HashMap<&str, &str>, block: &Block) -> Self {
if ![#(#block_ids),*].contains(&block.id) { if ![#(#block_ids),*].contains(&block.id) {
panic!("{} is not a valid block for {}", &block.name, #struct_name); panic!("{} is not a valid block for {}", &block.name, #struct_name);
} }
@ -847,6 +843,8 @@ pub(crate) fn build() -> TokenStream {
use pumpkin_util::loot_table::*; use pumpkin_util::loot_table::*;
use pumpkin_util::math::experience::Experience; use pumpkin_util::math::experience::Experience;
use pumpkin_util::math::vector3::Vector3; use pumpkin_util::math::vector3::Vector3;
use std::collections::HashMap;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct BlockProperty { pub struct BlockProperty {
@ -871,10 +869,10 @@ pub(crate) fn build() -> TokenStream {
fn default(block: &Block) -> Self where Self: Sized; fn default(block: &Block) -> Self where Self: Sized;
// Convert properties to a `Vec` of `(name, value)` // Convert properties to a `Vec` of `(name, value)`
fn to_props(&self) -> Vec<(String, String)>; fn to_props(&self) -> HashMap<String, String>;
// Convert properties to a block state, and add them onto the default state. // Convert properties to a block state, and add them onto the default state.
fn from_props(props: Vec<(&str, &str)>, block: &Block) -> Self where Self: Sized; fn from_props(props: HashMap<&str, &str>, block: &Block) -> Self where Self: Sized;
} }
pub trait EnumVariants { pub trait EnumVariants {
@ -986,7 +984,7 @@ pub(crate) fn build() -> TokenStream {
} }
#[doc = r" Get the properties of the block."] #[doc = r" Get the properties of the block."]
pub fn from_properties(&self, props: Vec<(&str, &str)>) -> Option<Box<dyn BlockProperties>> { pub fn from_properties(&self, props: HashMap<&str, &str>) -> Option<Box<dyn BlockProperties>> {
match self.id { match self.id {
#block_properties_from_props_and_name #block_properties_from_props_and_name
_ => None _ => None

View File

@ -173,7 +173,7 @@ impl ToTokens for FluidPropertyStruct {
let key2 = Ident::new_raw(&entry.original_name, Span::call_site()); let key2 = Ident::new_raw(&entry.original_name, Span::call_site());
quote! { quote! {
props.push((#key.to_string(), self.#key2.to_value().to_string())); (#key.to_string(), self.#key2.to_value().to_string()),
} }
}); });
@ -255,13 +255,8 @@ impl ToTokens for FluidPropertyStruct {
Self::from_state_id(fluid.default_state_index, fluid) Self::from_state_id(fluid.default_state_index, fluid)
} }
#[allow(clippy::vec_init_then_push)]
fn to_props(&self) -> Vec<(String, String)> { fn to_props(&self) -> Vec<(String, String)> {
let mut props = vec![]; vec![#(#to_props_values)*]
#(#to_props_values)*
props
} }
fn from_props(props: Vec<(String, String)>, fluid: &Fluid) -> Self { fn from_props(props: Vec<(String, String)>, fluid: &Fluid) -> Self {

View File

@ -27,11 +27,11 @@ impl BlockStateCodec {
let mut state_id = block.default_state.id; let mut state_id = block.default_state.id;
if let Some(properties) = &self.properties { if let Some(properties) = &self.properties {
let properties_vec: Vec<(&str, &str)> = properties let props = properties
.iter() .iter()
.map(|(key, value)| (key.as_str(), value.as_str())) .map(|(k, v)| (k.as_str(), v.as_str()))
.collect(); .collect();
let block_properties = block.from_properties(properties_vec).unwrap(); let block_properties = block.from_properties(props).unwrap();
state_id = block_properties.to_state_id(&block); state_id = block_properties.to_state_id(&block);
} }

View File

@ -439,18 +439,7 @@ impl BlockPalette {
BlockStateCodec { BlockStateCodec {
name: block.name.into(), name: block.name.into(),
properties: { properties: block.properties(registry_id).map(|p| p.to_props()),
if let Some(properties) = block.properties(registry_id) {
let props = properties.to_props();
let mut props_map = HashMap::new();
for prop in props {
props_map.insert(prop.0.clone(), prop.1.clone());
}
Some(props_map)
} else {
None
}
},
} }
} }
} }

View File

@ -62,7 +62,7 @@ impl CoralFeature {
.to_props(); .to_props();
let facing = dir.to_facing(); let facing = dir.to_facing();
// Set the right Axis // Set the right Axis
let props_vec: Vec<(&str, &str)> = original_props let props = original_props
.iter() .iter()
.map(|(key, value)| { .map(|(key, value)| {
if key == "facing" { if key == "facing" {
@ -76,7 +76,7 @@ impl CoralFeature {
&dir_pos.0, &dir_pos.0,
&get_state_by_state_id( &get_state_by_state_id(
wall_coral wall_coral
.from_properties(props_vec) .from_properties(props)
.unwrap() .unwrap()
.to_state_id(&wall_coral), .to_state_id(&wall_coral),
) )

View File

@ -163,7 +163,7 @@ impl FancyTrunkPlacer {
let original_props = &block.properties(trunk_provider.id).unwrap().to_props(); let original_props = &block.properties(trunk_provider.id).unwrap().to_props();
let axis = axis.to_value(); let axis = axis.to_value();
// Set the right Axis // Set the right Axis
let props_vec: Vec<(&str, &str)> = original_props let props = original_props
.iter() .iter()
.map(|(key, value)| { .map(|(key, value)| {
if key == "axis" { if key == "axis" {
@ -173,10 +173,7 @@ impl FancyTrunkPlacer {
} }
}) })
.collect(); .collect();
let state = block let state = block.from_properties(props).unwrap().to_state_id(&block);
.from_properties(props_vec)
.unwrap()
.to_state_id(&block);
if chunk.chunk_pos == block_pos_2.chunk_and_chunk_relative_position().0 { if chunk.chunk_pos == block_pos_2.chunk_and_chunk_relative_position().0 {
chunk.set_block_state( chunk.set_block_state(
&block_pos_2.0, &block_pos_2.0,

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use pumpkin_data::{Block, BlockState, block_properties::get_block_by_state_id, item::Item}; use pumpkin_data::{Block, BlockState, block_properties::get_block_by_state_id, item::Item};
use pumpkin_util::{ use pumpkin_util::{
loot_table::{ loot_table::{
@ -169,13 +171,21 @@ impl LootConditionExt for LootCondition {
properties, properties,
} => { } => {
if let Some(state) = &params.block_state { if let Some(state) = &params.block_state {
let props = let block_actual_properties: HashMap<String, String> = match Block::properties(
Block::properties(&get_block_by_state_id(state.id).unwrap(), state.id) &get_block_by_state_id(state.id).unwrap(),
.map_or_else(Vec::new, |props| props.to_props()); state.id,
) {
Some(props_data) => props_data.to_props(), // Assuming to_props() returns HashMap<String, String>
None => {
return properties.is_empty();
}
};
return properties return properties.iter().all(|&(expected_key, expected_value)| {
.iter() block_actual_properties.get(expected_key).is_some_and(
.all(|(key, value)| props.iter().any(|(k, v)| k == key && v == value)); |actual_value_string| actual_value_string.as_str() == expected_value,
)
});
} }
false false
} }

View File

@ -79,16 +79,18 @@ fn waterlogged_check(block: &Block, state: &BlockState) -> Option<bool> {
fn set_waterlogged(block: &Block, state: &BlockState, waterlogged: bool) -> u16 { fn set_waterlogged(block: &Block, state: &BlockState, waterlogged: bool) -> u16 {
let original_props = &block.properties(state.id).unwrap().to_props(); let original_props = &block.properties(state.id).unwrap().to_props();
let mut props_vec: Vec<(&str, &str)> = Vec::with_capacity(original_props.len());
let waterlogged = waterlogged.to_string(); let waterlogged = waterlogged.to_string();
for (key, value) in original_props { let props = original_props
.iter()
.map(|(key, value)| {
if key == "waterlogged" { if key == "waterlogged" {
props_vec.push((key.as_str(), &waterlogged)); ("waterlogged", waterlogged.as_str())
} else { } else {
props_vec.push((key.as_str(), value.as_str())); (key.as_str(), value.as_str())
} }
} })
block.from_properties(props_vec).unwrap().to_state_id(block) .collect();
block.from_properties(props).unwrap().to_state_id(block)
} }
#[async_trait] #[async_trait]

View File

@ -34,16 +34,20 @@ impl PumpkinItem for EnderEyeItem {
let world = player.world().await; let world = player.world().await;
let state_id = world.get_block_state_id(&location).await; let state_id = world.get_block_state_id(&location).await;
let original_props = &block.properties(state_id).unwrap().to_props(); let original_props = block.properties(state_id).unwrap().to_props();
let mut props_vec: Vec<(&str, &str)> = Vec::with_capacity(original_props.len());
for (key, value) in original_props { let props = original_props
.iter()
.map(|(key, value)| {
if key == "eye" { if key == "eye" {
props_vec.push((key.as_str(), "true")); (key.as_str(), "true")
} else { } else {
props_vec.push((key.as_str(), value.as_str())); (key.as_str(), value.as_str())
} }
} })
let new_state_id = block.from_properties(props_vec).unwrap().to_state_id(block); .collect();
let new_state_id = block.from_properties(props).unwrap().to_state_id(block);
world world
.set_block_state(&location, new_state_id, BlockFlags::empty()) .set_block_state(&location, new_state_id, BlockFlags::empty())
.await; .await;

View File

@ -67,18 +67,18 @@ async fn get_ignite_result(block: &Block, world: &Arc<World>, location: &BlockPo
None => return None, None => return None,
}; };
let mut props_vec: Vec<(&str, &str)> = Vec::with_capacity(original_props.len()); let props = original_props
for (key, _value) in &original_props { .iter()
if key == "extinguished" { .filter_map(|(key, _value)| {
// campfire match key.as_str() {
props_vec.push((key.as_str(), "true")); "extinguished" => Some(("extinguished", "true")),
} else if key == "lit" { "lit" => Some(("lit", "true")),
// candles _ => None, // Discard other keys
props_vec.push((key.as_str(), "true"));
}
} }
})
.collect();
let new_state_id = block.from_properties(props_vec).unwrap().to_state_id(block); let new_state_id = block.from_properties(props).unwrap().to_state_id(block);
(new_state_id != state_id).then_some(new_state_id) (new_state_id != state_id).then_some(new_state_id)
} }

View File

@ -1185,22 +1185,6 @@ impl World {
let position = chunk.read().await.position; let position = chunk.read().await.position;
#[cfg(debug_assertions)]
if position == (0, 0).into() {
use pumpkin_protocol::client::play::CChunkData;
let binding = chunk.read().await;
let packet = CChunkData(&binding);
let mut test = Vec::new();
packet.write_packet_data(&mut test).unwrap();
let len = test.len();
log::debug!(
"Chunk packet size: {}B {}KB {}MB",
len,
len / 1024,
len / (1024 * 1024)
);
}
let (world, chunk) = if level.is_chunk_watched(&position) { let (world, chunk) = if level.is_chunk_watched(&position) {
(world.clone(), chunk) (world.clone(), chunk)
} else { } else {
@ -1523,7 +1507,7 @@ impl World {
for player in players.values() { for player in players.values() {
player.send_system_message(&event.join_message).await; player.send_system_message(&event.join_message).await;
} }
log::info!("{}", event.join_message.clone().to_pretty_console()); log::info!("{}", event.join_message.to_pretty_console());
} }
}); });
Ok(()) Ok(())
@ -1575,7 +1559,7 @@ impl World {
for player in players.values() { for player in players.values() {
player.send_system_message(&event.leave_message).await; player.send_system_message(&event.leave_message).await;
} }
log::info!("{}", event.leave_message.clone().to_pretty_console()); log::info!("{}", event.leave_message.to_pretty_console());
} }
} }
} }