default block properties

This commit is contained in:
mat 2022-05-28 20:59:22 -05:00
parent 8cd0ff2aac
commit 9c1c286236
4 changed files with 123 additions and 37 deletions

View file

@ -20,10 +20,14 @@ struct PropertyDefinitions {
properties: Vec<PropertyDefinition>,
}
struct PropertyAndDefault {
name: Ident,
default: Ident,
}
struct BlockDefinition {
name: Ident,
behavior: Expr,
properties: Punctuated<Ident, Token![,]>,
properties_and_defaults: Vec<PropertyAndDefault>,
}
struct BlockDefinitions {
blocks: Vec<BlockDefinition>,
@ -39,14 +43,14 @@ impl Parse for PropertyDefinition {
// Floor,
// Wall,
// Ceiling
// };
// },
let name = input.parse()?;
let content;
braced!(content in input);
let variants = content.parse_terminated(Ident::parse)?;
input.parse::<Token![;]>()?;
input.parse::<Token![,]>()?;
Ok(PropertyDefinition { name, variants })
}
}
@ -66,11 +70,11 @@ impl Parse for PropertyDefinitions {
impl Parse for BlockDefinition {
fn parse(input: ParseStream) -> Result<Self> {
// acacia_button => BlockBehavior { has_collision: false }, {
// acacia_button => BlockBehavior::default().no_collision(), {
// Face,
// Facing,
// Powered
// };
// },
let name = input.parse()?;
input.parse::<Token![=>]>()?;
let behavior = input.parse()?;
@ -78,12 +82,29 @@ impl Parse for BlockDefinition {
input.parse::<Token![,]>()?;
let content;
braced!(content in input);
let properties = content.parse_terminated(Ident::parse)?;
input.parse::<Token![;]>()?;
let mut properties_and_defaults = Vec::new();
loop {
let property = match content.parse() {
Ok(property) => property,
Err(_) => break,
};
content.parse::<Token![=]>()?;
let property_default = content.parse()?;
properties_and_defaults.push(PropertyAndDefault {
name: property,
default: property_default,
});
if content.parse::<Token![,]>().is_err() {
break;
}
}
input.parse::<Token![,]>()?;
Ok(BlockDefinition {
name,
behavior,
properties,
properties_and_defaults,
})
}
}
@ -109,6 +130,8 @@ impl Parse for MakeBlockStates {
braced!(content in input);
let properties = content.parse()?;
input.parse::<Token![,]>()?;
let blocks_ident = input.parse::<Ident>()?;
assert_eq!(blocks_ident.to_string(), "Blocks");
input.parse::<Token![=>]>()?;
@ -183,9 +206,9 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
let mut from_state_to_block_match = quote! {};
for block in &input.block_definitions.blocks {
let block_property_names = &block
.properties
.properties_and_defaults
.iter()
.map(|p| p.to_string())
.map(|p| p.name.to_string())
.collect::<Vec<_>>();
let mut block_properties_vec = Vec::new();
for property_name in block_property_names {
@ -200,7 +223,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
// pub facing: properties::Facing,
// pub powered: properties::Powered,
let mut block_struct_fields = quote! {};
for property in &block.properties {
for PropertyAndDefault { name: property, .. } in &block.properties_and_defaults {
let property_name_snake =
Ident::new(&property.to_string(), proc_macro2::Span::call_site());
block_struct_fields.extend(quote! {
@ -268,12 +291,16 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
// }
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];
for i in (0..block.properties_and_defaults.len()).rev() {
let PropertyAndDefault {
name: property_name,
..
} = &block.properties_and_defaults[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),
#property_name: #property_name::from((b / #division) % #property_variants_count),
});
division *= property_variants_count;
@ -289,6 +316,17 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
},
});
let mut block_default_fields = quote! {};
for PropertyAndDefault {
name: property,
default: property_default,
} in &block.properties_and_defaults
{
block_default_fields.extend(quote! {
#property: #property::#property_default,
})
}
let block_behavior = &block.behavior;
let block_id = block.name.to_string();
let block_struct = quote! {
@ -314,6 +352,13 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
}
}
impl Default for #block_struct_name {
fn default() -> Self {
Self {
#block_default_fields
}
}
}
};
block_structs.extend(block_struct);

View file

@ -12,43 +12,43 @@ make_block_states! {
Floor,
Wall,
Ceiling
};
},
Facing {
North,
South,
West,
East
};
},
Powered {
True,
False
};
},
Half {
Upper,
Lower
};
},
Hinge {
Left,
Right
};
},
Open {
True,
False
};
}
},
},
Blocks => {
acacia_button => BlockBehavior::default().no_collision(), {
Face,
Facing,
Powered
};
Face=Floor,
Facing=North,
Powered=True
},
acacia_door => BlockBehavior::default(), {
Facing,
Half,
Hinge,
Open,
Powered
};
Facing=North,
Half=Upper,
Hinge=Left,
Open=True,
Powered=True
},
}
}

View file

@ -1,5 +1,6 @@
from lib.utils import to_camel_case
from lib.utils import get_dir_location
import json
BLOCKS_RS_DIR = get_dir_location('../azalea-block/src/blocks.rs')
@ -11,10 +12,45 @@ def generate_blocks(blocks: dict):
new_make_block_states_macro_code = []
new_make_block_states_macro_code.append('make_block_states! {')
# Find properties
properties = {}
for block_name, block_data in blocks.items():
block_properties = block_data['properties']
for block_data in blocks.values():
block_properties = block_data.get('properties', {})
properties.update(block_properties)
print(properties)
# Property codegen
new_make_block_states_macro_code.append(' Properties => {')
for property_name, property_variants in properties.items():
new_make_block_states_macro_code.append(
f' {to_camel_case(property_name)} => {{')
for variant in property_variants:
new_make_block_states_macro_code.append(
f' {to_camel_case(variant)},')
new_make_block_states_macro_code.append(
f' }},')
new_make_block_states_macro_code.append(' },')
# Block codegen
new_make_block_states_macro_code.append(' Blocks => {')
for block_id, block_data in blocks.items():
block_id = block_id.split(':')[1]
block_states = block_data['states']
default_property_variants = {}
for state in block_states:
if state.get('default'):
default_property_variants = state.get('properties', {})
# TODO: use burger to generate the blockbehavior
new_make_block_states_macro_code.append(
f' {block_id} => BlockBehavior::default(), {{')
for property in block_data.get('properties', {}):
property_default = default_property_variants.get(property)
new_make_block_states_macro_code.append(
f' {to_camel_case(property)}={to_camel_case(property_default)},')
new_make_block_states_macro_code.append(' },')
new_make_block_states_macro_code.append(' },')
print('\n'.join(new_make_block_states_macro_code))

View file

@ -11,7 +11,12 @@ def to_snake_case(name: str):
def to_camel_case(name: str):
s = re.sub('_([a-z])', lambda m: m.group(1).upper(), name)
return s[0].upper() + s[1:]
s = s[0].upper() + s[1:]
# if the first character is a number, we need to add an underscore
# maybe we could convert it to the number name (like 2 would become "two")?
if s[0].isdigit():
s = f'_{s}'
return s
def padded_hex(n: int):