From ff2f3c7af5bd4c1a1c10fa7c269830b9081319e4 Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 28 May 2022 13:39:33 -0500 Subject: slight optimization --- azalea-block/block-macros/src/lib.rs | 88 +++++++++++++++++++++++++++++------- azalea-block/src/blocks.rs | 25 ++++++++++ 2 files changed, 96 insertions(+), 17 deletions(-) diff --git a/azalea-block/block-macros/src/lib.rs b/azalea-block/block-macros/src/lib.rs index 4e82d39d..3d937ac4 100644 --- a/azalea-block/block-macros/src/lib.rs +++ b/azalea-block/block-macros/src/lib.rs @@ -129,24 +129,51 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { let mut property_enums = quote! {}; let mut properties_map = HashMap::new(); + + let mut state_id = 0usize; + for property in &input.property_definitions.properties { let mut property_enum_variants = quote! {}; + let mut property_from_number_variants = quote! {}; let mut property_enum_variant_names = Vec::new(); - for variant in &property.variants { + let property_name = &property.name; + + for i in 0..property.variants.len() { + let variant = &property.variants[i]; + + let i_lit = syn::Lit::Int(syn::LitInt::new( + &i.to_string(), + proc_macro2::Span::call_site(), + )); + property_enum_variants.extend(quote! { - #variant, + #variant = #i_lit, }); + + // i_lit is used here instead of i because otherwise it says 0size + // in the expansion and that looks uglier + property_from_number_variants.extend(quote! { + #i_lit => #property_name::#variant, + }); + property_enum_variant_names.push(variant.to_string()); } - let property_name = &property.name; - property_enums.extend(quote! { #[derive(Debug, Clone, Copy)] pub enum #property_name { #property_enum_variants } + + impl From for #property_name { + fn from(value: usize) -> Self { + match value { + #property_from_number_variants + _ => panic!("Invalid property value: {}", value), + } + } + } }); properties_map.insert(property_name.to_string(), property_enum_variant_names); } @@ -187,7 +214,10 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { let mut from_block_to_state_match = quote! {}; + let first_state_id = state_id; + for combination in combinations_of(&block_properties_vec) { + state_id += 1; let variant_name = Ident::new( &format!( "{}_{}", @@ -226,20 +256,41 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { #from_block_to_state_match_inner } => BlockState::#variant_name, }); + } - // BlockState::AcaciaButton_FloorNorthTrue => &AcaciaButtonBlock { - // face: properties::Face::Floor, - // facing: properties::Facing::North, - // powered: properties::Powered::True, - // }, - from_state_to_block_match.extend(quote! { - BlockState::#variant_name => &#block_struct_name { - #from_block_to_state_match_inner - }, - }) + // 7035..=7058 => { + // let b = b - 7035; + // &AcaciaButtonBlock { + // Powered: Powered::from((b / 1) % 2), + // Facing: Facing::from((b / 2) % 4), + // Face: Face::from((b / 8) % 3), + // } + // } + let mut from_state_to_block_inner = quote! {}; + let mut division = 1usize; + for i in (0..block.properties.len()).rev() { + let property = &block.properties[i]; + let property_variants = &block_properties_vec[i]; + let property_variants_count = property_variants.len(); + from_state_to_block_inner.extend(quote! { + #property: #property::from((b / #division) % #property_variants_count), + }); + + division *= property_variants_count; } + let last_state_id = state_id - 1; + from_state_to_block_match.extend(quote! { + #first_state_id..=#last_state_id => { + let b = b - #first_state_id; + Box::new(#block_struct_name { + #from_state_to_block_inner + }) + }, + }); + let block_behavior = &block.behavior; + let block_id = block.name.to_string(); let block_struct = quote! { #[derive(Debug)] pub struct #block_struct_name { @@ -250,6 +301,9 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { fn behavior(&self) -> BlockBehavior { #block_behavior } + fn id(&self) -> &'static str { + #block_id + } } impl From<#block_struct_name> for BlockState { @@ -274,15 +328,15 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { #block_structs - impl From for &dyn Block { + impl From for Box { fn from(b: BlockState) -> Self { + let b = b as usize; match b { #from_state_to_block_match + _ => panic!("Invalid block state: {}", b), } } } - - } .into() } diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index d4339ada..beba877e 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -3,6 +3,7 @@ use block_macros::make_block_states; pub trait Block { fn behavior(&self) -> BlockBehavior; + fn id(&self) -> &'static str; } make_block_states! { @@ -143,3 +144,27 @@ make_block_states! { // } // } // } + +// #[cfg(test)] +// mod tests { +// use super::*; + +// fn test_from_state_to_block() { +// let state = BlockState::AcaciaButton_CeilingSouthFalse; +// let block_state = BlockState::from(state); +// let block: Box = block_state.into(); +// assert_eq!(block.id(), "acacia_button"); +// // downcast block to AcaciaButtonBlock +// // let acacia_button_block = block.try_into::().unwrap(); +// // assert_eq!(acacia_button_block.face, Face::Ceiling); +// // assert_eq!(acacia_button_block.facing, Facing::South); +// // assert_eq!(acacia_button_block.powered, Powered::False); +// } + +// fn test_from_state_to_block_bottom_edge() { +// let state = BlockState::AcaciaButton_FloorNorthTrue; +// let block_state = BlockState::from(state); +// let block: Box = block_state.into(); +// assert_eq!(block.id(), "acacia_button"); +// } +// } -- cgit v1.2.3