diff options
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | azalea-block/azalea-block-macros/src/lib.rs | 30 | ||||
| -rw-r--r-- | azalea-block/azalea-block-macros/src/property/generate.rs | 18 | ||||
| -rw-r--r-- | azalea-block/src/generated.rs | 2 | ||||
| -rw-r--r-- | azalea-block/src/lib.rs | 13 |
5 files changed, 58 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 27b349cb..99e30e83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ is breaking anyways, semantic versioning is not followed. - Re-implement `Client::map_component` and `map_get_component`. - Add an `EntityRef` type to simplify interactions with entities. - `AccountTrait` was implemented, which allows for custom refresh and join behavior for `Account`s. +- Add `BlockTrait::set_property` to allow setting properties on blocks generically. ### Changed diff --git a/azalea-block/azalea-block-macros/src/lib.rs b/azalea-block/azalea-block-macros/src/lib.rs index 586d6a98..23546a2b 100644 --- a/azalea-block/azalea-block-macros/src/lib.rs +++ b/azalea-block/azalea-block-macros/src/lib.rs @@ -434,7 +434,8 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { }); let mut property_map_inner = quote! {}; - let mut get_property_inner = quote! {}; + let mut get_property_match_inner = quote! {}; + let mut set_property_match_inner = quote! {}; for PropertyWithNameAndDefault { name, @@ -450,10 +451,30 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { property_map_inner.extend(quote! { map.insert(#name, #variant_name_tokens); }); - get_property_inner.extend(quote! { + get_property_match_inner.extend(quote! { #name => Some(#variant_name_tokens), }); + + set_property_match_inner.extend(match kind { + PropertyKind::Enum => quote! { #name => self.#name_ident = new_value.parse()?, }, + PropertyKind::Bool => { + quote! { #name => self.#name_ident = new_value.parse::<bool>().map_err(|_| ())?, } + } + }); } + let set_property = if set_property_match_inner.is_empty() { + quote! { + Err(()) + } + } else { + quote! { + match name { + #set_property_match_inner + _ => return Err(()), + } + Ok(()) + } + }; let mut block_default_fields = quote! {}; for PropertyWithNameAndDefault { @@ -502,10 +523,13 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { } fn get_property(&self, name: &str) -> Option<&'static str> { match name { - #get_property_inner + #get_property_match_inner _ => None, } } + fn set_property(&mut self, name: &str, new_value: &str) -> Result<(), ()> { + #set_property + } } impl From<#block_struct_name> for BlockState { diff --git a/azalea-block/azalea-block-macros/src/property/generate.rs b/azalea-block/azalea-block-macros/src/property/generate.rs index c49afd53..fc48e609 100644 --- a/azalea-block/azalea-block-macros/src/property/generate.rs +++ b/azalea-block/azalea-block-macros/src/property/generate.rs @@ -36,6 +36,7 @@ fn generate_property_code( let property_struct_name = get_property_type_name(&property.data); let mut to_static_str_inner = quote! {}; + let mut from_str_match_inner = quote! {}; match &property.data { PropertyData::Enum { variants, .. } => { @@ -56,6 +57,9 @@ fn generate_property_code( to_static_str_inner.extend(quote! { Self::#variant_ident => #variant_str, }); + from_str_match_inner.extend(quote! { + #variant_str => Self::#variant_ident, + }); } properties_code.extend(quote! { @@ -79,6 +83,10 @@ fn generate_property_code( Self(true) => "true", Self(false) => "false", }); + from_str_match_inner.extend(quote! { + "true" => Self(true), + "false" => Self(false), + }); properties_code.extend(quote! { #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -122,6 +130,16 @@ fn generate_property_code( } } } + impl FromStr for #property_struct_name { + type Err = (); + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(match s { + #from_str_match_inner + _ => return Err(()) + }) + } + } impl std::fmt::Display for #property_struct_name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/azalea-block/src/generated.rs b/azalea-block/src/generated.rs index 8d91695f..d042da22 100644 --- a/azalea-block/src/generated.rs +++ b/azalea-block/src/generated.rs @@ -1,6 +1,6 @@ //! This code is @generated by codegen/genblocks.py. -use std::fmt::Debug; +use std::{fmt::Debug, str::FromStr}; use azalea_block_macros::make_block_states; diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index ad78102c..3c64af25 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -7,7 +7,7 @@ mod generated; mod range; use core::fmt::Debug; -use std::{any::Any, collections::HashMap}; +use std::{any::Any, collections::HashMap, str::FromStr}; use azalea_registry::builtin::BlockKind; pub use behavior::BlockBehavior; @@ -43,7 +43,16 @@ pub trait BlockTrait: Debug + Any { /// has no property with that name. /// /// To get all properties, you may use [`Self::property_map`]. + /// + /// To set a property, use [`Self::set_property`]. fn get_property(&self, name: &str) -> Option<&'static str>; + /// Update a property on this block, with the name and value being strings. + /// + /// Returns `Ok(())`, if the property name and value are valid, otherwise it + /// returns `Err(())`. + /// + /// To get a property, use [`Self::get_property`]. + fn set_property(&mut self, name: &str, new_value: &str) -> Result<(), ()>; } impl dyn BlockTrait { @@ -52,7 +61,7 @@ impl dyn BlockTrait { } } -pub trait Property { +pub trait Property: FromStr { type Value; fn try_from_block_state(state: BlockState) -> Option<Self::Value>; |
