diff --git a/Cargo.toml b/Cargo.toml index d3d44dfc..866ac2d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,10 @@ members = [ "src/base/macros", "src/base/profiling", "src/base/threadpool", + "src/blocks", + "src/blocks/crates/property", + "src/blocks/crates/generated", + "src/blocks/crates/build", "src/bin", "src/commands", "src/components", @@ -115,6 +119,8 @@ debug = true # Workspace members temper-app = { path = "src/app" } temper-anvil = { path = "src/adapters/anvil" } +temper-blocks = { path = "src/blocks" } +temper-block-properties = { path = "src/blocks/crates/property" } temper-config = { path = "src/config" } temper-core = { path = "src/core" } temper-default-commands = { path = "src/default_commands" } diff --git a/src/blocks/Cargo.toml b/src/blocks/Cargo.toml new file mode 100644 index 00000000..ce5adc49 --- /dev/null +++ b/src/blocks/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "temper-blocks" +edition.workspace = true +version = "0.0.1" + +[dependencies] +temper-world = { workspace = true } +temper-block-properties = { workspace = true } +temper-blocks-generated = { path = "crates/generated" } +temper-core = { workspace = true } +temper-macros = { workspace = true } +bevy_math = { workspace = true } + +[build-dependencies] +temper-blocks-build = { path = "crates/build" } +quote = { workspace = true } + +[lints] +workspace = true diff --git a/src/blocks/README.md b/src/blocks/README.md new file mode 100644 index 00000000..669d4c7a --- /dev/null +++ b/src/blocks/README.md @@ -0,0 +1,76 @@ +# Temper Blocks + +This is a quick tutorial on how to use this library to create and modify block behavior and structs. + +## Overview + +This is a brief overview of what this crate is actually doing. This is split up into 2 distinct pieces, +the struct generator and the behavior implementation. + +The struct generator (the `temper-blocks-build` crate) is given the `build_config.toml` and `blockstates.json` files +and generates structs based off of groups of blockstates. For each block in `blockstates.json`, it +figures out which properties that block has. It will then collect blocks that have those same properties +and group them under the same struct. When it's saving the structs, it will look at the `build_config.toml` +file and rename structs according to the names in that file. The `build_config.toml` also provides the struct +names of various block state properties. The list of block state properties Minecraft uses can be found at +`net.minecraft.world.level.block.state.properties.BlockStateProperties` (as of 1.21.11). + +The next step is the block behavior implementations (this is the main crate). To add behavior to blocks, implement +the `BlockBehavior` trait for that block struct. The trait has already been implemented for all block +structs so far (to avoid unsafe features, such as `min_specialization`, it's not the most convenient, but it works). +The build script for this crate uses the `blockstates.json` file to generate a list that maps protocol ids (index) +to block states (value). This list is then used to dispatch behavior functions based on the protocol id. + +This crate also implements a helper trait on `BlockStateId` that allows you to call block functions directly from it +(and it will also be updated if the function mutates the block state). + +As a side note, the `temper-blocks-generated` crate contains the glue code to use the generated structs from +the build crate. The build crate outputs to the build directory and this crate imports those files back in. +Additionally, the `temper-block-properties` crate is where block state property structs and enums can be found. + +## Tips and Notes + +- If the build script is emitting a warning about an unknown block, see the **Adding / Modifying Block Structs** section for more information. + +## Creating Block Behavior + +To create a new function for blocks to implement, navigate to the `behavior_trait.rs` file. Due to the complexity of the inner workings of the system, a macro has been built to make creating functions for blocks super easy. The macro syntax is pretty simple: + +```rust +block_behavior_trait!( + fn ([mut]; ) [-> ; { { + name: &'a str, + properties: Vec<(&'a str, &'a str)>, + values: FxHashMap>, +} + +pub struct ComplexBlock { + pub name: String, + pub properties: FxHashMap, +} + +#[allow(clippy::type_complexity)] +pub struct FinalizedConfiguration<'a> { + name: String, + properties: &'a [(&'a str, &'a str)], + associated_blocks: Vec<(&'a str, &'a FxHashMap>)>, +} + +pub fn fill_complex_block_mappings( + build_config: &BuildConfig, + block_states: Vec<(u32, ComplexBlock)>, + mappings: &mut [TokenStream], +) -> Vec { + let (blocks, configs) = dedup_blocks(build_config, &block_states); + + let mut final_configs = collect_configurations(build_config, &configs, &blocks); + final_configs.sort_by(|a, b| a.name.cmp(&b.name)); + + final_configs + .into_iter() + .map(|config| { + let struct_name = format_ident!("{}", config.name); + let vtable_name = format_ident!("VTABLE_{}", config.name.to_shouty_snake_case()); + + config.associated_blocks + .iter() + .for_each(|(_, values)| { + values + .iter() + .for_each(|(id, _)| { + mappings[*id as usize] = quote! { crate::StateBehaviorTable::spin_off(&#vtable_name, #id) } + }); + }); + + quote! { + const #vtable_name: crate::BlockBehaviorTable = crate::BlockBehaviorTable::from::<#struct_name>(); + } + }) + .collect() +} + +#[allow(clippy::type_complexity)] +pub fn generate_complex_blocks( + build_config: &BuildConfig, + block_states: Vec<(u32, ComplexBlock)>, +) -> (Vec<((TokenStream, TokenStream), Ident)>, TokenStream) { + let (blocks, configs) = dedup_blocks(build_config, &block_states); + + let mut finalized_configs = collect_configurations(build_config, &configs, &blocks); + finalized_configs.sort_by(|a, b| a.name.cmp(&b.name)); + + let ((structs, impls), names): ((Vec, Vec), Vec) = + finalized_configs + .into_iter() + .map( + |FinalizedConfiguration { + name, + properties: config, + associated_blocks, + }| { + let fields = config + .iter() + .map(|(name, _)| match *name { + "type" => format_ident!("ty"), + str => format_ident!("{str}"), + }) + .collect::>(); + + let types = config + .iter() + .map(|(_, value)| format_ident!("{value}")) + .collect::>(); + + if name.starts_with("GeneratedStruct") { + println!("cargo::warning=Unknown block type detected. See src/blocks/README.md for more information. (Saved as {}, associated blocks: {:?})", + name, + associated_blocks + .iter() + .map(|(name, _)| name) + ); + } + + let struct_name = format_ident!("{name}"); + + match associated_blocks.len() { + 0 => panic!("No blocks for {struct_name}"), + 1 => { + let trait_impl = generate_trait_impls( + &struct_name, + None, + config, + &associated_blocks, + ); + + ( + ( + quote! { + #[allow(unused_imports)] + use temper_block_properties::*; + + #[allow(dead_code)] + #[derive(Clone, Debug)] + pub struct #struct_name { + #(pub #fields: #types,)* + } + }, + quote! { + #[allow(unused_imports)] + use temper_block_properties::*; + use crate::#struct_name; + + #trait_impl + }, + ), + struct_name, + ) + } + _ => { + let mut variants = associated_blocks + .iter() + .map(|(name, _)| { + format_ident!( + "{}", + name.strip_prefix("minecraft:") + .unwrap_or(name) + .to_pascal_case() + ) + }) + .collect::>(); + + variants.sort(); + + let enum_name = format_ident!("{}Type", struct_name); + let trait_impl = generate_trait_impls( + &struct_name, + Some((&enum_name, &variants)), + config, + &associated_blocks, + ); + + ( + ( + quote! { + #[allow(unused_imports)] + use temper_block_properties::*; + + #[allow(dead_code)] + #[derive(Clone, Debug)] + pub enum #enum_name { + #(#variants,)* + } + + #[allow(dead_code)] + #[derive(Clone, Debug)] + pub struct #struct_name { + pub block_type: #enum_name, + #(pub #fields: #types),* + } + }, + quote! { + #[allow(unused_imports)] + use temper_block_properties::*; + use crate::#struct_name; + use crate::#enum_name; + + #trait_impl + }, + ), + struct_name, + ) + } + } + }, + ) + .unzip(); + + let mod_names = names + .iter() + .map(|name| format_ident!("{}", name.to_string().to_snake_case())) + .collect::>(); + + let impl_names = mod_names + .iter() + .map(|name| format_ident!("{}_impl", name)) + .collect::>(); + + let modules = quote! { + #( + mod #mod_names; + mod #impl_names; + pub use #mod_names::*; + )* + }; + + let data = structs + .into_iter() + .zip(impls) + .zip(names) + .collect::>(); + + (data, modules) +} + +fn property_descriptor_of(key: &str) -> &PropertyDescriptor { + TYPES + .get(key) + .unwrap_or_else(|| panic!("Property type for {key} not found!")) +} + +fn get_field_values( + values: &[(&String, &String)], + properties: &[(&str, &str)], +) -> (Vec, Vec) { + values + .iter() + .map(|(field, value)| { + ( + match field.as_str() { + "type" => format_ident!("ty"), + field => format_ident!("{field}"), + }, + { + let ty = &properties + .iter() + .find(|(name1, _)| name1 == field) + .unwrap() + .1; + (property_descriptor_of(ty).ident_for)(value) + }, + ) + }) + .unzip() +} + +#[allow(clippy::type_complexity)] +fn generate_trait_impls( + struct_name: &Ident, + enum_name: Option<(&Ident, &[Ident])>, + properties: &[(&str, &str)], + values: &[(&str, &FxHashMap>)], +) -> TokenStream { + let (from_match_arms, into_match_arms): (Vec, Vec) = match enum_name { + Some((enum_name, enum_variants)) => { + let mut values = values.iter().collect::>(); + values.sort_by_key(|(name, _)| name); + + values.iter() + .flat_map(|(name, values)| { + let name_ident = format_ident!("{}", name.strip_prefix("minecraft:").unwrap_or(name).to_pascal_case()); + + match enum_variants.iter().find(|variant| *variant == &name_ident) { + Some(variant) => { + let mut values = values.iter().collect::>(); + values.sort_by_key(|(id, _)| *id); + + let mut out = Vec::with_capacity(values.len()); + + for (id, values) in values { + let mut values = values + .iter() + .collect::>(); + + values.sort_by_key(|(field, _)| field.as_str()); + + let (fields, values) = get_field_values(&values, properties); + + let data = quote! { + #struct_name { block_type: #enum_name::#variant, #(#fields: #values),* } + }; + + out.push(( + quote! { + #id => Ok(#data) + }, + quote! { + #data => Ok(#id) + } + )) + } + + out + }, + None => panic!("could not find {} enum variant for {}", enum_name, name), + } + }) + .unzip() + } + None => { + let (_, values) = &values[0]; + + let mut values = values.iter().collect::>(); + values.sort_by_key(|(id, _)| *id); + + values + .into_iter() + .map(|(id, values)| { + let mut values = values.iter().collect::>(); + + values.sort_by_key(|(field, _)| field.as_str()); + + let (fields, values) = get_field_values(&values, properties); + + let data = quote! { + #struct_name { #(#fields: #values),* } + }; + + ( + quote! { + #id => Ok(#data) + }, + quote! { + #data => Ok(#id) + }, + ) + }) + .unzip() + } + }; + + quote! { + impl TryFrom for #struct_name { + type Error = (); + + fn try_from(data: u32) -> Result { + match data { + #(#from_match_arms),*, + _ => Err(()) + } + } + } + + impl TryInto for #struct_name { + type Error = (); + + fn try_into(self) -> Result { + #[allow(unreachable_patterns)] + match self { + #(#into_match_arms),*, + _ => Err(()) + } + } + } + } +} + +fn struct_name(config: &BuildConfig, num_structs: usize, properties: &[(&str, &str)]) -> String { + let prop_str = properties.iter().map(|(name, _)| *name).collect::>(); + let prop_str = prop_str.join("+"); + + match config.name_overrides.iter().find(|(key, _)| { + let mut split = key + .split("+") + .map(|str| str.to_string()) + .collect::>(); + split.sort(); + let new_key = split.join("+"); + + new_key == prop_str + }) { + None => format!("GeneratedStruct{}", num_structs), + Some((_, struct_name)) => struct_name.clone(), + } +} + +#[allow(clippy::type_complexity)] +fn dedup_blocks<'a>( + build_config: &'a BuildConfig, + block_states: &'a [(u32, ComplexBlock)], +) -> ( + Vec>, + Vec>, +) { + let mut missing_types = build_config + .property_types + .values() + .flatten() + .filter(|str| !TYPES.contains_key(str.as_str())) + .collect::>(); + + missing_types.sort(); + missing_types.dedup(); + + if !missing_types.is_empty() { + panic!("Missing types for {:?}", missing_types); + } + + let configurations: FxHashMap<&str, FxHashMap>> = block_states + .iter() + .map(|(id, block)| (block.name.as_str(), (*id, &block.properties))) + .fold(FxHashMap::default(), |mut acc, (k, v)| { + acc.entry(k) + .or_insert_with(FxHashMap::default) + .insert(v.0, v.1); + acc + }); + + let blocks = configurations + .into_iter() + .map(|(name, properties)| { + let property_values = properties + .values() + .flat_map(|properties| { + properties.iter().map(|(name, value)| { + let name = name.as_str(); + let value = value.as_str(); + let possible_types: Vec<&str> = match build_config.property_types.get(name) + { + None => panic!("Property type for {name} not found!"), + Some(SingleOrMultiple::Single(ty)) => vec![ty.as_str()], + Some(SingleOrMultiple::Multiple(ty)) => { + ty.iter().map(String::as_str).collect() + } + }; + + (name, (possible_types, value)) + }) + }) + .fold(HashMap::new(), |mut acc, (k, v)| { + acc.entry(k) + .or_insert_with(|| (v.0, Vec::new())) + .1 + .push(v.1); + + acc + }); + + let mut property_map: Vec<(&str, &str)> = property_values + .into_iter() + .map(|(name, (possible_types, values))| { + let property_type = possible_types + .into_iter() + .find(|ty| { + values + .iter() + .all(|value| (property_descriptor_of(ty).matches_values)(value)) + }) + .unwrap_or_else(|| { + panic!("Failed to find property type for values {values:?}") + }); + + (name, property_type) + }) + .collect(); + + property_map.sort(); + + BlockStateConfiguration { + name, + properties: property_map, + values: properties, + } + }) + .collect::>(); + + let mut configs = blocks + .iter() + .map(|block| block.properties.to_vec()) + .collect::>(); + + configs.sort(); + configs.dedup(); + + (blocks, configs) +} + +fn collect_configurations<'a>( + build_config: &'a BuildConfig, + configs: &'a [Vec<(&'a str, &'a str)>], + blocks: &'a [BlockStateConfiguration<'a>], +) -> Vec> { + let mut num_structs = 0; + + configs + .iter() + .flat_map(|config| { + let associated_blocks = blocks + .iter() + .filter(|block| &block.properties == config) + .collect::>(); + + let mut configs = vec![FinalizedConfiguration { + name: struct_name(build_config, num_structs, config), + properties: config, + associated_blocks: Vec::with_capacity(associated_blocks.len()), + }]; + + for block in associated_blocks { + if let Some(name) = build_config.block_overrides.get(block.name) { + match configs + .iter_mut() + .find(|config| config.name == name.as_str()) + { + Some(config) => config.associated_blocks.push((block.name, &block.values)), + None => configs.push(FinalizedConfiguration { + name: name.clone(), + properties: config.as_slice(), + associated_blocks: vec![(block.name, &block.values)], + }), + } + } else { + configs[0] + .associated_blocks + .push((block.name, &block.values)); + } + } + + if configs[0].associated_blocks.is_empty() { + configs.remove(0); + } + + num_structs += 1; + + configs + }) + .collect() +} diff --git a/src/blocks/crates/build/src/config.rs b/src/blocks/crates/build/src/config.rs new file mode 100644 index 00000000..bfcb698e --- /dev/null +++ b/src/blocks/crates/build/src/config.rs @@ -0,0 +1,44 @@ +use crate::BlockState; +use serde::Deserialize; +use std::collections::HashMap; + +#[derive(Deserialize)] +#[serde(untagged)] +pub enum SingleOrMultiple { + Single(String), + Multiple(Vec), +} + +#[derive(Deserialize)] +pub struct BuildConfig { + pub name_overrides: HashMap, + pub block_overrides: HashMap, + pub property_types: HashMap, +} + +pub const BUILD_CONFIG: &str = include_str!("../../../build_config.toml"); +pub const BLOCK_STATES: &str = include_str!("../../../../../assets/data/blockstates.json"); + +pub fn get_build_config() -> BuildConfig { + toml::from_str(BUILD_CONFIG).unwrap() +} + +pub fn get_block_states() -> HashMap { + let out: HashMap = serde_json::from_str(BLOCK_STATES).unwrap(); + + out.into_iter() + .map(|(k, v)| (k.parse::().unwrap(), v)) + .collect() +} + +impl<'a> IntoIterator for &'a SingleOrMultiple { + type Item = &'a String; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + match self { + SingleOrMultiple::Single(v) => vec![v].into_iter(), + SingleOrMultiple::Multiple(vals) => vals.iter().collect::>().into_iter(), + } + } +} diff --git a/src/blocks/crates/build/src/lib.rs b/src/blocks/crates/build/src/lib.rs new file mode 100644 index 00000000..f120c05b --- /dev/null +++ b/src/blocks/crates/build/src/lib.rs @@ -0,0 +1,68 @@ +use crate::complex::ComplexBlock; +use fxhash::FxHashMap; +use serde::Deserialize; +use std::collections::HashMap; +use std::io::Write; + +pub mod complex; +pub mod config; +pub mod simple; + +#[derive(Deserialize, Debug)] +pub struct BlockState { + name: String, + properties: Option>, +} + +#[allow(clippy::type_complexity)] +pub fn separate_blocks( + input: HashMap, +) -> (Vec<(u32, String)>, Vec<(u32, ComplexBlock)>) { + let mut simple_blocks = Vec::new(); + let mut complex_blocks = Vec::new(); + + for (id, state) in input.into_iter() { + match state.properties { + Some(properties) => complex_blocks.push(( + id, + ComplexBlock { + name: state.name, + properties: FxHashMap::from_iter(properties.into_iter()), + }, + )), + None => simple_blocks.push((id, state.name)), + } + } + + (simple_blocks, complex_blocks) +} + +pub fn format_code(unformatted_code: &str) -> String { + let mut child = std::process::Command::new("rustfmt") + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .spawn() + .expect("Failed to spawn rustfmt process."); + + child + .stdin + .take() + .expect("Failed to take rustfmt stdin") + .write_all(unformatted_code.as_bytes()) + .expect("Failed to write to rustfmt stdin."); + + let output = child + .wait_with_output() + .expect("Failed to wait for rustfmt process."); + + if output.status.success() { + String::from_utf8(output.stdout).expect("rustfmt output was not valid UTF-8.") + } else { + panic!( + "rustfmt failed with status: {}\n--- stderr ---\n{}", + output.status, + String::from_utf8_lossy(&output.stderr) + ); + } +} diff --git a/src/blocks/crates/build/src/simple.rs b/src/blocks/crates/build/src/simple.rs new file mode 100644 index 00000000..06f47631 --- /dev/null +++ b/src/blocks/crates/build/src/simple.rs @@ -0,0 +1,70 @@ +use heck::ToPascalCase; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; + +pub fn fill_simple_block_mappings( + simple_blocks: Vec<(u32, String)>, + mappings: &mut [TokenStream], +) -> TokenStream { + for (id, _) in simple_blocks { + mappings[id as usize] = + quote! { crate::StateBehaviorTable::spin_off(&VTABLE_SIMPLE_BLOCK, #id) }; + } + + quote! { + const VTABLE_SIMPLE_BLOCK: crate::BlockBehaviorTable = crate::BlockBehaviorTable::from::(); + } +} + +pub fn generate_simple_block_enum( + mut simple_blocks: Vec<(u32, String)>, +) -> (TokenStream, TokenStream) { + simple_blocks.sort_by_key(|(id, _)| *id); + + let mut map_entries = Vec::new(); + let mut from_arms = Vec::new(); + let mut enum_variants = Vec::new(); + + for (id, name) in simple_blocks { + let variant = name.strip_prefix("minecraft:").unwrap_or(&name); + let variant = format_ident!("{}", variant.to_pascal_case()); + + enum_variants.push(quote! { #variant }); + from_arms.push(quote! { #id => Ok(SimpleBlock::#variant) }); + map_entries.push(quote! { #id }); + } + + ( + quote! { + #[repr(usize)] + #[derive(Clone, Debug)] + pub enum SimpleBlock { + #(#enum_variants),* + } + }, + quote! { + const SIMPLE_BLOCK_STATE_MAP: &[u32] = &[ + #(#map_entries,)* + ]; + + impl TryFrom for SimpleBlock { + type Error = (); + + fn try_from(data: u32) -> Result { + match data { + #(#from_arms),*, + _ => Err(()) + } + } + } + + impl TryInto for SimpleBlock { + type Error = (); + + fn try_into(self) -> Result { + Ok(SIMPLE_BLOCK_STATE_MAP[self as usize]) + } + } + }, + ) +} diff --git a/src/blocks/crates/generated/Cargo.toml b/src/blocks/crates/generated/Cargo.toml new file mode 100644 index 00000000..8fd32b3a --- /dev/null +++ b/src/blocks/crates/generated/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "temper-blocks-generated" +version = "0.1.0" +edition = "2024" + +[dependencies] +temper-block-properties = { path = "../property" } + +[build-dependencies] +temper-blocks-build = { path = "../build" } +heck = "0.5" +quote = { workspace = true } \ No newline at end of file diff --git a/src/blocks/crates/generated/build.rs b/src/blocks/crates/generated/build.rs new file mode 100644 index 00000000..95db2fa5 --- /dev/null +++ b/src/blocks/crates/generated/build.rs @@ -0,0 +1,57 @@ +use heck::ToSnakeCase; +use std::fs; +use temper_blocks_build::complex::generate_complex_blocks; +use temper_blocks_build::config::{get_block_states, get_build_config}; +use temper_blocks_build::simple::generate_simple_block_enum; +use temper_blocks_build::{format_code, separate_blocks}; + +fn main() { + let build_config = get_build_config(); + let block_states = get_block_states(); + + let (simple_blocks, complex_blocks) = separate_blocks(block_states); + + let (simple_enum, enum_impl) = generate_simple_block_enum(simple_blocks); + let (block_structs, block_mod) = generate_complex_blocks(&build_config, complex_blocks); + + let out_dir = std::env::var("OUT_DIR").unwrap(); + + let enum_impl = quote::quote! { + use crate::SimpleBlock; + + #enum_impl + }; + + fs::write( + format!("{}/blocks.rs", out_dir), + format_code(&block_mod.to_string()), + ) + .unwrap(); + fs::write( + format!("{}/simple.rs", out_dir), + format_code(&simple_enum.to_string()), + ) + .unwrap(); + fs::write( + format!("{}/simple_impl.rs", out_dir), + format_code(&enum_impl.to_string()), + ) + .unwrap(); + + block_structs + .into_iter() + .for_each(|((structure, struct_impl), name)| { + let mod_name = name.to_string().to_snake_case(); + + fs::write( + format!("{}/{}.rs", out_dir, mod_name), + format_code(&structure.to_string()), + ) + .unwrap(); + fs::write( + format!("{}/{}_impl.rs", out_dir, mod_name), + format_code(&struct_impl.to_string()), + ) + .unwrap(); + }); +} diff --git a/src/blocks/crates/generated/src/blocks.rs b/src/blocks/crates/generated/src/blocks.rs new file mode 100644 index 00000000..e45e5b88 --- /dev/null +++ b/src/blocks/crates/generated/src/blocks.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/blocks.rs")); diff --git a/src/blocks/crates/generated/src/lib.rs b/src/blocks/crates/generated/src/lib.rs new file mode 100644 index 00000000..e5fc53e9 --- /dev/null +++ b/src/blocks/crates/generated/src/lib.rs @@ -0,0 +1,6 @@ +mod blocks; +mod simple; +mod simple_impl; + +pub use blocks::*; +pub use simple::*; diff --git a/src/blocks/crates/generated/src/simple.rs b/src/blocks/crates/generated/src/simple.rs new file mode 100644 index 00000000..bbf103d3 --- /dev/null +++ b/src/blocks/crates/generated/src/simple.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/simple.rs")); diff --git a/src/blocks/crates/generated/src/simple_impl.rs b/src/blocks/crates/generated/src/simple_impl.rs new file mode 100644 index 00000000..496435cc --- /dev/null +++ b/src/blocks/crates/generated/src/simple_impl.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/simple_impl.rs")); diff --git a/src/blocks/crates/property/Cargo.toml b/src/blocks/crates/property/Cargo.toml new file mode 100644 index 00000000..86235c0d --- /dev/null +++ b/src/blocks/crates/property/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "temper-block-properties" +version = "0.1.0" +edition = "2024" + +[dependencies] +bevy_math = { workspace = true } +proc-macro2 = { workspace = true, optional = true } +quote = { workspace = true, optional = true } +lazy_static = { workspace = true, optional = true } + +[features] +default = [] +block-struct-generation = ["dep:proc-macro2", "dep:quote", "dep:lazy_static"] \ No newline at end of file diff --git a/src/blocks/crates/property/src/double_block_half.rs b/src/blocks/crates/property/src/double_block_half.rs new file mode 100644 index 00000000..a886bed5 --- /dev/null +++ b/src/blocks/crates/property/src/double_block_half.rs @@ -0,0 +1,24 @@ +use crate::enum_property; +use bevy_math::IVec3; + +enum_property!( + DoubleBlockHalf, + Upper => "upper", + Lower => "lower", +); + +impl DoubleBlockHalf { + pub fn other_half(&self) -> Self { + match self { + Self::Upper => Self::Lower, + Self::Lower => Self::Upper, + } + } + + pub fn direction_to_other(&self) -> IVec3 { + match self { + Self::Upper => IVec3::new(0, -1, 0), + Self::Lower => IVec3::new(0, 1, 0), + } + } +} diff --git a/src/blocks/crates/property/src/lib.rs b/src/blocks/crates/property/src/lib.rs new file mode 100644 index 00000000..0ec4007a --- /dev/null +++ b/src/blocks/crates/property/src/lib.rs @@ -0,0 +1,149 @@ +use std::str::FromStr; + +mod double_block_half; +mod note_block_instrument; +mod simple; + +pub use double_block_half::DoubleBlockHalf; +pub use note_block_instrument::NoteBlockInstrument; +pub use simple::*; + +#[cfg(feature = "block-struct-generation")] +lazy_static::lazy_static! { + pub static ref TYPES: std::collections::HashMap<&'static str, PropertyDescriptor> = { + let mut map = std::collections::HashMap::new(); + + map.insert("i32", PropertyDescriptor::I32); + map.insert("bool", PropertyDescriptor::BOOL); + map.insert("AttachFace", AttachFace::DESCRIPTOR); + map.insert("Axis", Axis::DESCRIPTOR); + map.insert("BambooLeaves", BambooLeaves::DESCRIPTOR); + map.insert("BedPart", BedPart::DESCRIPTOR); + map.insert("BellAttachType", BellAttachType::DESCRIPTOR); + map.insert("ChestType", ChestType::DESCRIPTOR); + map.insert("CreakingHeartState", CreakingHeartState::DESCRIPTOR); + map.insert("ComparatorMode", ComparatorMode::DESCRIPTOR); + map.insert("Direction", Direction::DESCRIPTOR); + map.insert("DoorHingeSide", DoorHingeSide::DESCRIPTOR); + map.insert("DoubleBlockHalf", DoubleBlockHalf::DESCRIPTOR); + map.insert("DripstoneThickness", DripstoneThickness::DESCRIPTOR); + map.insert("FrontAndTop", FrontAndTop::DESCRIPTOR); + map.insert("Half", Half::DESCRIPTOR); + map.insert("NoteBlockInstrument", NoteBlockInstrument::DESCRIPTOR); + map.insert("PistonType", PistonType::DESCRIPTOR); + map.insert("CopperGolemPose", CopperGolemPose::DESCRIPTOR); + map.insert("RailShape", RailShape::DESCRIPTOR); + map.insert("RedstoneSide", RedstoneSide::DESCRIPTOR); + map.insert("SculkSensorPhase", SculkSensorPhase::DESCRIPTOR); + map.insert("SideChainPart", SideChainPart::DESCRIPTOR); + map.insert("SlabType", SlabType::DESCRIPTOR); + map.insert("StairsShape", StairsShape::DESCRIPTOR); + map.insert("StructureMode", StructureMode::DESCRIPTOR); + map.insert("TestBlockMode", TestBlockMode::DESCRIPTOR); + map.insert("Tilt", Tilt::DESCRIPTOR); + map.insert("TrialSpawnerState", TrialSpawnerState::DESCRIPTOR); + map.insert("VaultState", VaultState::DESCRIPTOR); + map.insert("WallSide", WallSide::DESCRIPTOR); + + map + }; +} + +#[cfg(feature = "block-struct-generation")] +pub struct PropertyDescriptor { + pub matches_values: fn(&str) -> bool, + pub ident_for: fn(&str) -> proc_macro2::TokenStream, +} + +#[cfg(feature = "block-struct-generation")] +impl PropertyDescriptor { + const I32: PropertyDescriptor = PropertyDescriptor { + matches_values: |str| str.parse::().is_ok(), + ident_for: |str| { + let val = str.parse::().expect("failed to parse i32"); + quote::quote! { #val } + }, + }; + + const BOOL: PropertyDescriptor = PropertyDescriptor { + matches_values: |str| matches!(str, "true" | "false"), + ident_for: |str| { + let val = str.parse::().expect("failed to parse bool"); + quote::quote! { #val } + }, + }; +} + +/// Marker trait for types that can be used as block state property values +pub trait BlockStateProperty: FromStr + ToString { + fn values(&self) -> &[&str] { + &[] + } +} + +impl BlockStateProperty for i32 {} +impl BlockStateProperty for bool {} + +/// Helper macro to implement enum property types. The syntax is simple: +/// +/// ```rust +/// enum_property!( +/// MyBlockStateProperty, // Enum name +/// A => "a", // Enum variants and their block state property string value +/// West => "west", +/// // Etc... +/// ); +/// ``` +#[macro_export] +macro_rules! enum_property { + ($name:ident, $($variant:ident => $variant_str:expr),* $(,)?) => { + #[derive(Clone, Debug)] + pub enum $name { + $($variant),* + } + + #[cfg(feature = "block-struct-generation")] + impl $name { + pub const DESCRIPTOR: $crate::PropertyDescriptor = $crate::PropertyDescriptor { + matches_values: Self::matches_values, + ident_for: Self::ident_for, + }; + + fn matches_values(str: &str) -> bool { + matches!(str, $($variant_str)|*) + } + + fn ident_for(str: &str) -> proc_macro2::TokenStream { + match str { + $($variant_str => quote::quote!{ $name::$variant }),*, + str => panic!("{} is not a valid member of enum property {}", str, stringify!($name)), + } + } + } + + impl std::str::FromStr for $name { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + $($variant_str => Ok($name::$variant)),*, + s => Err(format!("Unknown property for {}: {}", stringify!($name), s)), + } + } + } + + impl std::fmt::Display for $name { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + $($name::$variant => write!(f, $variant_str)),* + } + } + } + + impl $crate::BlockStateProperty for $name { + fn values(&self) -> &[&str] { + &[$($variant_str),*] + } + } + }; +} diff --git a/src/blocks/crates/property/src/note_block_instrument.rs b/src/blocks/crates/property/src/note_block_instrument.rs new file mode 100644 index 00000000..17acd8fa --- /dev/null +++ b/src/blocks/crates/property/src/note_block_instrument.rs @@ -0,0 +1,30 @@ +use crate::enum_property; + +enum_property!( + NoteBlockInstrument, + Harp => "harp", + BaseDrum => "basedrum", + Snare => "snare", + Hat => "hat", + Bass => "bass", + Flute => "flute", + Bell => "bell", + Guitar => "guitar", + Chime => "chime", + Xylophone => "xylophone", + IronXylophone => "iron_xylophone", + CowBell => "cow_bell", + Didgeridoo => "didgeridoo", + Bit => "bit", + Banjo => "banjo", + Pling => "pling", + Zombie => "zombie", + Skeleton => "skeleton", + Creeper => "creeper", + Dragon => "dragon", + WitherSkeleton => "wither_skeleton", + Piglin => "piglin", + CustomHead => "custom_head", +); + +// TODO: return sound events based on the variant diff --git a/src/blocks/crates/property/src/simple.rs b/src/blocks/crates/property/src/simple.rs new file mode 100644 index 00000000..0f2039fd --- /dev/null +++ b/src/blocks/crates/property/src/simple.rs @@ -0,0 +1,219 @@ +/// All of these enums come directly from the enums found in the `net.minecraft.world.level.block.state.properties` package. +use crate::enum_property; + +enum_property!( + AttachFace, + Floor => "floor", + Wall => "wall", + Ceiling => "ceiling", +); + +enum_property!( + Axis, + X => "x", + Y => "y", + Z => "z", +); + +enum_property!( + BambooLeaves, + None => "none", + Small => "small", + Large => "large", +); + +enum_property!( + BedPart, + Head => "head", + Foot => "foot", +); + +enum_property!( + BellAttachType, + Floor => "floor", + Ceiling => "ceiling", + SingleWall => "single_wall", + DoubleWall => "double_wall", +); + +enum_property!( + ChestType, + Single => "single", + Left => "left", + Right => "right", +); + +enum_property!( + ComparatorMode, + Compare => "compare", + Subtract => "subtract", +); + +enum_property!( + CreakingHeartState, + Uprooted => "uprooted", + Dormant => "dormant", + Awake => "awake", +); + +enum_property!( + Direction, + Down => "down", + Up => "up", + North => "north", + South => "south", + East => "east", + West => "west", +); + +enum_property!( + DoorHingeSide, + Left => "left", + Right => "right", +); + +enum_property!( + DripstoneThickness, + TipMerge => "tip_merge", + Tip => "tip", + Frustum => "frustum", + Middle => "middle", + Base => "base", +); + +enum_property!( + FrontAndTop, + DownEast => "down_east", + DownNorth => "down_north", + DownSouth => "down_south", + DownWest => "down_west", + UpEast => "up_east", + UpNorth => "up_north", + UpSouth => "up_south", + UpWest => "up_west", + WestUp => "west_up", + EastUp => "east_up", + NorthUp => "north_up", + SouthUp => "south_up", +); + +enum_property!( + Half, + Top => "top", + Bottom => "bottom", +); + +enum_property!( + CopperGolemPose, + Standing => "standing", + Sitting => "sitting", + Running => "running", + Star => "star", +); + +enum_property!( + PistonType, + Default => "normal", + Sticky => "sticky", +); + +enum_property!( + RailShape, + NorthSouth => "north_south", + EastWest => "east_west", + AscendingEast => "ascending_east", + AscendingWest => "ascending_west", + AscendingNorth => "ascending_north", + AscendingSouth => "ascending_south", + SouthEast => "south_east", + SouthWest => "south_west", + NorthWest => "north_west", + NorthEast => "north_east", +); + +enum_property!( + RedstoneSide, + Up => "up", + Side => "side", + None => "none", +); + +enum_property!( + SculkSensorPhase, + Inactive => "inactive", + Active => "active", + Cooldown => "cooldown", +); + +enum_property!( + SideChainPart, + Unconnected => "unconnected", + Right => "right", + Center => "center", + Left => "left", +); + +enum_property!( + SlabType, + Top => "top", + Bottom => "bottom", + Double => "double", +); + +enum_property!( + StairsShape, + Straight => "straight", + InnerLeft => "inner_left", + InnerRight => "inner_right", + OuterLeft => "outer_left", + OuterRight => "outer_right", +); + +enum_property!( + StructureMode, + Save => "save", + Load => "load", + Corner => "corner", + Data => "data", +); + +enum_property!( + TestBlockMode, + Start => "start", + Log => "log", + Fail => "fail", + Accept => "accept", +); + +enum_property!( + Tilt, + None => "none", + Unstable => "unstable", + Partial => "partial", + Full => "full", +); + +enum_property!( + TrialSpawnerState, + Inactive => "inactive", + WaitingForPlayers => "waiting_for_players", + Active => "active", + WaitingForRewardEjection => "waiting_for_reward_ejection", + EjectingReward => "ejecting_reward", + Cooldown => "cooldown", +); + +enum_property!( + VaultState, + Inactive => "inactive", + Active => "active", + Unlocking => "unlocking", + Ejecting => "ejecting", +); + +enum_property!( + WallSide, + None => "none", + Low => "low", + Tall => "tall", +); diff --git a/src/blocks/src/bed_block.rs b/src/blocks/src/bed_block.rs new file mode 100644 index 00000000..6616f7ea --- /dev/null +++ b/src/blocks/src/bed_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BedBlock; + +impl BlockBehavior for BedBlock {} diff --git a/src/blocks/src/behavior_trait.rs b/src/blocks/src/behavior_trait.rs new file mode 100644 index 00000000..ba015d72 --- /dev/null +++ b/src/blocks/src/behavior_trait.rs @@ -0,0 +1,157 @@ +use crate::{PlacementContext, BLOCK_MAPPINGS}; +use temper_core::block_state_id::BlockStateId; +use temper_core::pos::BlockPos; +use temper_world::World; + +/// Macro to autogenerate the `BlockBehavior` trait and associated VTable structs. +/// +/// This macro simply exists to make adding methods to blocks easier. It should NOT be used anywhere except in this file, and should also only be used once. +/// See below this macro for where to add functions. +/// +/// The syntax for this macro is as follows: `fn ([mut]; ) [-> ; ]` +/// - `name`: The name of the method +/// - `mut`: Optional, whether the function takes a mutable reference to the block or not +/// - `arguments`: Any additional arguments to the method +/// - `return type`: Optional, what the function returns +/// - `default return value`: Optional, required if return type is set, the default expression to use for blocks that do not implement this method. +macro_rules! block_behavior_trait { + ($(fn $name:ident($($mut_meta:ident)?; $($argument:ident: $ty:ty),*) $(-> $ret:ty; $default:expr)?),* $(,)?) => { + macro_rules! ptr_ret_ty { + (mut) => { + u32 + }; + () => { + () + }; + (mut $retb:ty) => { + (u32, $retb) + }; + ($retb:ty) => { + $retb + }; + } + + macro_rules! id_ret_decode { + (mut, $in_data:expr) => { + ($in_data, ()) + }; + (, $in_data:expr) => { + ((), ()) + }; + (mut $retb:ty, $in_data:expr) => { + $in_data + }; + ($retb:ty, $in_data:expr) => { + ((), $in_data) + }; + } + + macro_rules! lambda_ret_ty { + (mut; $data:expr;) => { + $data + .try_into() + .unwrap_or_else(|_| panic!("Failed to convert block data back into id")) + }; + () => { + () + }; + (mut; $data:expr; $retb:ty; $ret_val:expr) => { + ( + $data + .try_into() + .unwrap_or_else(|_| panic!("Failed to convert block data back into id")), + $ret_val, + ) + }; + ($retb:ty; $ret_val:expr) => { + $ret_val + }; + } + + pub trait BlockBehavior: + TryInto + TryFrom + Clone + std::fmt::Debug + { + $( + fn $name(&$($mut_meta)? self, $($argument: $ty),*) $(-> $ret)? { $($default)? } + )* + } + + #[allow(dead_code)] + pub trait BlockDispatch { + fn try_cast(&self) -> Option; + + $( + fn $name(&$($mut_meta)? self, $($argument: $ty),*) $(-> $ret)?; + )* + } + + pub struct BlockBehaviorTable { + $( + $name: fn(id: u32, $($argument: $ty),*) -> ptr_ret_ty!{$($mut_meta)? $($ret)?} + ),* + } + + impl BlockBehaviorTable { + pub const fn from() -> Self { + Self { + $( + $name: |id, $($argument),*| { + let $($mut_meta)? data = T::try_from(id).unwrap_or_else(|_| panic!("Failed to convert id to data")); + let _ret = data.$name($($argument),*); + lambda_ret_ty!($($mut_meta; data;)? $($ret; _ret)?) + } + ),* + } + } + } + + pub struct StateBehaviorTable { + block: &'static BlockBehaviorTable, + id: u32, + } + + impl StateBehaviorTable { + pub const fn spin_off(block: &'static BlockBehaviorTable, id: u32) -> Self { + Self { block, id } + } + + $( + pub fn $name(&self, $($argument: $ty),*) -> ptr_ret_ty!{$($mut_meta)? $($ret)?} { + (self.block.$name)(self.id, $($argument),*) + } + )* + } + + macro_rules! update_self { + (mut, $s:expr, $new_id:expr) => { + *$s = Self::new($new_id); + }; + (, $s:expr, $new_id:expr) => { + + }; + } + + impl BlockDispatch for BlockStateId { + fn try_cast(&self) -> Option { + T::try_from(self.raw()).ok() + } + + $( + fn $name(& $($mut_meta)? self, $($argument: $ty),*) $(-> $ret)? { + let (_new_id, _ret) = id_ret_decode!{$($mut_meta)? $($ret)?, BLOCK_MAPPINGS[self.raw() as usize].$name($($argument),*)}; + update_self!{$($mut_meta)?, self, _new_id} + _ret + } + )* + } + }; +} + +// This is where methods are defined for blocks. See the macro above for the syntax. +// +// This is the only place where the `block_behavior_trait!` macro should be used. +block_behavior_trait!( + fn get_placement_state(mut; _context: PlacementContext), + fn can_be_replaced(; _context: PlacementContext) -> bool; false, + fn update(mut; _world: &World, _pos: BlockPos), +); diff --git a/src/blocks/src/bubble_column.rs b/src/blocks/src/bubble_column.rs new file mode 100644 index 00000000..64fbff99 --- /dev/null +++ b/src/blocks/src/bubble_column.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BubbleColumnBlock; + +impl BlockBehavior for BubbleColumnBlock {} diff --git a/src/blocks/src/building/mod.rs b/src/blocks/src/building/mod.rs new file mode 100644 index 00000000..7ead741d --- /dev/null +++ b/src/blocks/src/building/mod.rs @@ -0,0 +1,4 @@ +mod pillar_block; +mod simple_block; +mod slab; +mod stairs; diff --git a/src/blocks/src/building/pillar_block.rs b/src/blocks/src/building/pillar_block.rs new file mode 100644 index 00000000..7e8bb268 --- /dev/null +++ b/src/blocks/src/building/pillar_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::PillarBlock; + +impl BlockBehavior for PillarBlock {} diff --git a/src/blocks/src/building/simple_block.rs b/src/blocks/src/building/simple_block.rs new file mode 100644 index 00000000..d7d069df --- /dev/null +++ b/src/blocks/src/building/simple_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SimpleBlock; + +impl BlockBehavior for SimpleBlock {} diff --git a/src/blocks/src/building/slab.rs b/src/blocks/src/building/slab.rs new file mode 100644 index 00000000..429a2d2d --- /dev/null +++ b/src/blocks/src/building/slab.rs @@ -0,0 +1,40 @@ +use crate::{BlockBehavior, BlockDispatch, PlacementContext}; +use temper_block_properties::SlabType; +use temper_blocks_generated::SlabBlock; +use temper_core::block_face::BlockFace; +use temper_core::block_state_id::BlockStateId; +use temper_macros::match_block; + +impl BlockBehavior for SlabBlock { + #[inline(always)] + fn get_placement_state(&mut self, context: PlacementContext) { + let block = context + .level + .get_chunk(context.block_pos.chunk(), context.dimension) + .map(|c| c.get_block(context.block_pos.chunk_block_pos())) + .unwrap_or(BlockStateId::new(0)); + + self.ty = if block.try_cast::().is_some() { + SlabType::Double + } else { + match context.face { + BlockFace::Top => SlabType::Bottom, + BlockFace::Bottom => SlabType::Top, + _ => { + if context.cursor.y > 0.5 { + SlabType::Top + } else { + SlabType::Bottom + } + } + } + }; + + self.waterlogged = match_block!("water", block); + } + + #[inline(always)] + fn can_be_replaced(&self, _context: PlacementContext) -> bool { + true + } +} diff --git a/src/blocks/src/building/stairs.rs b/src/blocks/src/building/stairs.rs new file mode 100644 index 00000000..41d85074 --- /dev/null +++ b/src/blocks/src/building/stairs.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::StairsBlock; + +impl BlockBehavior for StairsBlock {} diff --git a/src/blocks/src/cake.rs b/src/blocks/src/cake.rs new file mode 100644 index 00000000..59f0b14f --- /dev/null +++ b/src/blocks/src/cake.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CakeBlock; + +impl BlockBehavior for CakeBlock {} diff --git a/src/blocks/src/candle_cake.rs b/src/blocks/src/candle_cake.rs new file mode 100644 index 00000000..01b02f9d --- /dev/null +++ b/src/blocks/src/candle_cake.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CandleCakeBlock; + +impl BlockBehavior for CandleCakeBlock {} diff --git a/src/blocks/src/decorative/banner.rs b/src/blocks/src/decorative/banner.rs new file mode 100644 index 00000000..9a54e979 --- /dev/null +++ b/src/blocks/src/decorative/banner.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BannerBlock; + +impl BlockBehavior for BannerBlock {} diff --git a/src/blocks/src/decorative/bell.rs b/src/blocks/src/decorative/bell.rs new file mode 100644 index 00000000..fd7bd9d2 --- /dev/null +++ b/src/blocks/src/decorative/bell.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BellBlock; + +impl BlockBehavior for BellBlock {} diff --git a/src/blocks/src/decorative/candle.rs b/src/blocks/src/decorative/candle.rs new file mode 100644 index 00000000..5196705e --- /dev/null +++ b/src/blocks/src/decorative/candle.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CandleBlock; + +impl BlockBehavior for CandleBlock {} diff --git a/src/blocks/src/decorative/chain.rs b/src/blocks/src/decorative/chain.rs new file mode 100644 index 00000000..a7b416ab --- /dev/null +++ b/src/blocks/src/decorative/chain.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ChainBlock; + +impl BlockBehavior for ChainBlock {} diff --git a/src/blocks/src/decorative/chiseled_bookshelf.rs b/src/blocks/src/decorative/chiseled_bookshelf.rs new file mode 100644 index 00000000..cf554ba7 --- /dev/null +++ b/src/blocks/src/decorative/chiseled_bookshelf.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ChiseledBookshelfBlock; + +impl BlockBehavior for ChiseledBookshelfBlock {} diff --git a/src/blocks/src/decorative/decorated_pot.rs b/src/blocks/src/decorative/decorated_pot.rs new file mode 100644 index 00000000..493276ca --- /dev/null +++ b/src/blocks/src/decorative/decorated_pot.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::DecoratedPotBlock; + +impl BlockBehavior for DecoratedPotBlock {} diff --git a/src/blocks/src/decorative/door.rs b/src/blocks/src/decorative/door.rs new file mode 100644 index 00000000..a4dc216e --- /dev/null +++ b/src/blocks/src/decorative/door.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::DoorBlock; + +impl BlockBehavior for DoorBlock {} diff --git a/src/blocks/src/decorative/fence_gate.rs b/src/blocks/src/decorative/fence_gate.rs new file mode 100644 index 00000000..2b628cdf --- /dev/null +++ b/src/blocks/src/decorative/fence_gate.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::FenceGateBlock; + +impl BlockBehavior for FenceGateBlock {} diff --git a/src/blocks/src/decorative/fence_pane.rs b/src/blocks/src/decorative/fence_pane.rs new file mode 100644 index 00000000..39c6b101 --- /dev/null +++ b/src/blocks/src/decorative/fence_pane.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::FenceAndPaneBlock; + +impl BlockBehavior for FenceAndPaneBlock {} diff --git a/src/blocks/src/decorative/hanging_sign.rs b/src/blocks/src/decorative/hanging_sign.rs new file mode 100644 index 00000000..503e055b --- /dev/null +++ b/src/blocks/src/decorative/hanging_sign.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::HangingSignBlock; + +impl BlockBehavior for HangingSignBlock {} diff --git a/src/blocks/src/decorative/lantern.rs b/src/blocks/src/decorative/lantern.rs new file mode 100644 index 00000000..792dabd4 --- /dev/null +++ b/src/blocks/src/decorative/lantern.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LanternBlock; + +impl BlockBehavior for LanternBlock {} diff --git a/src/blocks/src/decorative/mod.rs b/src/blocks/src/decorative/mod.rs new file mode 100644 index 00000000..78cee89a --- /dev/null +++ b/src/blocks/src/decorative/mod.rs @@ -0,0 +1,16 @@ +mod banner; +mod bell; +mod candle; +mod chain; +mod chiseled_bookshelf; +mod decorated_pot; +mod door; +mod fence_gate; +mod fence_pane; +mod hanging_sign; +mod lantern; +mod note_block; +mod sign; +mod trapdoor; +mod wall; +mod waterloggable_wall; diff --git a/src/blocks/src/decorative/note_block.rs b/src/blocks/src/decorative/note_block.rs new file mode 100644 index 00000000..9c1c2117 --- /dev/null +++ b/src/blocks/src/decorative/note_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::NoteBlock; + +impl BlockBehavior for NoteBlock {} diff --git a/src/blocks/src/decorative/sign.rs b/src/blocks/src/decorative/sign.rs new file mode 100644 index 00000000..2e3c5519 --- /dev/null +++ b/src/blocks/src/decorative/sign.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SignBlock; + +impl BlockBehavior for SignBlock {} diff --git a/src/blocks/src/decorative/trapdoor.rs b/src/blocks/src/decorative/trapdoor.rs new file mode 100644 index 00000000..d9ac4967 --- /dev/null +++ b/src/blocks/src/decorative/trapdoor.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::TrapdoorBlock; + +impl BlockBehavior for TrapdoorBlock {} diff --git a/src/blocks/src/decorative/wall.rs b/src/blocks/src/decorative/wall.rs new file mode 100644 index 00000000..18842b11 --- /dev/null +++ b/src/blocks/src/decorative/wall.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::WallBlock; + +impl BlockBehavior for WallBlock {} diff --git a/src/blocks/src/decorative/waterloggable_wall.rs b/src/blocks/src/decorative/waterloggable_wall.rs new file mode 100644 index 00000000..efc082b2 --- /dev/null +++ b/src/blocks/src/decorative/waterloggable_wall.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::WaterloggableWallAttachedBlock; + +impl BlockBehavior for WaterloggableWallAttachedBlock {} diff --git a/src/blocks/src/facing_block.rs b/src/blocks/src/facing_block.rs new file mode 100644 index 00000000..568a5cee --- /dev/null +++ b/src/blocks/src/facing_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::FacingBlock; + +impl BlockBehavior for FacingBlock {} diff --git a/src/blocks/src/fire.rs b/src/blocks/src/fire.rs new file mode 100644 index 00000000..25a62b04 --- /dev/null +++ b/src/blocks/src/fire.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::FireBlock; + +impl BlockBehavior for FireBlock {} diff --git a/src/blocks/src/functional/barrel.rs b/src/blocks/src/functional/barrel.rs new file mode 100644 index 00000000..29874041 --- /dev/null +++ b/src/blocks/src/functional/barrel.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BarrelBlock; + +impl BlockBehavior for BarrelBlock {} diff --git a/src/blocks/src/functional/brewing_stand.rs b/src/blocks/src/functional/brewing_stand.rs new file mode 100644 index 00000000..b9f299a6 --- /dev/null +++ b/src/blocks/src/functional/brewing_stand.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BrewingStandBlock; + +impl BlockBehavior for BrewingStandBlock {} diff --git a/src/blocks/src/functional/campfire.rs b/src/blocks/src/functional/campfire.rs new file mode 100644 index 00000000..a3f6e546 --- /dev/null +++ b/src/blocks/src/functional/campfire.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CampfireBlock; + +impl BlockBehavior for CampfireBlock {} diff --git a/src/blocks/src/functional/cauldron.rs b/src/blocks/src/functional/cauldron.rs new file mode 100644 index 00000000..c53c0b11 --- /dev/null +++ b/src/blocks/src/functional/cauldron.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LevelCauldronBlock; + +impl BlockBehavior for LevelCauldronBlock {} diff --git a/src/blocks/src/functional/chest.rs b/src/blocks/src/functional/chest.rs new file mode 100644 index 00000000..68c5e5b5 --- /dev/null +++ b/src/blocks/src/functional/chest.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ChestBlock; + +impl BlockBehavior for ChestBlock {} diff --git a/src/blocks/src/functional/command_block.rs b/src/blocks/src/functional/command_block.rs new file mode 100644 index 00000000..907b938a --- /dev/null +++ b/src/blocks/src/functional/command_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CommandBlock; + +impl BlockBehavior for CommandBlock {} diff --git a/src/blocks/src/functional/composter.rs b/src/blocks/src/functional/composter.rs new file mode 100644 index 00000000..30a916ba --- /dev/null +++ b/src/blocks/src/functional/composter.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ComposterBlock; + +impl BlockBehavior for ComposterBlock {} diff --git a/src/blocks/src/functional/end_portal.rs b/src/blocks/src/functional/end_portal.rs new file mode 100644 index 00000000..4aaa9d59 --- /dev/null +++ b/src/blocks/src/functional/end_portal.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::EndPortalBlock; + +impl BlockBehavior for EndPortalBlock {} diff --git a/src/blocks/src/functional/furnace.rs b/src/blocks/src/functional/furnace.rs new file mode 100644 index 00000000..843a8cb4 --- /dev/null +++ b/src/blocks/src/functional/furnace.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::FurnaceBlock; + +impl BlockBehavior for FurnaceBlock {} diff --git a/src/blocks/src/functional/grindstone.rs b/src/blocks/src/functional/grindstone.rs new file mode 100644 index 00000000..e01b161e --- /dev/null +++ b/src/blocks/src/functional/grindstone.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::GrindstoneBlock; + +impl BlockBehavior for GrindstoneBlock {} diff --git a/src/blocks/src/functional/jigsaw.rs b/src/blocks/src/functional/jigsaw.rs new file mode 100644 index 00000000..b8edc923 --- /dev/null +++ b/src/blocks/src/functional/jigsaw.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::JigsawBlock; + +impl BlockBehavior for JigsawBlock {} diff --git a/src/blocks/src/functional/lectern.rs b/src/blocks/src/functional/lectern.rs new file mode 100644 index 00000000..98d8ebe6 --- /dev/null +++ b/src/blocks/src/functional/lectern.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LecternBlock; + +impl BlockBehavior for LecternBlock {} diff --git a/src/blocks/src/functional/light.rs b/src/blocks/src/functional/light.rs new file mode 100644 index 00000000..2052caeb --- /dev/null +++ b/src/blocks/src/functional/light.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LightBlock; + +impl BlockBehavior for LightBlock {} diff --git a/src/blocks/src/functional/mod.rs b/src/blocks/src/functional/mod.rs new file mode 100644 index 00000000..efb610f2 --- /dev/null +++ b/src/blocks/src/functional/mod.rs @@ -0,0 +1,19 @@ +mod barrel; +mod brewing_stand; +mod campfire; +mod cauldron; +mod chest; +mod command_block; +mod composter; +mod end_portal; +mod furnace; +mod grindstone; +mod jigsaw; +mod lectern; +mod light; +mod respawn_anchor; +mod scaffolding; +mod structure; +mod test; +mod trial_spawner; +mod vault; diff --git a/src/blocks/src/functional/respawn_anchor.rs b/src/blocks/src/functional/respawn_anchor.rs new file mode 100644 index 00000000..f610a7e6 --- /dev/null +++ b/src/blocks/src/functional/respawn_anchor.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::RespawnAnchor; + +impl BlockBehavior for RespawnAnchor {} diff --git a/src/blocks/src/functional/scaffolding.rs b/src/blocks/src/functional/scaffolding.rs new file mode 100644 index 00000000..856babb7 --- /dev/null +++ b/src/blocks/src/functional/scaffolding.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ScaffoldingBlock; + +impl BlockBehavior for ScaffoldingBlock {} diff --git a/src/blocks/src/functional/structure.rs b/src/blocks/src/functional/structure.rs new file mode 100644 index 00000000..f0241f0c --- /dev/null +++ b/src/blocks/src/functional/structure.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::StructureBlock; + +impl BlockBehavior for StructureBlock {} diff --git a/src/blocks/src/functional/test.rs b/src/blocks/src/functional/test.rs new file mode 100644 index 00000000..3acb04ad --- /dev/null +++ b/src/blocks/src/functional/test.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::TestBlock; + +impl BlockBehavior for TestBlock {} diff --git a/src/blocks/src/functional/trial_spawner.rs b/src/blocks/src/functional/trial_spawner.rs new file mode 100644 index 00000000..33d7187c --- /dev/null +++ b/src/blocks/src/functional/trial_spawner.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::TrialSpawnerBlock; + +impl BlockBehavior for TrialSpawnerBlock {} diff --git a/src/blocks/src/functional/vault.rs b/src/blocks/src/functional/vault.rs new file mode 100644 index 00000000..1ebd1554 --- /dev/null +++ b/src/blocks/src/functional/vault.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::VaultBlock; + +impl BlockBehavior for VaultBlock {} diff --git a/src/blocks/src/lib.rs b/src/blocks/src/lib.rs new file mode 100644 index 00000000..ca21c89e --- /dev/null +++ b/src/blocks/src/lib.rs @@ -0,0 +1,40 @@ +use bevy_math::DVec3; +use temper_core::block_face::BlockFace; +use temper_core::dimension::Dimension; +use temper_core::pos::BlockPos; +use temper_world::World; + +mod bed_block; +mod behavior_trait; +mod bubble_column; +mod building; +mod cake; +mod candle_cake; +mod decorative; +mod facing_block; +mod fire; +mod functional; +mod liquid; +mod nature; +mod redstone; +mod skull; +mod suspicious_block; +mod wall_skull; +mod waterloggable_block; + +#[allow(unused_imports)] // Used in the include! +use crate::behavior_trait::BlockBehaviorTable; + +pub use crate::behavior_trait::{BlockBehavior, BlockDispatch, StateBehaviorTable}; + +pub const BLOCK_MAPPINGS: &[StateBehaviorTable] = + include!(concat!(env!("OUT_DIR"), "/mappings.rs")); + +pub struct PlacementContext<'a> { + pub face: BlockFace, + pub cursor: DVec3, + pub block_clicked: BlockPos, + pub block_pos: BlockPos, + pub level: &'a World, + pub dimension: Dimension, +} diff --git a/src/blocks/src/liquid.rs b/src/blocks/src/liquid.rs new file mode 100644 index 00000000..782f5578 --- /dev/null +++ b/src/blocks/src/liquid.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LiquidBlock; + +impl BlockBehavior for LiquidBlock {} diff --git a/src/blocks/src/nature/bamboo.rs b/src/blocks/src/nature/bamboo.rs new file mode 100644 index 00000000..eca21792 --- /dev/null +++ b/src/blocks/src/nature/bamboo.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BambooBlock; + +impl BlockBehavior for BambooBlock {} diff --git a/src/blocks/src/nature/big_dripleaf.rs b/src/blocks/src/nature/big_dripleaf.rs new file mode 100644 index 00000000..2da3d6c5 --- /dev/null +++ b/src/blocks/src/nature/big_dripleaf.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BigDripleafBlock; + +impl BlockBehavior for BigDripleafBlock {} diff --git a/src/blocks/src/nature/chorus.rs b/src/blocks/src/nature/chorus.rs new file mode 100644 index 00000000..20b7016f --- /dev/null +++ b/src/blocks/src/nature/chorus.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ChorusPlantBlock; + +impl BlockBehavior for ChorusPlantBlock {} diff --git a/src/blocks/src/nature/cocoa_beans.rs b/src/blocks/src/nature/cocoa_beans.rs new file mode 100644 index 00000000..f7e601ca --- /dev/null +++ b/src/blocks/src/nature/cocoa_beans.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CocoaBeansBlock; + +impl BlockBehavior for CocoaBeansBlock {} diff --git a/src/blocks/src/nature/creaking_heart.rs b/src/blocks/src/nature/creaking_heart.rs new file mode 100644 index 00000000..ade177db --- /dev/null +++ b/src/blocks/src/nature/creaking_heart.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CreakingHeartBlock; + +impl BlockBehavior for CreakingHeartBlock {} diff --git a/src/blocks/src/nature/crop.rs b/src/blocks/src/nature/crop.rs new file mode 100644 index 00000000..144cc60b --- /dev/null +++ b/src/blocks/src/nature/crop.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CropBlock; + +impl BlockBehavior for CropBlock {} diff --git a/src/blocks/src/nature/double_plant_block.rs b/src/blocks/src/nature/double_plant_block.rs new file mode 100644 index 00000000..8e748545 --- /dev/null +++ b/src/blocks/src/nature/double_plant_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::DoublePlantBlock; + +impl BlockBehavior for DoublePlantBlock {} diff --git a/src/blocks/src/nature/dripstone.rs b/src/blocks/src/nature/dripstone.rs new file mode 100644 index 00000000..4a47076d --- /dev/null +++ b/src/blocks/src/nature/dripstone.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::DripstoneBlock; + +impl BlockBehavior for DripstoneBlock {} diff --git a/src/blocks/src/nature/farmland.rs b/src/blocks/src/nature/farmland.rs new file mode 100644 index 00000000..6ff7a2c2 --- /dev/null +++ b/src/blocks/src/nature/farmland.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::FarmlandBlock; + +impl BlockBehavior for FarmlandBlock {} diff --git a/src/blocks/src/nature/flower_cover.rs b/src/blocks/src/nature/flower_cover.rs new file mode 100644 index 00000000..1df9d430 --- /dev/null +++ b/src/blocks/src/nature/flower_cover.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::FlowerCoverBlock; + +impl BlockBehavior for FlowerCoverBlock {} diff --git a/src/blocks/src/nature/frosted_ice.rs b/src/blocks/src/nature/frosted_ice.rs new file mode 100644 index 00000000..dff0d7be --- /dev/null +++ b/src/blocks/src/nature/frosted_ice.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::FrostedIceBlock; + +impl BlockBehavior for FrostedIceBlock {} diff --git a/src/blocks/src/nature/glow_berries.rs b/src/blocks/src/nature/glow_berries.rs new file mode 100644 index 00000000..7b7f6163 --- /dev/null +++ b/src/blocks/src/nature/glow_berries.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::GlowBerriesBlock; + +impl BlockBehavior for GlowBerriesBlock {} diff --git a/src/blocks/src/nature/glow_berries_plant.rs b/src/blocks/src/nature/glow_berries_plant.rs new file mode 100644 index 00000000..e4c488d4 --- /dev/null +++ b/src/blocks/src/nature/glow_berries_plant.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::GlowBerriesPlantBlock; + +impl BlockBehavior for GlowBerriesPlantBlock {} diff --git a/src/blocks/src/nature/hive.rs b/src/blocks/src/nature/hive.rs new file mode 100644 index 00000000..e196b850 --- /dev/null +++ b/src/blocks/src/nature/hive.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::HiveBlock; + +impl BlockBehavior for HiveBlock {} diff --git a/src/blocks/src/nature/large_mushroom.rs b/src/blocks/src/nature/large_mushroom.rs new file mode 100644 index 00000000..2a92a2ee --- /dev/null +++ b/src/blocks/src/nature/large_mushroom.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LargeMushroomBlock; + +impl BlockBehavior for LargeMushroomBlock {} diff --git a/src/blocks/src/nature/leaf_litter.rs b/src/blocks/src/nature/leaf_litter.rs new file mode 100644 index 00000000..ad8b29b9 --- /dev/null +++ b/src/blocks/src/nature/leaf_litter.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LeafLitterBlock; + +impl BlockBehavior for LeafLitterBlock {} diff --git a/src/blocks/src/nature/leaves.rs b/src/blocks/src/nature/leaves.rs new file mode 100644 index 00000000..d532b9ca --- /dev/null +++ b/src/blocks/src/nature/leaves.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LeavesBlock; + +impl BlockBehavior for LeavesBlock {} diff --git a/src/blocks/src/nature/lichen.rs b/src/blocks/src/nature/lichen.rs new file mode 100644 index 00000000..44218421 --- /dev/null +++ b/src/blocks/src/nature/lichen.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LichenBlock; + +impl BlockBehavior for LichenBlock {} diff --git a/src/blocks/src/nature/mangrove_propagule.rs b/src/blocks/src/nature/mangrove_propagule.rs new file mode 100644 index 00000000..140a8715 --- /dev/null +++ b/src/blocks/src/nature/mangrove_propagule.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::MangrovePopaguleBlock; + +impl BlockBehavior for MangrovePopaguleBlock {} diff --git a/src/blocks/src/nature/mod.rs b/src/blocks/src/nature/mod.rs new file mode 100644 index 00000000..5dc98248 --- /dev/null +++ b/src/blocks/src/nature/mod.rs @@ -0,0 +1,31 @@ +mod bamboo; +mod big_dripleaf; +mod chorus; +mod cocoa_beans; +mod creaking_heart; +mod crop; +mod double_plant_block; +mod dripstone; +mod farmland; +mod flower_cover; +mod frosted_ice; +mod glow_berries; +mod glow_berries_plant; +mod hive; +mod large_mushroom; +mod leaf_litter; +mod leaves; +mod lichen; +mod mangrove_propagule; +mod pale_hanging_moss; +mod pale_moss_carpet; +mod pitcher_crop; +mod sapling_block; +mod sea_pickle; +mod small_dripleaf; +mod sniffer_egg; +mod snow; +mod snowy; +mod stem; +mod turtle_egg; +mod vine; diff --git a/src/blocks/src/nature/pale_hanging_moss.rs b/src/blocks/src/nature/pale_hanging_moss.rs new file mode 100644 index 00000000..2510c375 --- /dev/null +++ b/src/blocks/src/nature/pale_hanging_moss.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::PaleHangingMossBlock; + +impl BlockBehavior for PaleHangingMossBlock {} diff --git a/src/blocks/src/nature/pale_moss_carpet.rs b/src/blocks/src/nature/pale_moss_carpet.rs new file mode 100644 index 00000000..b7654db5 --- /dev/null +++ b/src/blocks/src/nature/pale_moss_carpet.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::PaleMossCarpetBlock; + +impl BlockBehavior for PaleMossCarpetBlock {} diff --git a/src/blocks/src/nature/pitcher_crop.rs b/src/blocks/src/nature/pitcher_crop.rs new file mode 100644 index 00000000..094174d6 --- /dev/null +++ b/src/blocks/src/nature/pitcher_crop.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::PitcherCropBlock; + +impl BlockBehavior for PitcherCropBlock {} diff --git a/src/blocks/src/nature/sapling_block.rs b/src/blocks/src/nature/sapling_block.rs new file mode 100644 index 00000000..567ff9ce --- /dev/null +++ b/src/blocks/src/nature/sapling_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SaplingBlock; + +impl BlockBehavior for SaplingBlock {} diff --git a/src/blocks/src/nature/sea_pickle.rs b/src/blocks/src/nature/sea_pickle.rs new file mode 100644 index 00000000..4c1509af --- /dev/null +++ b/src/blocks/src/nature/sea_pickle.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SeaPickleBlock; + +impl BlockBehavior for SeaPickleBlock {} diff --git a/src/blocks/src/nature/small_dripleaf.rs b/src/blocks/src/nature/small_dripleaf.rs new file mode 100644 index 00000000..1142e481 --- /dev/null +++ b/src/blocks/src/nature/small_dripleaf.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SmallDripleafBlock; + +impl BlockBehavior for SmallDripleafBlock {} diff --git a/src/blocks/src/nature/sniffer_egg.rs b/src/blocks/src/nature/sniffer_egg.rs new file mode 100644 index 00000000..056478ed --- /dev/null +++ b/src/blocks/src/nature/sniffer_egg.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SnifferEggBlock; + +impl BlockBehavior for SnifferEggBlock {} diff --git a/src/blocks/src/nature/snow.rs b/src/blocks/src/nature/snow.rs new file mode 100644 index 00000000..381109f7 --- /dev/null +++ b/src/blocks/src/nature/snow.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SnowBlock; + +impl BlockBehavior for SnowBlock {} diff --git a/src/blocks/src/nature/snowy.rs b/src/blocks/src/nature/snowy.rs new file mode 100644 index 00000000..8dfb6ca3 --- /dev/null +++ b/src/blocks/src/nature/snowy.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SnowyBlock; + +impl BlockBehavior for SnowyBlock {} diff --git a/src/blocks/src/nature/stem.rs b/src/blocks/src/nature/stem.rs new file mode 100644 index 00000000..d0fb1d3d --- /dev/null +++ b/src/blocks/src/nature/stem.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::StemBlock; + +impl BlockBehavior for StemBlock {} diff --git a/src/blocks/src/nature/turtle_egg.rs b/src/blocks/src/nature/turtle_egg.rs new file mode 100644 index 00000000..51c87126 --- /dev/null +++ b/src/blocks/src/nature/turtle_egg.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::TurtleEggBlock; + +impl BlockBehavior for TurtleEggBlock {} diff --git a/src/blocks/src/nature/vine.rs b/src/blocks/src/nature/vine.rs new file mode 100644 index 00000000..94620341 --- /dev/null +++ b/src/blocks/src/nature/vine.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::VineBlock; + +impl BlockBehavior for VineBlock {} diff --git a/src/blocks/src/redstone/bulb.rs b/src/blocks/src/redstone/bulb.rs new file mode 100644 index 00000000..207901c3 --- /dev/null +++ b/src/blocks/src/redstone/bulb.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::BulbBlock; + +impl BlockBehavior for BulbBlock {} diff --git a/src/blocks/src/redstone/button.rs b/src/blocks/src/redstone/button.rs new file mode 100644 index 00000000..fbfdc0a9 --- /dev/null +++ b/src/blocks/src/redstone/button.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ButtonBlock; + +impl BlockBehavior for ButtonBlock {} diff --git a/src/blocks/src/redstone/calibrated_sculk_sensor.rs b/src/blocks/src/redstone/calibrated_sculk_sensor.rs new file mode 100644 index 00000000..0d1300f8 --- /dev/null +++ b/src/blocks/src/redstone/calibrated_sculk_sensor.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CalibratedSculkSensorBlock; + +impl BlockBehavior for CalibratedSculkSensorBlock {} diff --git a/src/blocks/src/redstone/comparator.rs b/src/blocks/src/redstone/comparator.rs new file mode 100644 index 00000000..4a0d0042 --- /dev/null +++ b/src/blocks/src/redstone/comparator.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ComparatorBlock; + +impl BlockBehavior for ComparatorBlock {} diff --git a/src/blocks/src/redstone/crafter.rs b/src/blocks/src/redstone/crafter.rs new file mode 100644 index 00000000..538be302 --- /dev/null +++ b/src/blocks/src/redstone/crafter.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::CrafterBlock; + +impl BlockBehavior for CrafterBlock {} diff --git a/src/blocks/src/redstone/daylight_detector.rs b/src/blocks/src/redstone/daylight_detector.rs new file mode 100644 index 00000000..9152b7f5 --- /dev/null +++ b/src/blocks/src/redstone/daylight_detector.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::DaylightDetectorBlock; + +impl BlockBehavior for DaylightDetectorBlock {} diff --git a/src/blocks/src/redstone/dispenser.rs b/src/blocks/src/redstone/dispenser.rs new file mode 100644 index 00000000..b2bbf5e4 --- /dev/null +++ b/src/blocks/src/redstone/dispenser.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::DispenserBlock; + +impl BlockBehavior for DispenserBlock {} diff --git a/src/blocks/src/redstone/hopper.rs b/src/blocks/src/redstone/hopper.rs new file mode 100644 index 00000000..a05f176a --- /dev/null +++ b/src/blocks/src/redstone/hopper.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::HopperBlock; + +impl BlockBehavior for HopperBlock {} diff --git a/src/blocks/src/redstone/jukebox.rs b/src/blocks/src/redstone/jukebox.rs new file mode 100644 index 00000000..7e975ce1 --- /dev/null +++ b/src/blocks/src/redstone/jukebox.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::JukeboxBlock; + +impl BlockBehavior for JukeboxBlock {} diff --git a/src/blocks/src/redstone/lamp.rs b/src/blocks/src/redstone/lamp.rs new file mode 100644 index 00000000..2e884248 --- /dev/null +++ b/src/blocks/src/redstone/lamp.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::RedstoneLampBlock; + +impl BlockBehavior for RedstoneLampBlock {} diff --git a/src/blocks/src/redstone/lever.rs b/src/blocks/src/redstone/lever.rs new file mode 100644 index 00000000..17333344 --- /dev/null +++ b/src/blocks/src/redstone/lever.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LeverBlock; + +impl BlockBehavior for LeverBlock {} diff --git a/src/blocks/src/redstone/lightning_rod.rs b/src/blocks/src/redstone/lightning_rod.rs new file mode 100644 index 00000000..a1610a36 --- /dev/null +++ b/src/blocks/src/redstone/lightning_rod.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::LightningRodBlock; + +impl BlockBehavior for LightningRodBlock {} diff --git a/src/blocks/src/redstone/mod.rs b/src/blocks/src/redstone/mod.rs new file mode 100644 index 00000000..7438c999 --- /dev/null +++ b/src/blocks/src/redstone/mod.rs @@ -0,0 +1,30 @@ +mod bulb; +mod button; +mod calibrated_sculk_sensor; +mod comparator; +mod crafter; +mod daylight_detector; +mod dispenser; +mod hopper; +mod jukebox; +mod lamp; +mod lever; +mod lightning_rod; +mod observer; +mod ore; +mod piston; +mod pressure_plate; +mod rail; +mod redstone_rail; +mod repeater; +mod sculk_catalyst; +mod sculk_sensor; +mod sculk_shrieker; +mod target; +mod tnt; +mod torch; +mod tripwire; +mod tripwire_hook; +mod wall_torch; +mod weighted_pressure_plate; +mod wire; diff --git a/src/blocks/src/redstone/observer.rs b/src/blocks/src/redstone/observer.rs new file mode 100644 index 00000000..eff40d23 --- /dev/null +++ b/src/blocks/src/redstone/observer.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::ObserverBlock; + +impl BlockBehavior for ObserverBlock {} diff --git a/src/blocks/src/redstone/ore.rs b/src/blocks/src/redstone/ore.rs new file mode 100644 index 00000000..421f65a0 --- /dev/null +++ b/src/blocks/src/redstone/ore.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::RedstoneOreBlock; + +impl BlockBehavior for RedstoneOreBlock {} diff --git a/src/blocks/src/redstone/piston/head.rs b/src/blocks/src/redstone/piston/head.rs new file mode 100644 index 00000000..6bdb4cef --- /dev/null +++ b/src/blocks/src/redstone/piston/head.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::PistonHeadBlock; + +impl BlockBehavior for PistonHeadBlock {} diff --git a/src/blocks/src/redstone/piston/mod.rs b/src/blocks/src/redstone/piston/mod.rs new file mode 100644 index 00000000..53fa6668 --- /dev/null +++ b/src/blocks/src/redstone/piston/mod.rs @@ -0,0 +1,7 @@ +use crate::BlockBehavior; +use temper_blocks_generated::PistonBlock; + +mod head; +mod moving_head; + +impl BlockBehavior for PistonBlock {} diff --git a/src/blocks/src/redstone/piston/moving_head.rs b/src/blocks/src/redstone/piston/moving_head.rs new file mode 100644 index 00000000..0c38afb5 --- /dev/null +++ b/src/blocks/src/redstone/piston/moving_head.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::MovingPistonBlock; + +impl BlockBehavior for MovingPistonBlock {} diff --git a/src/blocks/src/redstone/pressure_plate.rs b/src/blocks/src/redstone/pressure_plate.rs new file mode 100644 index 00000000..34e1a92c --- /dev/null +++ b/src/blocks/src/redstone/pressure_plate.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::PressurePlateBlock; + +impl BlockBehavior for PressurePlateBlock {} diff --git a/src/blocks/src/redstone/rail.rs b/src/blocks/src/redstone/rail.rs new file mode 100644 index 00000000..ac21e4f1 --- /dev/null +++ b/src/blocks/src/redstone/rail.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::RailBlock; + +impl BlockBehavior for RailBlock {} diff --git a/src/blocks/src/redstone/redstone_rail.rs b/src/blocks/src/redstone/redstone_rail.rs new file mode 100644 index 00000000..b7c07e91 --- /dev/null +++ b/src/blocks/src/redstone/redstone_rail.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::RedstoneRailBlock; + +impl BlockBehavior for RedstoneRailBlock {} diff --git a/src/blocks/src/redstone/repeater.rs b/src/blocks/src/redstone/repeater.rs new file mode 100644 index 00000000..c15cbd74 --- /dev/null +++ b/src/blocks/src/redstone/repeater.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::RepeaterBlock; + +impl BlockBehavior for RepeaterBlock {} diff --git a/src/blocks/src/redstone/sculk_catalyst.rs b/src/blocks/src/redstone/sculk_catalyst.rs new file mode 100644 index 00000000..cc6039c2 --- /dev/null +++ b/src/blocks/src/redstone/sculk_catalyst.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SculkCatalystBlock; + +impl BlockBehavior for SculkCatalystBlock {} diff --git a/src/blocks/src/redstone/sculk_sensor.rs b/src/blocks/src/redstone/sculk_sensor.rs new file mode 100644 index 00000000..46cedbab --- /dev/null +++ b/src/blocks/src/redstone/sculk_sensor.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SculkSensorBlock; + +impl BlockBehavior for SculkSensorBlock {} diff --git a/src/blocks/src/redstone/sculk_shrieker.rs b/src/blocks/src/redstone/sculk_shrieker.rs new file mode 100644 index 00000000..7053e901 --- /dev/null +++ b/src/blocks/src/redstone/sculk_shrieker.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SculkShriekerBlock; + +impl BlockBehavior for SculkShriekerBlock {} diff --git a/src/blocks/src/redstone/target.rs b/src/blocks/src/redstone/target.rs new file mode 100644 index 00000000..7baed0a3 --- /dev/null +++ b/src/blocks/src/redstone/target.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::TargetBlock; + +impl BlockBehavior for TargetBlock {} diff --git a/src/blocks/src/redstone/tnt.rs b/src/blocks/src/redstone/tnt.rs new file mode 100644 index 00000000..ae44feda --- /dev/null +++ b/src/blocks/src/redstone/tnt.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::TntBlock; + +impl BlockBehavior for TntBlock {} diff --git a/src/blocks/src/redstone/torch.rs b/src/blocks/src/redstone/torch.rs new file mode 100644 index 00000000..07c1a93f --- /dev/null +++ b/src/blocks/src/redstone/torch.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::RedstoneTorchBlock; + +impl BlockBehavior for RedstoneTorchBlock {} diff --git a/src/blocks/src/redstone/tripwire.rs b/src/blocks/src/redstone/tripwire.rs new file mode 100644 index 00000000..364b8267 --- /dev/null +++ b/src/blocks/src/redstone/tripwire.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::TripwireBlock; + +impl BlockBehavior for TripwireBlock {} diff --git a/src/blocks/src/redstone/tripwire_hook.rs b/src/blocks/src/redstone/tripwire_hook.rs new file mode 100644 index 00000000..a14a0c0a --- /dev/null +++ b/src/blocks/src/redstone/tripwire_hook.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::TripwireHookBlock; + +impl BlockBehavior for TripwireHookBlock {} diff --git a/src/blocks/src/redstone/wall_torch.rs b/src/blocks/src/redstone/wall_torch.rs new file mode 100644 index 00000000..75016123 --- /dev/null +++ b/src/blocks/src/redstone/wall_torch.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::WallRedstoneTorchBlock; + +impl BlockBehavior for WallRedstoneTorchBlock {} diff --git a/src/blocks/src/redstone/weighted_pressure_plate.rs b/src/blocks/src/redstone/weighted_pressure_plate.rs new file mode 100644 index 00000000..ed3af340 --- /dev/null +++ b/src/blocks/src/redstone/weighted_pressure_plate.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::WeightedPressurePlateBlock; + +impl BlockBehavior for WeightedPressurePlateBlock {} diff --git a/src/blocks/src/redstone/wire.rs b/src/blocks/src/redstone/wire.rs new file mode 100644 index 00000000..eded0acd --- /dev/null +++ b/src/blocks/src/redstone/wire.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::RedstoneWireBlock; + +impl BlockBehavior for RedstoneWireBlock {} diff --git a/src/blocks/src/skull.rs b/src/blocks/src/skull.rs new file mode 100644 index 00000000..e6704b86 --- /dev/null +++ b/src/blocks/src/skull.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SkullBlock; + +impl BlockBehavior for SkullBlock {} diff --git a/src/blocks/src/suspicious_block.rs b/src/blocks/src/suspicious_block.rs new file mode 100644 index 00000000..00604b7f --- /dev/null +++ b/src/blocks/src/suspicious_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::SuspiciousBlock; + +impl BlockBehavior for SuspiciousBlock {} diff --git a/src/blocks/src/wall_skull.rs b/src/blocks/src/wall_skull.rs new file mode 100644 index 00000000..8c9b1cae --- /dev/null +++ b/src/blocks/src/wall_skull.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::WallSkullBlock; + +impl BlockBehavior for WallSkullBlock {} diff --git a/src/blocks/src/waterloggable_block.rs b/src/blocks/src/waterloggable_block.rs new file mode 100644 index 00000000..b877b4de --- /dev/null +++ b/src/blocks/src/waterloggable_block.rs @@ -0,0 +1,4 @@ +use crate::BlockBehavior; +use temper_blocks_generated::WaterloggableBlock; + +impl BlockBehavior for WaterloggableBlock {} diff --git a/src/core/src/block_face.rs b/src/core/src/block_face.rs new file mode 100644 index 00000000..4a56e1ba --- /dev/null +++ b/src/core/src/block_face.rs @@ -0,0 +1,75 @@ +use bevy_math::IVec3; +use std::io::Read; +use temper_codec::decode::errors::NetDecodeError; +use temper_codec::decode::{NetDecode, NetDecodeOpts}; +use temper_codec::net_types::var_int::VarInt; +use temper_nbt::tokio::io::AsyncRead; + +#[derive(Debug, Clone)] +pub enum BlockFace { + Top, + Bottom, + North, + South, + East, + West, +} + +impl BlockFace { + pub fn is_x_axis(&self) -> bool { + matches!(self, BlockFace::East | BlockFace::West) + } + + pub fn is_y_axis(&self) -> bool { + matches!(self, BlockFace::Top | BlockFace::Bottom) + } + + pub fn is_z_axis(&self) -> bool { + matches!(self, BlockFace::North | BlockFace::South) + } + + /// Returns the translation vector that will get the block that touches this face. + pub fn translation_vec(&self) -> IVec3 { + match self { + BlockFace::Top => IVec3::new(0, 1, 0), + BlockFace::Bottom => IVec3::new(0, -1, 0), + BlockFace::North => IVec3::new(0, 0, -1), + BlockFace::South => IVec3::new(0, 0, 1), + BlockFace::East => IVec3::new(1, 0, 0), + BlockFace::West => IVec3::new(-1, 0, 0), + } + } +} + +impl NetDecode for BlockFace { + fn decode(reader: &mut R, opts: &NetDecodeOpts) -> Result { + let VarInt(data) = VarInt::decode(reader, opts)?; + + match data { + 0 => Ok(BlockFace::Bottom), + 1 => Ok(BlockFace::Top), + 2 => Ok(BlockFace::North), + 3 => Ok(BlockFace::South), + 4 => Ok(BlockFace::West), + 5 => Ok(BlockFace::East), + _ => Err(NetDecodeError::InvalidEnumVariant), + } + } + + async fn decode_async( + reader: &mut R, + opts: &NetDecodeOpts, + ) -> Result { + let VarInt(data) = VarInt::decode_async(reader, opts).await?; + + match data { + 0 => Ok(BlockFace::Bottom), + 1 => Ok(BlockFace::Top), + 2 => Ok(BlockFace::North), + 3 => Ok(BlockFace::South), + 4 => Ok(BlockFace::West), + 5 => Ok(BlockFace::East), + _ => Err(NetDecodeError::InvalidEnumVariant), + } + } +} diff --git a/src/core/src/lib.rs b/src/core/src/lib.rs index af38f11f..886ae262 100644 --- a/src/core/src/lib.rs +++ b/src/core/src/lib.rs @@ -2,6 +2,7 @@ pub mod errors; // Core structs/types. Usually used in ECS Components. pub mod block_data; +pub mod block_face; pub mod block_state_id; pub mod color; pub mod dimension; diff --git a/src/game_systems/src/packets/Cargo.toml b/src/game_systems/src/packets/Cargo.toml index efe130c4..ee909cb7 100644 --- a/src/game_systems/src/packets/Cargo.toml +++ b/src/game_systems/src/packets/Cargo.toml @@ -17,6 +17,7 @@ temper-commands = { workspace = true } temper-net-runtime = { workspace = true } temper-codec = { workspace = true } temper-config = { workspace = true } +temper-blocks = { workspace = true } once_cell = { workspace = true } serde_json = { workspace = true } temper-macros = { workspace = true } diff --git a/src/game_systems/src/packets/src/place_block.rs b/src/game_systems/src/packets/src/place_block.rs index 317adf59..f35ee2cf 100644 --- a/src/game_systems/src/packets/src/place_block.rs +++ b/src/game_systems/src/packets/src/place_block.rs @@ -7,24 +7,23 @@ use temper_components::{bounds::CollisionBounds, player::sneak::SneakState}; use temper_core::pos::BlockPos; use temper_messages::BlockInteractMessage; -use temper_net_runtime::connection::StreamWriter; -use temper_protocol::PlaceBlockReceiver; -use temper_protocol::outgoing::block_change_ack::BlockChangeAck; -use temper_protocol::outgoing::block_update::BlockUpdate; -use temper_state::GlobalStateResource; -use tracing::{debug, error, trace}; - use bevy_math::DVec3; -use block_placing::PlacedBlocks; -use std::collections::HashMap; +use temper_blocks::BlockDispatch; use temper_components::player::rotation::Rotation; use temper_config::server_config::get_global_config; +use temper_core::block_state_id::ITEM_TO_BLOCK_MAPPING; use temper_core::dimension::Dimension; use temper_core::mq; use temper_inventories::hotbar::Hotbar; use temper_inventories::inventory::Inventory; use temper_messages::world_change::WorldChange; +use temper_net_runtime::connection::StreamWriter; +use temper_protocol::PlaceBlockReceiver; +use temper_protocol::outgoing::block_change_ack::BlockChangeAck; +use temper_protocol::outgoing::block_update::BlockUpdate; +use temper_state::GlobalStateResource; use temper_text::{Color, NamedColor, TextComponentBuilder}; +use tracing::{debug, error, trace}; pub fn handle( receiver: Res, @@ -43,7 +42,7 @@ pub fn handle( mut block_interact: MessageWriter, ) { 'ev_loop: for (event, eid) in receiver.0.try_iter() { - let Ok((entity, conn, inventory, hotbar, pos, rot, sneak)) = query.get(eid) else { + let Ok((entity, conn, inventory, hotbar, _pos, _rot, sneak)) = query.get(eid) else { debug!("Could not get connection for entity {:?}", eid); continue; }; @@ -110,18 +109,9 @@ pub fn handle( trace!("Block placement out of bounds: {}", block_pos); continue 'ev_loop; } - let offset_pos = block_pos - + match event.face.0 { - 0 => (0, -1, 0), - 1 => (0, 1, 0), - 2 => (0, 0, -1), - 3 => (0, 0, 1), - 4 => (-1, 0, 0), - 5 => (1, 0, 0), - _ => (0, 0, 0), - }; + let offset_pos = block_pos + event.face.translation_vec().into(); - let block_clicked = { + let _block_clicked = { let chunk = state .0 .world @@ -166,42 +156,64 @@ pub fn handle( chunk.get_block(offset_pos.chunk_block_pos()) }; - let placed_blocks = block_placing::place_item( - state.0.clone(), - block_placing::BlockPlaceContext { - block_clicked, - block_position: offset_pos, - face_clicked: match event.face.0 { - 0 => block_placing::BlockFace::Bottom, - 1 => block_placing::BlockFace::Top, - 2 => block_placing::BlockFace::North, - 3 => block_placing::BlockFace::South, - 4 => block_placing::BlockFace::West, - 5 => block_placing::BlockFace::East, - _ => { - debug!("Invalid block face"); - continue 'ev_loop; - } - }, - click_position: DVec3::new( - event.cursor_x as f64, - event.cursor_y as f64, - event.cursor_z as f64, - ), - player_position: *pos, - player_rotation: *rot, - item_used: item_id, - }, - ) - .unwrap_or_else(|err| { - error!("Block placement failed: {:?}", err); - PlacedBlocks { - blocks: HashMap::new(), - take_item: false, - } + let mut block_state = ITEM_TO_BLOCK_MAPPING + .get() + .unwrap() + .get(&(item_id.as_u32() as i32)) + .copied() + .unwrap(); + + block_state.get_placement_state(temper_blocks::PlacementContext { + face: event.face, + cursor: DVec3::new( + event.cursor_x as _, + event.cursor_y as _, + event.cursor_z as _, + ), + block_clicked: block_pos, + block_pos: offset_pos, + level: &state.0.world, + dimension: Dimension::Overworld, }); - for (block_pos, block_state) in placed_blocks.blocks { + let placed_blocks = vec![(offset_pos, block_state)]; + + // let placed_blocks = block_placing::place_item( + // state.0.clone(), + // block_placing::BlockPlaceContext { + // block_clicked, + // block_position: offset_pos, + // face_clicked: match event.face.0 { + // 0 => block_placing::BlockFace::Bottom, + // 1 => block_placing::BlockFace::Top, + // 2 => block_placing::BlockFace::North, + // 3 => block_placing::BlockFace::South, + // 4 => block_placing::BlockFace::West, + // 5 => block_placing::BlockFace::East, + // _ => { + // debug!("Invalid block face"); + // continue 'ev_loop; + // } + // }, + // click_position: DVec3::new( + // event.cursor_x as f64, + // event.cursor_y as f64, + // event.cursor_z as f64, + // ), + // player_position: *pos, + // player_rotation: *rot, + // item_used: item_id, + // }, + // ) + // .unwrap_or_else(|err| { + // error!("Block placement failed: {:?}", err); + // PlacedBlocks { + // blocks: HashMap::new(), + // take_item: false, + // } + // }); + + for (block_pos, block_state) in placed_blocks { let block_chunk = block_pos.chunk(); world_change.write(WorldChange { chunk: Some(block_chunk), diff --git a/src/net/protocol/src/incoming/place_block.rs b/src/net/protocol/src/incoming/place_block.rs index c3692543..703e88d1 100644 --- a/src/net/protocol/src/incoming/place_block.rs +++ b/src/net/protocol/src/incoming/place_block.rs @@ -1,5 +1,6 @@ use temper_codec::net_types::network_position::NetworkPosition; use temper_codec::net_types::var_int::VarInt; +use temper_core::block_face::BlockFace; use temper_macros::{NetDecode, packet}; #[derive(NetDecode, Debug)] @@ -7,7 +8,7 @@ use temper_macros::{NetDecode, packet}; pub struct PlaceBlock { pub hand: VarInt, pub position: NetworkPosition, - pub face: VarInt, + pub face: BlockFace, pub cursor_x: f32, pub cursor_y: f32, pub cursor_z: f32,