aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2022-05-27 23:10:34 -0500
committermat <github@matdoes.dev>2022-05-27 23:10:34 -0500
commitd56c44766e0f71f5f871b6a457174b81126a2331 (patch)
tree4e7b0cccde9a64c936229cfa92a63835d16046cb
parentc0433b7d4934caa5b1a42625d16058fcece2a86d (diff)
downloadazalea-drasl-d56c44766e0f71f5f871b6a457174b81126a2331.tar.xz
block macros
-rw-r--r--azalea-block/block-macros/src/lib.rs58
-rw-r--r--azalea-block/block-macros/src/utils.rs39
-rw-r--r--azalea-block/src/blocks.rs27
-rw-r--r--examples/craft_dig_straight_down.rs2
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;