mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 22:52:32 +00:00
block macros
This commit is contained in:
parent
c0433b7d49
commit
d56c44766e
4 changed files with 109 additions and 17 deletions
|
@ -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()
|
||||
}
|
||||
|
|
39
azalea-block/block-macros/src/utils.rs
Normal file
39
azalea-block/block-macros/src/utils.rs
Normal file
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue