diff options
| author | mat <git@matdoes.dev> | 2024-12-24 09:40:29 +0000 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2024-12-24 09:40:29 +0000 |
| commit | a599b5614e6acf65e552940fff99a9252a600472 (patch) | |
| tree | cf686191747a389f963b633a0898940cba594d13 /azalea-block | |
| parent | f03e0c22355778a9863cccb5a59d852278d60701 (diff) | |
| download | azalea-drasl-a599b5614e6acf65e552940fff99a9252a600472.tar.xz | |
make BlockState a u16 and add a BlockStateIntegerRepr type
Diffstat (limited to 'azalea-block')
| -rwxr-xr-x | azalea-block/azalea-block-macros/src/lib.rs | 20 | ||||
| -rwxr-xr-x | azalea-block/src/lib.rs | 47 | ||||
| -rw-r--r-- | azalea-block/src/range.rs | 6 |
3 files changed, 54 insertions, 19 deletions
diff --git a/azalea-block/azalea-block-macros/src/lib.rs b/azalea-block/azalea-block-macros/src/lib.rs index de13ff6e..9374527f 100755 --- a/azalea-block/azalea-block-macros/src/lib.rs +++ b/azalea-block/azalea-block-macros/src/lib.rs @@ -19,6 +19,8 @@ use syn::{ }; use utils::{combinations_of, to_pascal_case}; +// must be the same as the type in `azalea-block/src/lib.rs` +type BlockStateIntegerRepr = u16; enum PropertyType { /// `Axis { X, Y, Z }` Enum { @@ -275,7 +277,7 @@ impl Parse for MakeBlockStates { } struct PropertyVariantData { - pub block_state_ids: Vec<u32>, + pub block_state_ids: Vec<BlockStateIntegerRepr>, pub ident: Ident, pub is_enum: bool, } @@ -288,7 +290,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { let mut properties_map = HashMap::new(); let mut property_struct_names_to_names = HashMap::new(); - let mut state_id: u32 = 0; + let mut state_id: BlockStateIntegerRepr = 0; for property in &input.property_definitions.properties { let property_struct_name: Ident; @@ -339,8 +341,8 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { #property_enum_variants } - impl From<u32> for #property_struct_name { - fn from(value: u32) -> Self { + impl From<crate::BlockStateIntegerRepr> for #property_struct_name { + fn from(value: crate::BlockStateIntegerRepr) -> Self { match value { #property_from_number_variants _ => panic!("Invalid property value: {}", value), @@ -358,8 +360,8 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct #property_struct_name(pub bool); - impl From<u32> for #property_struct_name { - fn from(value: u32) -> Self { + impl From<crate::BlockStateIntegerRepr> for #property_struct_name { + fn from(value: crate::BlockStateIntegerRepr) -> Self { match value { 0 => Self(false), 1 => Self(true), @@ -583,7 +585,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { // } // } let mut from_state_to_block_inner = quote! {}; - let mut division = 1u32; + let mut division: BlockStateIntegerRepr = 1; for i in (0..properties_with_name.len()).rev() { let PropertyWithNameAndDefault { property_type: property_struct_name_ident, @@ -593,7 +595,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { } = &properties_with_name[i]; let property_variants = &block_properties_vec[i]; - let property_variants_count = property_variants.len() as u32; + let property_variants_count = property_variants.len() as crate::BlockStateIntegerRepr; let conversion_code = { if &property_value_type.to_string() == "bool" { assert_eq!(property_variants_count, 2); @@ -695,7 +697,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { let mut generated = quote! { impl BlockState { /// The highest possible block state ID. - pub const MAX_STATE: u32 = #last_state_id; + pub const MAX_STATE: crate::BlockStateIntegerRepr = #last_state_id; /// Get a property from this block state. Will be `None` if the block can't have the property. /// diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index 3de0aa5a..65dd581e 100755 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -40,22 +40,34 @@ pub trait Property { fn try_from_block_state(state: BlockState) -> Option<Self::Value>; } +/// The type that's used internally to represent a block state ID. +/// +/// This should be either `u16` or `u32`. If you choose to modify it, you must +/// also change it in `azalea-block-macros/src/lib.rs`. +/// +/// This does not affect protocol serialization, it just allows you to make the +/// internal type smaller if you want. +pub type BlockStateIntegerRepr = u16; + /// A representation of a state a block can be in. /// /// For example, a stone block only has one state but each possible stair /// rotation is a different state. +/// +/// Note that this type is internally either a `u16` or `u32`, depending on +/// [`BlockStateIntegerRepr`]. #[derive(Copy, Clone, PartialEq, Eq, Default, Hash)] pub struct BlockState { /// The protocol ID for the block state. IDs may change every /// version, so you shouldn't hard-code them or store them in databases. - pub id: u32, + pub id: BlockStateIntegerRepr, } impl BlockState { pub const AIR: BlockState = BlockState { id: 0 }; #[inline] - pub fn is_valid_state(state_id: u32) -> bool { + pub fn is_valid_state(state_id: BlockStateIntegerRepr) -> bool { state_id <= Self::MAX_STATE } @@ -70,8 +82,22 @@ impl BlockState { impl TryFrom<u32> for BlockState { type Error = (); - /// Safely converts a state id to a block state. + /// Safely converts a u32 state id to a block state. fn try_from(state_id: u32) -> Result<Self, Self::Error> { + let state_id = state_id as BlockStateIntegerRepr; + if Self::is_valid_state(state_id) { + Ok(BlockState { id: state_id }) + } else { + Err(()) + } + } +} +impl TryFrom<u16> for BlockState { + type Error = (); + + /// Safely converts a u16 state id to a block state. + fn try_from(state_id: u16) -> Result<Self, Self::Error> { + let state_id = state_id as BlockStateIntegerRepr; if Self::is_valid_state(state_id) { Ok(BlockState { id: state_id }) } else { @@ -90,7 +116,7 @@ impl AzaleaRead for BlockState { } impl AzaleaWrite for BlockState { fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - u32::azalea_write_var(&self.id, buf) + u32::azalea_write_var(&(self.id as u32), buf) } } @@ -158,12 +184,16 @@ impl From<FluidState> for BlockState { azalea_registry::Fluid::Empty => BlockState::AIR, azalea_registry::Fluid::Water | azalea_registry::Fluid::FlowingWater => { BlockState::from(crate::blocks::Water { - level: crate::properties::WaterLevel::from(state.height as u32), + level: crate::properties::WaterLevel::from( + state.height as BlockStateIntegerRepr, + ), }) } azalea_registry::Fluid::Lava | azalea_registry::Fluid::FlowingLava => { BlockState::from(crate::blocks::Lava { - level: crate::properties::LavaLevel::from(state.height as u32), + level: crate::properties::LavaLevel::from( + state.height as BlockStateIntegerRepr, + ), }) } } @@ -182,7 +212,10 @@ mod tests { #[test] fn test_from_u32() { - assert_eq!(BlockState::try_from(0).unwrap(), BlockState::AIR); + assert_eq!( + BlockState::try_from(0 as BlockStateIntegerRepr).unwrap(), + BlockState::AIR + ); assert!(BlockState::try_from(BlockState::MAX_STATE).is_ok()); assert!(BlockState::try_from(BlockState::MAX_STATE + 1).is_err()); diff --git a/azalea-block/src/range.rs b/azalea-block/src/range.rs index 9b520d49..779d805d 100644 --- a/azalea-block/src/range.rs +++ b/azalea-block/src/range.rs @@ -3,15 +3,15 @@ use std::{ ops::{Add, RangeInclusive}, }; -use crate::BlockState; +use crate::{BlockState, BlockStateIntegerRepr}; #[derive(Debug, Clone)] pub struct BlockStates { pub set: HashSet<BlockState>, } -impl From<RangeInclusive<u32>> for BlockStates { - fn from(range: RangeInclusive<u32>) -> Self { +impl From<RangeInclusive<BlockStateIntegerRepr>> for BlockStates { + fn from(range: RangeInclusive<BlockStateIntegerRepr>) -> Self { let mut set = HashSet::with_capacity((range.end() - range.start() + 1) as usize); for id in range { set.insert(BlockState { id }); |
