From cf62babfe4e243841181cdacf81406de4f1dc363 Mon Sep 17 00:00:00 2001 From: lukas0008 Date: Wed, 18 Sep 2024 16:59:12 +0200 Subject: [PATCH 1/4] Make itertools a workspace dependency --- Cargo.lock | 2 ++ Cargo.toml | 2 ++ pumpkin-inventory/Cargo.toml | 2 +- pumpkin-protocol/Cargo.toml | 2 +- pumpkin-world/Cargo.toml | 2 +- pumpkin/Cargo.toml | 2 +- 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fff734d2..1caeddee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2003,6 +2003,8 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", + "serde", + "serde_json", "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 9b13bf54..bf45f7db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/pumpkin-inventory/Cargo.toml b/pumpkin-inventory/Cargo.toml index 29daefc7..dd6c4566 100644 --- a/pumpkin-inventory/Cargo.toml +++ b/pumpkin-inventory/Cargo.toml @@ -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 diff --git a/pumpkin-protocol/Cargo.toml b/pumpkin-protocol/Cargo.toml index 0c0ab129..70059083 100644 --- a/pumpkin-protocol/Cargo.toml +++ b/pumpkin-protocol/Cargo.toml @@ -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" } diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index 56f6dade..9244d9ba 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -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" diff --git a/pumpkin/Cargo.toml b/pumpkin/Cargo.toml index 839947f0..5e2948a1 100644 --- a/pumpkin/Cargo.toml +++ b/pumpkin/Cargo.toml @@ -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 From ee7d652bf1f803d18c42ba134b921956971e11ca Mon Sep 17 00:00:00 2001 From: lukas0008 Date: Wed, 18 Sep 2024 17:01:18 +0200 Subject: [PATCH 2/4] Move assets folder outside of pumpkin-world --- {pumpkin-world/assets => assets}/blocks.json | 0 {pumpkin-world/assets => assets}/items.json | 0 {pumpkin-world/assets => assets}/registries.json | 0 pumpkin-world/src/block/block_registry.rs | 2 +- pumpkin-world/src/global_registry.rs | 2 +- pumpkin-world/src/item/item_registry.rs | 2 +- 6 files changed, 3 insertions(+), 3 deletions(-) rename {pumpkin-world/assets => assets}/blocks.json (100%) rename {pumpkin-world/assets => assets}/items.json (100%) rename {pumpkin-world/assets => assets}/registries.json (100%) diff --git a/pumpkin-world/assets/blocks.json b/assets/blocks.json similarity index 100% rename from pumpkin-world/assets/blocks.json rename to assets/blocks.json diff --git a/pumpkin-world/assets/items.json b/assets/items.json similarity index 100% rename from pumpkin-world/assets/items.json rename to assets/items.json diff --git a/pumpkin-world/assets/registries.json b/assets/registries.json similarity index 100% rename from pumpkin-world/assets/registries.json rename to assets/registries.json diff --git a/pumpkin-world/src/block/block_registry.rs b/pumpkin-world/src/block/block_registry.rs index 7d7b3f69..cd06e98d 100644 --- a/pumpkin-world/src/block/block_registry.rs +++ b/pumpkin-world/src/block/block_registry.rs @@ -5,7 +5,7 @@ use serde::Deserialize; use super::block_id::BlockId; pub static BLOCKS: LazyLock> = 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.") }); diff --git a/pumpkin-world/src/global_registry.rs b/pumpkin-world/src/global_registry.rs index 19f8a6e6..f822b57a 100644 --- a/pumpkin-world/src/global_registry.rs +++ b/pumpkin-world/src/global_registry.rs @@ -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 { diff --git a/pumpkin-world/src/item/item_registry.rs b/pumpkin-world/src/item/item_registry.rs index f91dd300..756c30b4 100644 --- a/pumpkin-world/src/item/item_registry.rs +++ b/pumpkin-world/src/item/item_registry.rs @@ -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> = LazyLock::new(|| { serde_json::from_str(ITEMS_JSON).expect("Could not parse items.json registry.") From 79c67303864dda9fb4a57acc536c78ff71219476 Mon Sep 17 00:00:00 2001 From: lukas0008 Date: Wed, 18 Sep 2024 17:11:45 +0200 Subject: [PATCH 3/4] Make block_id macro --- Cargo.lock | 1 + pumpkin-macros/Cargo.toml | 3 + pumpkin-macros/src/block_id.rs | 136 +++++++++++++++++++++++++++++++++ pumpkin-macros/src/lib.rs | 6 ++ 4 files changed, 146 insertions(+) create mode 100644 pumpkin-macros/src/block_id.rs diff --git a/Cargo.lock b/Cargo.lock index 1caeddee..c7f798fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2001,6 +2001,7 @@ dependencies = [ name = "pumpkin-macros" version = "0.1.0" dependencies = [ + "itertools 0.13.0", "proc-macro2", "quote", "serde", diff --git a/pumpkin-macros/Cargo.toml b/pumpkin-macros/Cargo.toml index c677c7c0..5dca73b9 100644 --- a/pumpkin-macros/Cargo.toml +++ b/pumpkin-macros/Cargo.toml @@ -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" diff --git a/pumpkin-macros/src/block_id.rs b/pumpkin-macros/src/block_id.rs new file mode 100644 index 00000000..825de0b6 --- /dev/null +++ b/pumpkin-macros/src/block_id.rs @@ -0,0 +1,136 @@ +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, +} + +/// 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, +} + +/// 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, + + // 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>, +} + +static BLOCKS: LazyLock> = 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::::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() +} diff --git a/pumpkin-macros/src/lib.rs b/pumpkin-macros/src/lib.rs index 34615922..da53c14b 100644 --- a/pumpkin-macros/src/lib.rs +++ b/pumpkin-macros/src/lib.rs @@ -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) +} From d2f700ac1fe6eb95952848e546ae170fc929a23f Mon Sep 17 00:00:00 2001 From: lukas0008 Date: Wed, 18 Sep 2024 17:21:05 +0200 Subject: [PATCH 4/4] Cargo fmt --- pumpkin-macros/src/block_id.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pumpkin-macros/src/block_id.rs b/pumpkin-macros/src/block_id.rs index 825de0b6..796eeca5 100644 --- a/pumpkin-macros/src/block_id.rs +++ b/pumpkin-macros/src/block_id.rs @@ -109,7 +109,9 @@ pub fn block_id_impl(item: TokenStream) -> TokenStream { .states .iter() .find(|state| state.is_default) - .expect("Error inside blocks.json file: Every Block should have at least 1 default state") + .expect( + "Error inside blocks.json file: Every Block should have at least 1 default state", + ) .id } else { match block_info