From aac64d013546c8be3b992af63d70150155386c11 Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 27 May 2022 16:04:22 -0500 Subject: Start making azalea-block --- azalea-block/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 azalea-block/src/lib.rs (limited to 'azalea-block/src/lib.rs') diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs new file mode 100644 index 00000000..db94d081 --- /dev/null +++ b/azalea-block/src/lib.rs @@ -0,0 +1,5 @@ +pub mod behavior; +pub mod blocks; +pub mod properties; + +use std::fmt::Debug; -- cgit v1.2.3 From 88bc6d16602c163d122685997dc269d5d97a93a2 Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 27 May 2022 19:34:09 -0500 Subject: Start making block macro --- Cargo.lock | 40 +++++--- azalea-block/Cargo.toml | 5 +- azalea-block/block-macros/Cargo.toml | 14 +++ azalea-block/block-macros/src/lib.rs | 157 +++++++++++++++++++++++++++++ azalea-block/src/blocks.rs | 188 ++++++++++++++++++++--------------- azalea-block/src/lib.rs | 2 - azalea-block/src/properties.rs | 20 ---- 7 files changed, 310 insertions(+), 116 deletions(-) create mode 100644 azalea-block/block-macros/Cargo.toml create mode 100644 azalea-block/block-macros/src/lib.rs delete mode 100644 azalea-block/src/properties.rs (limited to 'azalea-block/src/lib.rs') diff --git a/Cargo.lock b/Cargo.lock index 87a6a3aa..09523320 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,6 +81,9 @@ dependencies = [ [[package]] name = "azalea-block" version = "0.1.0" +dependencies = [ + "block-macros", +] [[package]] name = "azalea-brigadier" @@ -200,6 +203,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bot" version = "0.1.0" @@ -971,11 +983,11 @@ checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -986,9 +998,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.10" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] @@ -1244,13 +1256,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.92" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1407,6 +1419,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + [[package]] name = "unicode-normalization" version = "0.1.19" @@ -1428,12 +1446,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "url" version = "2.2.2" diff --git a/azalea-block/Cargo.toml b/azalea-block/Cargo.toml index ea43e8ae..edeba385 100644 --- a/azalea-block/Cargo.toml +++ b/azalea-block/Cargo.toml @@ -1,8 +1,11 @@ [package] +edition = "2021" name = "azalea-block" version = "0.1.0" -edition = "2021" + +[lib] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +block-macros = {path = "./block-macros"} diff --git a/azalea-block/block-macros/Cargo.toml b/azalea-block/block-macros/Cargo.toml new file mode 100644 index 00000000..03b19e1d --- /dev/null +++ b/azalea-block/block-macros/Cargo.toml @@ -0,0 +1,14 @@ +[package] +edition = "2021" +name = "block-macros" +version = "0.1.0" + +[lib] +proc-macro = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +proc-macro2 = "1.0.39" +quote = "1.0.18" +syn = "1.0.95" diff --git a/azalea-block/block-macros/src/lib.rs b/azalea-block/block-macros/src/lib.rs new file mode 100644 index 00000000..20ec5f3e --- /dev/null +++ b/azalea-block/block-macros/src/lib.rs @@ -0,0 +1,157 @@ +use proc_macro::TokenStream; +use quote::{quote, ToTokens}; +use std::fmt::Debug; +use syn::{ + self, braced, + parse::{Parse, ParseStream, Result}, + parse_macro_input, + punctuated::Punctuated, + Data, DeriveInput, Expr, FieldsNamed, Ident, LitInt, Token, +}; + +struct PropertyDefinition { + name: Ident, + variants: Punctuated, +} +struct PropertyDefinitions { + properties: Vec, +} + +struct BlockDefinition { + name: Ident, + behavior: Expr, + properties: Punctuated, +} +struct BlockDefinitions { + blocks: Vec, +} +struct MakeBlockStates { + property_definitions: PropertyDefinitions, + block_definitions: BlockDefinitions, +} + +impl Parse for PropertyDefinition { + fn parse(input: ParseStream) -> Result { + // Face { + // Floor, + // Wall, + // Ceiling + // }; + let name = input.parse()?; + let variants = input.parse_terminated(Ident::parse)?; + input.parse::()?; + Ok(PropertyDefinition { name, variants }) + } +} + +impl Parse for PropertyDefinitions { + fn parse(input: ParseStream) -> Result { + let mut property_definitions = Vec::new(); + while !input.is_empty() { + property_definitions.push(input.parse()?); + } + + Ok(PropertyDefinitions { + properties: property_definitions, + }) + } +} + +impl Parse for BlockDefinition { + fn parse(input: ParseStream) -> Result { + // acacia_button => BlockBehavior { has_collision: false }, { + // Face, + // Facing, + // Powered + // }; + let name = input.parse()?; + input.parse::]>()?; + let behavior = input.parse()?; + input.parse::()?; + let content; + braced!(content in input); + let properties = content.parse_terminated(Ident::parse)?; + input.parse::()?; + Ok(BlockDefinition { + name, + behavior, + properties, + }) + } +} + +impl Parse for BlockDefinitions { + fn parse(input: ParseStream) -> Result { + let mut blocks = Vec::new(); + while !input.is_empty() { + blocks.push(input.parse()?); + } + + Ok(BlockDefinitions { blocks }) + } +} + +impl Parse for MakeBlockStates { + fn parse(input: ParseStream) -> Result { + // PROPERTIES => { ... } BLOCKS => { ... } + let properties_ident = input.parse::()?; + assert_eq!(properties_ident.to_string(), "PROPERTIES"); + input.parse::]>()?; + let content; + braced!(content in input); + let properties = content.parse()?; + + let blocks_ident = input.parse::()?; + assert_eq!(blocks_ident.to_string(), "BLOCKS"); + input.parse::]>()?; + let content; + braced!(content in input); + let blocks = content.parse()?; + + Ok(MakeBlockStates { + property_definitions: properties, + block_definitions: blocks, + }) + } +} + +#[proc_macro] +pub fn make_block_states(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as MakeBlockStates); + + let mut property_enums = quote! {}; + + for property in &input.property_definitions.properties { + let mut property_enum_variants = quote! {}; + + for variant in &property.variants { + property_enum_variants.extend(quote! { + #variant, + }); + } + + let property_name = property.name; + + property_enums.extend(quote! { + #[derive(Debug, Clone, Copy)] + pub enum #property_name { + #property_enum_variants + } + }); + } + + // 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); + // } + + quote! { + #property_enums + // #block_state_enum_variants + } + .into() +} diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index f6f33a89..6bc82a20 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -1,88 +1,118 @@ use crate::{behavior::BlockBehavior, properties}; -// make_block_states! { -// acacia_button => BlockBehavior { has_collision: false }, { -// Face, -// Facing, -// Powered -// }; -// acacia_door => BlockBehavior { has_collision: true }, { -// Facing, -// Half, -// Hinge, -// Open, -// Powered -// }; +make_block_states! { + PROPERTIES => { + Face { + Floor, + Wall, + Ceiling + }; + } + BLOCKS => { + acacia_button => BlockBehavior { has_collision: false }, { + Face, + Facing, + Powered + }; + acacia_door => BlockBehavior { has_collision: true }, { + Facing, + Half, + Hinge, + Open, + Powered + }; + } +} + +// #[derive(Debug, Clone, Copy)] +// pub enum Face { +// Floor, +// Wall, +// Ceiling, // } -// the underscore makes it more readable, so i think it's fine to allow it -#[allow(non_camel_case_types)] -pub enum BlockState { - AcaciaButton_FloorNorthTrue, - AcaciaButton_WallNorthTrue, - AcaciaButton_CeilingNorthTrue, -} +// #[derive(Debug, Clone, Copy)] +// pub enum Facing { +// North, +// South, +// West, +// East, +// } -pub trait Block { - fn behavior(&self) -> BlockBehavior; -} +// #[derive(Debug, Clone, Copy)] +// pub enum Powered { +// True, +// False, +// } -#[derive(Debug)] -pub struct AcaciaButtonBlock { - pub face: properties::Face, - pub facing: properties::Facing, - pub powered: properties::Powered, -} +// // the underscore makes it more readable, so i think it's fine to allow it +// #[allow(non_camel_case_types)] +// pub enum BlockState { +// AcaciaButton_FloorNorthTrue, +// AcaciaButton_WallNorthTrue, +// AcaciaButton_CeilingNorthTrue, +// } -impl Block for AcaciaButtonBlock { - fn behavior(&self) -> BlockBehavior { - BlockBehavior { - has_collision: false, - } - } -} +// pub trait Block { +// fn behavior(&self) -> BlockBehavior; +// } -pub struct AcaciaDoorBlock { - pub facing: properties::Facing, - // pub half: properties::Half, - // pub hinge: properties::Hinge, - // pub open: properties::Open, - pub powered: properties::Powered, -} +// #[derive(Debug)] +// pub struct AcaciaButtonBlock { +// pub face: properties::Face, +// pub facing: properties::Facing, +// pub powered: properties::Powered, +// } -impl From for &dyn Block { - fn from(b: BlockState) -> Self { - match b { - BlockState::AcaciaButton_FloorNorthTrue => &AcaciaButtonBlock { - face: properties::Face::Floor, - facing: properties::Facing::North, - powered: properties::Powered::True, - }, - // BlockState::AcaciaButton_WallNorthTrue => todo!(), - // BlockState::AcaciaButton_CeilingNorthTrue => todo!(), - _ => todo!(), - } - } -} -impl From for BlockState { - fn from(b: AcaciaButtonBlock) -> Self { - match b { - AcaciaButtonBlock { - face: properties::Face::Floor, - facing: properties::Facing::North, - powered: properties::Powered::True, - } => BlockState::AcaciaButton_FloorNorthTrue, - // AcaciaButtonBlock { - // face: properties::Face::Wall, - // facing: properties::Facing::North, - // powered: properties::Powered::True, - // } => todo!(), - // AcaciaButtonBlock { - // face: properties::Face::Ceiling, - // facing: properties::Facing::North, - // powered: properties::Powered::True, - // } => todo!(), - _ => todo!(), - } - } -} +// impl Block for AcaciaButtonBlock { +// fn behavior(&self) -> BlockBehavior { +// BlockBehavior { +// has_collision: false, +// } +// } +// } + +// pub struct AcaciaDoorBlock { +// pub facing: properties::Facing, +// // pub half: properties::Half, +// // pub hinge: properties::Hinge, +// // pub open: properties::Open, +// pub powered: properties::Powered, +// } + +// impl From for &dyn Block { +// fn from(b: BlockState) -> Self { +// match b { +// BlockState::AcaciaButton_FloorNorthTrue => &AcaciaButtonBlock { +// face: properties::Face::Floor, +// facing: properties::Facing::North, +// powered: properties::Powered::True, +// }, +// // BlockState::AcaciaButton_WallNorthTrue => todo!(), +// // BlockState::AcaciaButton_CeilingNorthTrue => todo!(), +// _ => todo!(), +// } +// } +// } +// impl From for BlockState { +// fn from(b: AcaciaButtonBlock) -> Self { +// match b { +// AcaciaButtonBlock { +// face: properties::Face::Floor, +// facing: properties::Facing::North, +// powered: properties::Powered::True, +// } => BlockState::AcaciaButton_FloorNorthTrue, +// // AcaciaButtonBlock { +// // face: properties::Face::Wall, +// // facing: properties::Facing::North, +// // powered: properties::Powered::True, +// // } => todo!(), +// // AcaciaButtonBlock { +// // face: properties::Face::Ceiling, +// // facing: properties::Facing::North, +// // powered: properties::Powered::True, +// // } => todo!(), +// _ => todo!(), +// } +// } +// } diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index db94d081..30f2aadc 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -1,5 +1,3 @@ pub mod behavior; pub mod blocks; pub mod properties; - -use std::fmt::Debug; diff --git a/azalea-block/src/properties.rs b/azalea-block/src/properties.rs deleted file mode 100644 index ac81fcb3..00000000 --- a/azalea-block/src/properties.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[derive(Debug, Clone, Copy)] -pub enum Face { - Floor, - Wall, - Ceiling, -} - -#[derive(Debug, Clone, Copy)] -pub enum Facing { - North, - South, - West, - East, -} - -#[derive(Debug, Clone, Copy)] -pub enum Powered { - True, - False, -} -- cgit v1.2.3 From c0433b7d4934caa5b1a42625d16058fcece2a86d Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 27 May 2022 19:36:18 -0500 Subject: Compiles --- azalea-block/block-macros/src/lib.rs | 8 ++++++-- azalea-block/src/blocks.rs | 3 ++- azalea-block/src/lib.rs | 1 - 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'azalea-block/src/lib.rs') diff --git a/azalea-block/block-macros/src/lib.rs b/azalea-block/block-macros/src/lib.rs index 20ec5f3e..d6c3465e 100644 --- a/azalea-block/block-macros/src/lib.rs +++ b/azalea-block/block-macros/src/lib.rs @@ -38,7 +38,11 @@ impl Parse for PropertyDefinition { // Ceiling // }; let name = input.parse()?; - let variants = input.parse_terminated(Ident::parse)?; + + let content; + braced!(content in input); + let variants = content.parse_terminated(Ident::parse)?; + input.parse::()?; Ok(PropertyDefinition { name, variants }) } @@ -130,7 +134,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { }); } - let property_name = property.name; + let property_name = &property.name; property_enums.extend(quote! { #[derive(Debug, Clone, Copy)] diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index 6bc82a20..a50e8804 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -1,4 +1,5 @@ -use crate::{behavior::BlockBehavior, properties}; +use crate::behavior::BlockBehavior; +use block_macros::make_block_states; make_block_states! { PROPERTIES => { diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index 30f2aadc..488e8e62 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -1,3 +1,2 @@ pub mod behavior; pub mod blocks; -pub mod properties; -- cgit v1.2.3 From 3573eb4ba04280cd25263fbe6e468b05036bc9cb Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 28 May 2022 01:12:12 -0500 Subject: more block macro stuff --- azalea-block/block-macros/src/lib.rs | 79 ++++++++++++++++++++++++++++++++++-- azalea-block/src/behavior.rs | 9 ++++ azalea-block/src/blocks.rs | 9 +++- azalea-block/src/lib.rs | 7 +++- 4 files changed, 97 insertions(+), 7 deletions(-) (limited to 'azalea-block/src/lib.rs') diff --git a/azalea-block/block-macros/src/lib.rs b/azalea-block/block-macros/src/lib.rs index 9cbd6ca3..0ad5af34 100644 --- a/azalea-block/block-macros/src/lib.rs +++ b/azalea-block/block-macros/src/lib.rs @@ -152,17 +152,40 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { } let mut block_state_enum_variants = quote! {}; + let mut block_structs = quote! {}; for block in &input.block_definitions.blocks { - let block_properties = &block.properties; + let block_property_names = &block + .properties + .iter() + .map(|p| p.to_string()) + .collect::>(); let mut block_properties_vec = Vec::new(); - for property in block_properties { - let property_name = &property.to_string(); + for property_name in block_property_names { let property_variants = properties_map .get(property_name) .expect(format!("Property '{}' not found", property_name).as_str()) .clone(); block_properties_vec.push(property_variants); } + + // pub face: properties::Face, + // pub facing: properties::Facing, + // pub powered: properties::Powered, + let mut block_struct_fields = quote! {}; + for property in &block.properties { + let property_name_snake = + Ident::new(&property.to_string(), proc_macro2::Span::call_site()); + block_struct_fields.extend(quote! { + pub #property_name_snake: #property, + }) + } + let block_struct_name = Ident::new( + &format!("{}Block", to_pascal_case(&block.name.to_string())), + proc_macro2::Span::call_site(), + ); + + let mut from_block_to_state_match = quote! {}; + for combination in combinations_of(&block_properties_vec) { let variant_name = Ident::new( &format!( @@ -179,7 +202,55 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { block_state_enum_variants.extend(quote! { #variant_name, }); + + // face: properties::Face::Floor, + // facing: properties::Facing::North, + // powered: properties::Powered::True, + let mut from_block_to_state_match_inner = quote! {}; + for i in 0..block_property_names.len() { + let property_name = &block_property_names[i]; + let property_name_ident = Ident::new(property_name, proc_macro2::Span::call_site()); + let property_name_snake = + Ident::new(&property_name.to_string(), proc_macro2::Span::call_site()); + let variant = + Ident::new(&combination[i].to_string(), proc_macro2::Span::call_site()); + + from_block_to_state_match_inner.extend(quote! { + #property_name_ident: #property_name_snake::#variant, + }); + } + + from_block_to_state_match.extend(quote! { + #block_struct_name { + #from_block_to_state_match_inner + } => BlockState::#variant_name, + }); } + + let block_behavior = &block.behavior; + let block_struct = quote! { + #[derive(Debug)] + pub struct #block_struct_name { + #block_struct_fields + } + + impl Block for #block_struct_name { + fn behavior(&self) -> BlockBehavior { + #block_behavior + } + } + + impl From<#block_struct_name> for BlockState { + fn from(b: #block_struct_name) -> Self { + match b { + #from_block_to_state_match + } + } + } + + }; + + block_structs.extend(block_struct); } quote! { @@ -188,6 +259,8 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { pub enum BlockState { #block_state_enum_variants } + + #block_structs } .into() } diff --git a/azalea-block/src/behavior.rs b/azalea-block/src/behavior.rs index 974260f2..949f3bd8 100644 --- a/azalea-block/src/behavior.rs +++ b/azalea-block/src/behavior.rs @@ -1,3 +1,12 @@ +#[derive(Default)] pub struct BlockBehavior { pub has_collision: bool, } + +impl BlockBehavior { + #[inline] + pub fn no_collision(mut self) -> Self { + self.has_collision = false; + self + } +} diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index 855de96b..d4339ada 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -1,5 +1,10 @@ +use crate::BlockBehavior; use block_macros::make_block_states; +pub trait Block { + fn behavior(&self) -> BlockBehavior; +} + make_block_states! { PROPERTIES => { Face { @@ -31,12 +36,12 @@ make_block_states! { }; } BLOCKS => { - acacia_button => BlockBehavior::new().no_collision(), { + acacia_button => BlockBehavior::default().no_collision(), { Face, Facing, Powered }; - acacia_door => BlockBehavior::new(), { + acacia_door => BlockBehavior::default(), { Facing, Half, Hinge, diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index 488e8e62..459b486e 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -1,2 +1,5 @@ -pub mod behavior; -pub mod blocks; +mod behavior; +mod blocks; + +pub use behavior::BlockBehavior; +pub use blocks::*; -- cgit v1.2.3 From 4f89f70091962c967a7022e6f293f11a446abc3c Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 16 Jun 2022 20:48:01 -0500 Subject: type -> kind --- azalea-block/src/blocks.rs | 6 +++--- azalea-block/src/lib.rs | 1 + codegen/lib/code/blocks.py | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'azalea-block/src/lib.rs') diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index 77fb8276..b8d204fd 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -272,7 +272,7 @@ make_block_states! { Upper, Lower, }, - "type" => PistonType { + "kind" => PistonType { Normal, Sticky, }, @@ -333,7 +333,7 @@ make_block_states! { OuterLeft, OuterRight, }, - "type" => ChestType { + "kind" => ChestType { Single, Left, Right, @@ -936,7 +936,7 @@ make_block_states! { _14, _15, }, - "type" => Type { + "kind" => Type { Top, Bottom, Double, diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index 459b486e..01c86b11 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -3,3 +3,4 @@ mod blocks; pub use behavior::BlockBehavior; pub use blocks::*; + diff --git a/codegen/lib/code/blocks.py b/codegen/lib/code/blocks.py index f6d6bb4b..4ab4917f 100644 --- a/codegen/lib/code/blocks.py +++ b/codegen/lib/code/blocks.py @@ -103,6 +103,10 @@ def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: li ending = property_name.split('_')[-1] if ending.isdigit(): property_name = property_name[:-(len(ending) + 1)] + + # `type` is a reserved keyword, so we use kind instead ¯\_(ツ)_/¯ + if property_name == 'type': + property_name = 'kind' property_struct_names_to_names[property_struct_name] = property_name properties.update(block_properties) -- cgit v1.2.3 From 74c3ae52f84d988b8bf3f0affe143d2cd2d8143a Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 16 Jun 2022 23:38:51 -0500 Subject: azalea-world uses azalea-block --- Cargo.lock | 1 + azalea-block/block-macros/src/lib.rs | 12 +++++++++++ azalea-block/src/lib.rs | 41 ++++++++++++++++++++++++++++++++++++ azalea-world/Cargo.toml | 1 + azalea-world/src/bit_storage.rs | 6 ++++++ azalea-world/src/lib.rs | 21 ++++++++++++------ 6 files changed, 76 insertions(+), 6 deletions(-) (limited to 'azalea-block/src/lib.rs') diff --git a/Cargo.lock b/Cargo.lock index 1ef95311..f3b5df08 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -183,6 +183,7 @@ dependencies = [ name = "azalea-world" version = "0.1.0" dependencies = [ + "azalea-block", "azalea-core", "azalea-nbt", "azalea-protocol", diff --git a/azalea-block/block-macros/src/lib.rs b/azalea-block/block-macros/src/lib.rs index d38062d4..6206bb65 100644 --- a/azalea-block/block-macros/src/lib.rs +++ b/azalea-block/block-macros/src/lib.rs @@ -461,9 +461,12 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { block_structs.extend(block_struct); } + let last_state_id = (state_id - 1) as u32; quote! { #property_enums + #[repr(u32)] + #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum BlockState { #block_state_enum_variants } @@ -479,6 +482,15 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { } } } + + impl BlockState { + /// Returns the highest possible state + #[inline] + pub fn max_state() -> u32 { + #last_state_id + } + } + } .into() } diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index 01c86b11..95e8ce37 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -4,3 +4,44 @@ mod blocks; pub use behavior::BlockBehavior; pub use blocks::*; +use std::mem; + +impl BlockState { + /// Transmutes a u32 to a block state. UB if the value is not a valid block + /// state. + #[inline] + pub unsafe fn from_u32_unsafe(state_id: u32) -> Self { + mem::transmute::(state_id) + } + + #[inline] + pub fn is_valid_state(state_id: u32) -> bool { + state_id <= Self::max_state() + } +} + +impl TryFrom for BlockState { + type Error = (); + + /// Safely converts a state id to a block state. + fn try_from(state_id: u32) -> Result { + if Self::is_valid_state(state_id) { + Ok(unsafe { Self::from_u32_unsafe(state_id) }) + } else { + Err(()) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_from_u32() { + assert_eq!(BlockState::try_from(0).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-world/Cargo.toml b/azalea-world/Cargo.toml index e8d81ac3..79e6155d 100644 --- a/azalea-world/Cargo.toml +++ b/azalea-world/Cargo.toml @@ -9,3 +9,4 @@ version = "0.1.0" azalea-core = {path = "../azalea-core"} azalea-nbt = {path = "../azalea-nbt"} azalea-protocol = {path = "../azalea-protocol"} +azalea-block = {path = "../azalea-block"} diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index aba52aef..c69cb216 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -188,6 +188,12 @@ impl BitStorage { let bit_index = (index - cell_index * self.values_per_long as usize) * self.bits; *cell = *cell & !(self.mask << bit_index) | (value & self.mask) << bit_index; } + + /// The number of entries. + #[inline] + pub fn size(&self) -> usize { + self.size + } } #[cfg(test)] diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 766c61f0..8777c0a3 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -8,6 +8,7 @@ use azalea_core::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos}; use azalea_protocol::mc_buf::{McBufReadable, McBufWritable}; pub use bit_storage::BitStorage; use palette::PalettedContainer; +use azalea_block::BlockState; use std::{ io::{Read, Write}, ops::{Index, IndexMut}, @@ -57,7 +58,7 @@ impl World { self.storage.view_center = *pos; } - pub fn get_block_state(&self, pos: &BlockPos) -> Option { + pub fn get_block_state(&self, pos: &BlockPos) -> Option { self.storage.get_block_state(pos, self.min_y) } } @@ -122,7 +123,7 @@ impl ChunkStorage { && (chunk_pos.z - self.view_center.z).unsigned_abs() <= self.chunk_radius } - pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option { + pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option { let chunk_pos = ChunkPos::from(pos); println!("chunk_pos {:?} block_pos {:?}", chunk_pos, pos); let chunk = &self[&chunk_pos]; @@ -175,7 +176,7 @@ impl Chunk { (y.div_floor(16) - min_section_index) as u32 } - pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> u32 { + pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> BlockState { let section_index = self.section_index(pos.y, min_y); // TODO: make sure the section exists let section = &self.sections[section_index as usize]; @@ -210,6 +211,14 @@ impl McBufReadable for Section { // "A section has more blocks than what should be possible. This is a bug!" // ); let states = PalettedContainer::read_with_type(buf, &PalettedContainerType::BlockStates)?; + for i in 0..states.storage.size() { + if !BlockState::is_valid_state(states.storage.get(i) as u32) { + return Err(format!( + "Invalid block state {} (index {}) found in section.", + states.storage.get(i), i + )); + } + } let biomes = PalettedContainer::read_with_type(buf, &PalettedContainerType::Biomes)?; Ok(Section { block_count, @@ -229,9 +238,9 @@ impl McBufWritable for Section { } impl Section { - // TODO: return a BlockState instead of a u32 - fn get(&self, pos: ChunkSectionBlockPos) -> u32 { + fn get(&self, pos: ChunkSectionBlockPos) -> BlockState { + // TODO: use the unsafe method and do the check earlier self.states - .get(pos.x as usize, pos.y as usize, pos.z as usize) + .get(pos.x as usize, pos.y as usize, pos.z as usize).try_into().expect("Invalid block state.") } } -- cgit v1.2.3 From d0fc7d0eff32687d7210b730584db2c3faa055ae Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 17 Jun 2022 16:27:58 -0500 Subject: ClientboundSetEquipmentPacket --- azalea-block/src/blocks.rs | 2 +- azalea-block/src/lib.rs | 56 ++++++++-------- .../game/clientbound_set_equipment_packet.rs | 74 ++++++++++++++++++++++ azalea-protocol/src/packets/game/mod.rs | 2 + azalea-world/src/lib.rs | 9 ++- codegen/lib/code/packet.py | 9 +-- codegen/lib/code/utils.py | 5 +- codegen/lib/code/version.py | 2 +- 8 files changed, 120 insertions(+), 39 deletions(-) create mode 100644 azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs (limited to 'azalea-block/src/lib.rs') diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index b8d204fd..05973797 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -4951,4 +4951,4 @@ make_block_states! { reinforced_deepslate => BlockBehavior::default(), { }, } -} \ No newline at end of file +} diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index 95e8ce37..a6de1e92 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -7,41 +7,41 @@ pub use blocks::*; use std::mem; impl BlockState { - /// Transmutes a u32 to a block state. UB if the value is not a valid block - /// state. - #[inline] - pub unsafe fn from_u32_unsafe(state_id: u32) -> Self { - mem::transmute::(state_id) - } - - #[inline] - pub fn is_valid_state(state_id: u32) -> bool { - state_id <= Self::max_state() - } + /// Transmutes a u32 to a block state. UB if the value is not a valid block + /// state. + #[inline] + pub unsafe fn from_u32_unsafe(state_id: u32) -> Self { + mem::transmute::(state_id) + } + + #[inline] + pub fn is_valid_state(state_id: u32) -> bool { + state_id <= Self::max_state() + } } impl TryFrom for BlockState { - type Error = (); - - /// Safely converts a state id to a block state. - fn try_from(state_id: u32) -> Result { - if Self::is_valid_state(state_id) { - Ok(unsafe { Self::from_u32_unsafe(state_id) }) - } else { - Err(()) - } - } + type Error = (); + + /// Safely converts a state id to a block state. + fn try_from(state_id: u32) -> Result { + if Self::is_valid_state(state_id) { + Ok(unsafe { Self::from_u32_unsafe(state_id) }) + } else { + Err(()) + } + } } #[cfg(test)] mod tests { - use super::*; + use super::*; - #[test] - fn test_from_u32() { - assert_eq!(BlockState::try_from(0).unwrap(), BlockState::Air); + #[test] + fn test_from_u32() { + assert_eq!(BlockState::try_from(0).unwrap(), BlockState::Air); - assert!(BlockState::try_from(BlockState::max_state()).is_ok()); - assert!(BlockState::try_from(BlockState::max_state() + 1).is_err()); - } + assert!(BlockState::try_from(BlockState::max_state()).is_ok()); + assert!(BlockState::try_from(BlockState::max_state() + 1).is_err()); + } } diff --git a/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs new file mode 100644 index 00000000..3acbd58f --- /dev/null +++ b/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs @@ -0,0 +1,74 @@ +use azalea_core::Slot; +use packet_macros::{GamePacket, McBuf}; + +use crate::mc_buf::{McBufReadable, McBufWritable}; + +#[derive(Clone, Debug, McBuf, GamePacket)] +pub struct ClientboundSetEquipmentPacket { + #[var] + pub entity: i32, + pub slots: EquipmentSlots, +} + +#[derive(Clone, Debug)] +pub struct EquipmentSlots { + pub slots: Vec<(EquipmentSlot, Slot)>, +} + +impl McBufReadable for EquipmentSlots { + fn read_into(buf: &mut impl std::io::Read) -> Result { + let mut slots = vec![]; + + loop { + let equipment_byte = u8::read_into(buf)?; + let equipment_slot = EquipmentSlot::from_byte(equipment_byte & 127) + .ok_or_else(|| format!("Invalid equipment slot byte {}", equipment_byte))?; + let item = Slot::read_into(buf)?; + slots.push((equipment_slot, item)); + if equipment_byte & 128 == 0 { + break; + }; + } + + Ok(EquipmentSlots { slots }) + } +} +impl McBufWritable for EquipmentSlots { + fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { + for i in 0..self.slots.len() { + let (equipment_slot, item) = &self.slots[i]; + let mut equipment_byte = *equipment_slot as u8; + if i != self.slots.len() - 1 { + equipment_byte |= 128; + } + equipment_byte.write_into(buf)?; + item.write_into(buf)?; + } + + Ok(()) + } +} + +#[derive(Clone, Debug, Copy, McBuf)] +pub enum EquipmentSlot { + MainHand = 0, + OffHand = 1, + Feet = 2, + Legs = 3, + Chest = 4, + Head = 5, +} + +impl EquipmentSlot { + pub fn from_byte(byte: u8) -> Option { + match byte { + 0 => Some(EquipmentSlot::MainHand), + 1 => Some(EquipmentSlot::OffHand), + 2 => Some(EquipmentSlot::Feet), + 3 => Some(EquipmentSlot::Legs), + 4 => Some(EquipmentSlot::Chest), + 5 => Some(EquipmentSlot::Head), + _ => None, + } + } +} diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index eee36788..c4435636 100755 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -37,6 +37,7 @@ pub mod clientbound_set_default_spawn_position_packet; pub mod clientbound_set_display_chat_preview_packet; pub mod clientbound_set_entity_data_packet; pub mod clientbound_set_entity_link_packet; +pub mod clientbound_set_equipment_packet; pub mod clientbound_set_experience_packet; pub mod clientbound_set_health_packet; pub mod clientbound_set_time_packet; @@ -104,6 +105,7 @@ declare_state_packets!( 0x4b: clientbound_set_display_chat_preview_packet::ClientboundSetDisplayChatPreviewPacket, 0x4d: clientbound_set_entity_data_packet::ClientboundSetEntityDataPacket, 0x4f: clientbound_entity_velocity_packet::ClientboundEntityVelocityPacket, + 0x50: clientbound_set_equipment_packet::ClientboundSetEquipmentPacket, 0x51: clientbound_set_experience_packet::ClientboundSetExperiencePacket, 0x52: clientbound_set_health_packet::ClientboundSetHealthPacket, 0x59: clientbound_set_time_packet::ClientboundSetTimePacket, diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 26566416..e651e455 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -4,11 +4,11 @@ mod bit_storage; mod palette; use crate::palette::PalettedContainerType; +use azalea_block::BlockState; use azalea_core::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos}; use azalea_protocol::mc_buf::{McBufReadable, McBufWritable}; pub use bit_storage::BitStorage; use palette::PalettedContainer; -use azalea_block::BlockState; use std::{ io::{Read, Write}, ops::{Index, IndexMut}, @@ -218,7 +218,8 @@ impl McBufReadable for Section { if !BlockState::is_valid_state(states.storage.get(i) as u32) { return Err(format!( "Invalid block state {} (index {}) found in section.", - states.storage.get(i), i + states.storage.get(i), + i )); } } @@ -245,6 +246,8 @@ impl Section { fn get(&self, pos: ChunkSectionBlockPos) -> BlockState { // TODO: use the unsafe method and do the check earlier self.states - .get(pos.x as usize, pos.y as usize, pos.z as usize).try_into().expect("Invalid block state.") + .get(pos.x as usize, pos.y as usize, pos.z as usize) + .try_into() + .expect("Invalid block state.") } } diff --git a/codegen/lib/code/packet.py b/codegen/lib/code/packet.py index 36e0ba0c..2aabf39a 100644 --- a/codegen/lib/code/packet.py +++ b/codegen/lib/code/packet.py @@ -1,6 +1,6 @@ -from .utils import burger_type_to_rust_type, write_packet_file -from ..utils import padded_hex, to_snake_case, to_camel_case -from ..mappings import Mappings +from lib.code.utils import burger_type_to_rust_type, write_packet_file +from lib.utils import padded_hex, to_snake_case, to_camel_case, get_dir_location +from lib.mappings import Mappings import os @@ -74,7 +74,8 @@ def generate_packet(burger_packets, mappings: Mappings, target_packet_id, target '\n'.join(generated_packet_code)) print() - mod_rs_dir = f'../azalea-protocol/src/packets/{state}/mod.rs' + mod_rs_dir = get_dir_location( + f'../azalea-protocol/src/packets/{state}/mod.rs') with open(mod_rs_dir, 'r') as f: mod_rs = f.read().splitlines() diff --git a/codegen/lib/code/utils.py b/codegen/lib/code/utils.py index 28a5ef3c..ecfff4fb 100644 --- a/codegen/lib/code/utils.py +++ b/codegen/lib/code/utils.py @@ -1,4 +1,5 @@ +from lib.utils import get_dir_location import os # utilities specifically for codegen @@ -67,9 +68,9 @@ def burger_type_to_rust_type(burger_type): def write_packet_file(state, packet_name_snake_case, code): - with open(f'../azalea-protocol/src/packets/{state}/{packet_name_snake_case}.rs', 'w') as f: + with open(get_dir_location(f'../azalea-protocol/src/packets/{state}/{packet_name_snake_case}.rs'), 'w') as f: f.write(code) def fmt(): - os.system('cd .. && cargo fmt') + os.system(f'cd {get_dir_location("..")} && cargo fmt') diff --git a/codegen/lib/code/version.py b/codegen/lib/code/version.py index 4c8500be..511d30d1 100644 --- a/codegen/lib/code/version.py +++ b/codegen/lib/code/version.py @@ -1,6 +1,6 @@ +from lib.utils import get_dir_location import re import os -from lib.utils import get_dir_location README_DIR = get_dir_location('../README.md') VERSION_REGEX = r'\*Currently supported Minecraft version: `(.*)`.\*' -- cgit v1.2.3