diff options
| author | mat <github@matdoes.dev> | 2022-05-27 23:10:34 -0500 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2022-05-27 23:10:34 -0500 |
| commit | d56c44766e0f71f5f871b6a457174b81126a2331 (patch) | |
| tree | 4e7b0cccde9a64c936229cfa92a63835d16046cb | |
| parent | c0433b7d4934caa5b1a42625d16058fcece2a86d (diff) | |
| download | azalea-drasl-d56c44766e0f71f5f871b6a457174b81126a2331.tar.xz | |
block macros
| -rw-r--r-- | azalea-block/block-macros/src/lib.rs | 58 | ||||
| -rw-r--r-- | azalea-block/block-macros/src/utils.rs | 39 | ||||
| -rw-r--r-- | azalea-block/src/blocks.rs | 27 | ||||
| -rw-r--r-- | examples/craft_dig_straight_down.rs | 2 |
4 files changed, 109 insertions, 17 deletions
diff --git a/azalea-block/block-macros/src/lib.rs b/azalea-block/block-macros/src/lib.rs index d6c3465e..9cbd6ca3 100644 --- a/azalea-block/block-macros/src/lib.rs +++ b/azalea-block/block-macros/src/lib.rs @@ -1,13 +1,16 @@ +mod utils; + use proc_macro::TokenStream; -use quote::{quote, ToTokens}; -use std::fmt::Debug; +use quote::quote; +use std::collections::HashMap; use syn::{ self, braced, parse::{Parse, ParseStream, Result}, parse_macro_input, punctuated::Punctuated, - Data, DeriveInput, Expr, FieldsNamed, Ident, LitInt, Token, + Expr, Ident, Token, }; +use utils::{combinations_of, to_pascal_case}; struct PropertyDefinition { name: Ident, @@ -71,6 +74,7 @@ impl Parse for BlockDefinition { let name = input.parse()?; input.parse::<Token![=>]>()?; let behavior = input.parse()?; + input.parse::<Token![,]>()?; let content; braced!(content in input); @@ -124,14 +128,16 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as MakeBlockStates); let mut property_enums = quote! {}; - + let mut properties_map = HashMap::new(); for property in &input.property_definitions.properties { let mut property_enum_variants = quote! {}; + let mut property_enum_variant_names = Vec::new(); for variant in &property.variants { property_enum_variants.extend(quote! { #variant, }); + property_enum_variant_names.push(variant.to_string()); } let property_name = &property.name; @@ -142,20 +148,46 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { #property_enum_variants } }); + properties_map.insert(property_name.to_string(), property_enum_variant_names); } - // let mut block_state_enum_variants = quote! {}; - - // for block in &input.block_definitions.blocks { - // let block_state_enum_variant = quote! { - // #block.name(#block.behavior, #block.properties) - // }; - // block_state_enum_variants.extend(block_state_enum_variant); - // } + let mut block_state_enum_variants = quote! {}; + for block in &input.block_definitions.blocks { + let block_properties = &block.properties; + let mut block_properties_vec = Vec::new(); + for property in block_properties { + let property_name = &property.to_string(); + let property_variants = properties_map + .get(property_name) + .expect(format!("Property '{}' not found", property_name).as_str()) + .clone(); + block_properties_vec.push(property_variants); + } + for combination in combinations_of(&block_properties_vec) { + let variant_name = Ident::new( + &format!( + "{}_{}", + to_pascal_case(&block.name.to_string()), + combination + .iter() + .map(|v| v.to_string()) + .collect::<Vec<String>>() + .join("") + ), + proc_macro2::Span::call_site(), + ); + block_state_enum_variants.extend(quote! { + #variant_name, + }); + } + } quote! { #property_enums - // #block_state_enum_variants + + pub enum BlockState { + #block_state_enum_variants + } } .into() } diff --git a/azalea-block/block-macros/src/utils.rs b/azalea-block/block-macros/src/utils.rs new file mode 100644 index 00000000..8700e17f --- /dev/null +++ b/azalea-block/block-macros/src/utils.rs @@ -0,0 +1,39 @@ +pub fn combinations_of<T: Clone>(items: &[Vec<T>]) -> Vec<Vec<T>> { + let mut combinations = Vec::new(); + if items.len() == 1 { + for item in &items[0] { + combinations.push(vec![item.clone()]); + } + return combinations; + }; + + for i in 0..items[0].len() { + let item = &items[0][i]; + for other_combinations in combinations_of(&items[1..]) { + let mut combination = Vec::new(); + combination.push(item.clone()); + combination.extend(other_combinations); + combinations.push(combination); + } + } + + combinations +} + +pub fn to_pascal_case(s: &str) -> String { + let mut result = String::new(); + let mut prev_was_underscore = true; // set to true by default so the first character is capitalized + for c in s.chars() { + if c == '_' { + prev_was_underscore = true; + } else { + if prev_was_underscore { + result.push(c.to_ascii_uppercase()); + prev_was_underscore = false; + } else { + result.push(c); + } + } + } + result +} diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index a50e8804..855de96b 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -1,4 +1,3 @@ -use crate::behavior::BlockBehavior; use block_macros::make_block_states; make_block_states! { @@ -8,14 +7,36 @@ make_block_states! { Wall, Ceiling }; + Facing { + North, + South, + West, + East + }; + Powered { + True, + False + }; + Half { + Upper, + Lower + }; + Hinge { + Left, + Right + }; + Open { + True, + False + }; } BLOCKS => { - acacia_button => BlockBehavior { has_collision: false }, { + acacia_button => BlockBehavior::new().no_collision(), { Face, Facing, Powered }; - acacia_door => BlockBehavior { has_collision: true }, { + acacia_door => BlockBehavior::new(), { Facing, Half, Hinge, diff --git a/examples/craft_dig_straight_down.rs b/examples/craft_dig_straight_down.rs index 79985672..1d1a89f6 100644 --- a/examples/craft_dig_straight_down.rs +++ b/examples/craft_dig_straight_down.rs @@ -14,7 +14,7 @@ loop { pathfinder::Goals::NearXZ(5, azalea::BlockXZ(0, 0)) ).await; let chest = bot.open_chest(&bot.world.find_one_block(|b| b.id == "minecraft:chest")).await.unwrap(); - bot.take_amount(&chest, 3, |i| i.id == "#minecraft:planks").await; + bot.take_amount(&chest, 5, |i| i.id == "#minecraft:planks").await; // when rust adds async drop this won't be necessary chest.close().await; |
