Skip to content

Commit

Permalink
Merge pull request #101 from Snowiiii/block-macro
Browse files Browse the repository at this point in the history
Add `block_id!` macro
  • Loading branch information
lukas0008 authored Sep 19, 2024
2 parents 8a48241 + d2f700a commit a30dbde
Show file tree
Hide file tree
Showing 15 changed files with 159 additions and 7 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ crossbeam = "0.8.4"
uuid = { version = "1.10.0", features = ["serde", "v3", "v4"] }
derive_more = { version = "1.0.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }

itertools = "0.13.0"
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion pumpkin-inventory/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ pumpkin-world = { path = "../pumpkin-world" }
num-traits = "0.2"
num-derive = "0.4"
thiserror = "1.0.63"
itertools = "0.13.0"
itertools.workspace = true
parking_lot.workspace = true
crossbeam.workspace = true
3 changes: 3 additions & 0 deletions pumpkin-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ proc-macro = true
proc-macro2 = "1.0"
quote = "1.0"
syn = "2.0"
serde.workspace = true
itertools.workspace = true
serde_json = "1.0.128"
138 changes: 138 additions & 0 deletions pumpkin-macros/src/block_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
use std::{collections::HashMap, sync::LazyLock};

use itertools::Itertools;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse::Parser;

#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
struct RegistryBlockDefinition {
/// e.g. minecraft:door or minecraft:button
#[serde(rename = "type")]
pub category: String,

/// Specifies the variant of the blocks category.
/// e.g. minecraft:iron_door has the variant iron
#[serde(rename = "block_set_type")]
pub variant: Option<String>,
}

/// One possible state of a Block.
/// This could e.g. be an extended piston facing left.
#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
struct RegistryBlockState {
pub id: i32,

/// Whether this is the default state of the Block
#[serde(default, rename = "default")]
pub is_default: bool,

/// The propertise active for this `BlockState`.
#[serde(default)]
pub properties: HashMap<String, String>,
}

/// A fully-fledged block definition.
/// Stores the category, variant, all of the possible states and all of the possible properties.
#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
struct RegistryBlockType {
pub definition: RegistryBlockDefinition,
pub states: Vec<RegistryBlockState>,

// TODO is this safe to remove? It's currently not used in the Project. @lukas0008 @Snowiiii
/// A list of valid property keys/values for a block.
#[serde(default, rename = "properties")]
valid_properties: HashMap<String, Vec<String>>,
}

static BLOCKS: LazyLock<HashMap<String, RegistryBlockType>> = LazyLock::new(|| {
serde_json::from_str(include_str!("../../assets/blocks.json"))
.expect("Could not parse block.json registry.")
});

pub fn block_id_impl(item: TokenStream) -> TokenStream {
let data = syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated
.parse(item)
.unwrap();
let block_name = data
.first()
.expect("The first argument should be a block name");

let block_name = match block_name {
syn::Expr::Lit(lit) => match &lit.lit {
syn::Lit::Str(name) => name.value(),
_ => panic!("The first argument should be a string"),
},
_ => panic!("The first argument should be a string"),
};

let mut properties = HashMap::new();
for expr_thingy in data.into_iter().skip(1) {
match expr_thingy {
syn::Expr::Assign(assign) => {
let left = match assign.left.as_ref() {
syn::Expr::Lit(lit) => match &lit.lit {
syn::Lit::Str(name) => name.value(),
_ => panic!(
"All not-first arguments should be assignments (\"foo\" = \"bar\")"
),
},
_ => {
panic!("All not-first arguments should be assignments (\"foo\" = \"bar\")")
}
};
let right = match assign.right.as_ref() {
syn::Expr::Lit(lit) => match &lit.lit {
syn::Lit::Str(name) => name.value(),
_ => panic!(
"All not-first arguments should be assignments (\"foo\" = \"bar\")"
),
},
_ => {
panic!("All not-first arguments should be assignments (\"foo\" = \"bar\")")
}
};
properties.insert(left, right);
}
_ => panic!("All not-first arguments should be assignments (\"foo\" = \"bar\")"),
}
}

// panic!("{:?}", properties);

let block_info = &BLOCKS
.get(&block_name)
.expect("Block with that name does not exist");

let id = if properties.is_empty() {
block_info
.states
.iter()
.find(|state| state.is_default)
.expect(
"Error inside blocks.json file: Every Block should have at least 1 default state",
)
.id
} else {
match block_info
.states
.iter()
.find(|state| state.properties == properties)
{
Some(state) => state.id,
None => panic!(
"Could not find block with these properties, the following are valid properties: \n{}",
block_info
.valid_properties
.iter()
.map(|(name, values)| format!("{name} = {}", values.join(" | ")))
.join("\n")
),
}
};

quote! {
pumpkin_world::block::block_id::BlockId::from_id(#id as u16)
}
.into()
}
6 changes: 6 additions & 0 deletions pumpkin-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@ pub fn packet(input: TokenStream, item: TokenStream) -> TokenStream {

gen.into()
}

mod block_id;
#[proc_macro]
pub fn block_id(item: TokenStream) -> TokenStream {
block_id::block_id_impl(item)
}
2 changes: 1 addition & 1 deletion pumpkin-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ num-derive = "0.4"
aes = "0.8.4"
cfb8 = "0.8.1"

itertools = "0.13.0"
itertools.workspace = true
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
2 changes: 1 addition & 1 deletion pumpkin-world/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
tokio.workspace = true
rayon.workspace = true
derive_more.workspace = true
itertools = "0.13.0"
itertools.workspace = true
thiserror = "1.0"
futures = "0.3"
flate2 = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion pumpkin-world/src/block/block_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use serde::Deserialize;
use super::block_id::BlockId;

pub static BLOCKS: LazyLock<HashMap<String, RegistryBlockType>> = LazyLock::new(|| {
serde_json::from_str(include_str!("../../assets/blocks.json"))
serde_json::from_str(include_str!("../../../assets/blocks.json"))
.expect("Could not parse block.json registry.")
});

Expand Down
2 changes: 1 addition & 1 deletion pumpkin-world/src/global_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{collections::HashMap, sync::LazyLock};

pub const ITEM_REGISTRY: &str = "minecraft:item";

const REGISTRY_JSON: &str = include_str!("../assets/registries.json");
const REGISTRY_JSON: &str = include_str!("../../assets/registries.json");

#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct RegistryElement {
Expand Down
2 changes: 1 addition & 1 deletion pumpkin-world/src/item/item_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::LazyLock};
use super::Rarity;
use crate::global_registry::{self, ITEM_REGISTRY};

const ITEMS_JSON: &str = include_str!("../../assets/items.json");
const ITEMS_JSON: &str = include_str!("../../../assets/items.json");

pub static ITEMS: LazyLock<HashMap<String, ItemElement>> = LazyLock::new(|| {
serde_json::from_str(ITEMS_JSON).expect("Could not parse items.json registry.")
Expand Down
2 changes: 1 addition & 1 deletion pumpkin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pumpkin-entity = { path = "../pumpkin-entity" }
pumpkin-protocol = { path = "../pumpkin-protocol" }
pumpkin-registry = { path = "../pumpkin-registry" }

itertools = "0.13.0"
itertools.workspace = true

# config
serde.workspace = true
Expand Down

0 comments on commit a30dbde

Please sign in to comment.