Start making block macro

This commit is contained in:
mat 2022-05-27 19:34:09 -05:00
parent aac64d0135
commit 88bc6d1660
7 changed files with 310 additions and 116 deletions

40
Cargo.lock generated
View file

@ -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"

View file

@ -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"}

View file

@ -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"

View file

@ -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<Ident, Token![,]>,
}
struct PropertyDefinitions {
properties: Vec<PropertyDefinition>,
}
struct BlockDefinition {
name: Ident,
behavior: Expr,
properties: Punctuated<Ident, Token![,]>,
}
struct BlockDefinitions {
blocks: Vec<BlockDefinition>,
}
struct MakeBlockStates {
property_definitions: PropertyDefinitions,
block_definitions: BlockDefinitions,
}
impl Parse for PropertyDefinition {
fn parse(input: ParseStream) -> Result<Self> {
// Face {
// Floor,
// Wall,
// Ceiling
// };
let name = input.parse()?;
let variants = input.parse_terminated(Ident::parse)?;
input.parse::<Token![;]>()?;
Ok(PropertyDefinition { name, variants })
}
}
impl Parse for PropertyDefinitions {
fn parse(input: ParseStream) -> Result<Self> {
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<Self> {
// acacia_button => BlockBehavior { has_collision: false }, {
// Face,
// Facing,
// Powered
// };
let name = input.parse()?;
input.parse::<Token![=>]>()?;
let behavior = input.parse()?;
input.parse::<Token![,]>()?;
let content;
braced!(content in input);
let properties = content.parse_terminated(Ident::parse)?;
input.parse::<Token![;]>()?;
Ok(BlockDefinition {
name,
behavior,
properties,
})
}
}
impl Parse for BlockDefinitions {
fn parse(input: ParseStream) -> Result<Self> {
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<Self> {
// PROPERTIES => { ... } BLOCKS => { ... }
let properties_ident = input.parse::<Ident>()?;
assert_eq!(properties_ident.to_string(), "PROPERTIES");
input.parse::<Token![=>]>()?;
let content;
braced!(content in input);
let properties = content.parse()?;
let blocks_ident = input.parse::<Ident>()?;
assert_eq!(blocks_ident.to_string(), "BLOCKS");
input.parse::<Token![=>]>()?;
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()
}

View file

@ -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<BlockState> 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<AcaciaButtonBlock> 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<BlockState> 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<AcaciaButtonBlock> 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!(),
// }
// }
// }

View file

@ -1,5 +1,3 @@
pub mod behavior;
pub mod blocks;
pub mod properties;
use std::fmt::Debug;

View file

@ -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,
}