diff --git a/Cargo.lock b/Cargo.lock index 39b54e29..f3b5df08 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,9 +45,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.53" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" dependencies = [ "proc-macro2", "quote", @@ -78,6 +78,13 @@ dependencies = [ "uuid", ] +[[package]] +name = "azalea-block" +version = "0.1.0" +dependencies = [ + "block-macros", +] + [[package]] name = "azalea-brigadier" version = "0.1.0" @@ -176,6 +183,7 @@ dependencies = [ name = "azalea-world" version = "0.1.0" dependencies = [ + "azalea-block", "azalea-core", "azalea-nbt", "azalea-protocol", @@ -196,6 +204,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bot" version = "0.1.0" @@ -220,9 +237,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "byteorder" @@ -458,13 +475,11 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ - "cfg-if", "crc32fast", - "libc", "miniz_oxide", ] @@ -729,9 +744,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ "adler", ] @@ -1104,9 +1119,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" +checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c" [[package]] name = "serde" @@ -1207,9 +1222,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" dependencies = [ "proc-macro2", "quote", @@ -1272,9 +1287,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.18.2" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" dependencies = [ "bytes", "libc", @@ -1290,9 +1305,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 6c1fcaab..484da0b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "azalea-crypto", "azalea-world", "azalea-language", + "azalea-block", ] [profile.release] diff --git a/README.md b/README.md index e57b4728..f0975733 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Azalea -A Rust crate for creating Minecraft bots. +A collection of Rust crates for creating Minecraft bots and other utilities.

Azalea diff --git a/azalea-block/Cargo.toml b/azalea-block/Cargo.toml new file mode 100644 index 00000000..edeba385 --- /dev/null +++ b/azalea-block/Cargo.toml @@ -0,0 +1,11 @@ +[package] +edition = "2021" +name = "azalea-block" +version = "0.1.0" + +[lib] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +block-macros = {path = "./block-macros"} diff --git a/azalea-block/README.md b/azalea-block/README.md new file mode 100644 index 00000000..39843ef4 --- /dev/null +++ b/azalea-block/README.md @@ -0,0 +1,8 @@ +# Azalea Block + +Representation of Minecraft block states. + +There's two main things here, the `BlockState` enum and the `Block` trait. +`BlockState` is a simple enum with every possible block state as variant, and `Block` is a heavier trait which lets you access information about a block more easily. + +Every block is a struct that implements `Block`. You can freely convert between `BlockState` and `Block` with .into(). diff --git a/azalea-block/block-macros/Cargo.toml b/azalea-block/block-macros/Cargo.toml new file mode 100644 index 00000000..03b19e1d --- /dev/null +++ b/azalea-block/block-macros/Cargo.toml @@ -0,0 +1,14 @@ +[package] +edition = "2021" +name = "block-macros" +version = "0.1.0" + +[lib] +proc-macro = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +proc-macro2 = "1.0.39" +quote = "1.0.18" +syn = "1.0.95" diff --git a/azalea-block/block-macros/src/lib.rs b/azalea-block/block-macros/src/lib.rs new file mode 100644 index 00000000..6206bb65 --- /dev/null +++ b/azalea-block/block-macros/src/lib.rs @@ -0,0 +1,496 @@ +mod utils; + +use proc_macro::TokenStream; +use quote::quote; +use std::collections::HashMap; +use syn::{ + self, braced, + parse::{Parse, ParseStream, Result}, + parse_macro_input, + punctuated::Punctuated, + Expr, Ident, LitStr, Token, +}; +use utils::{combinations_of, to_pascal_case}; + +struct PropertyDefinition { + name: LitStr, + struct_name: Ident, + variants: Punctuated, +} +struct PropertyDefinitions { + properties: Vec, +} + +struct PropertyAndDefault { + struct_name: Ident, + default: Ident, +} +struct PropertyWithNameAndDefault { + name: String, + struct_name: Ident, + default: Ident, +} +struct BlockDefinition { + name: Ident, + behavior: Expr, + properties_and_defaults: Vec, +} +impl PropertyAndDefault { + fn into_property_with_name_and_default(&self, name: String) -> PropertyWithNameAndDefault { + PropertyWithNameAndDefault { + name, + struct_name: self.struct_name.clone(), + default: self.default.clone(), + } + } +} +struct BlockDefinitions { + blocks: Vec, +} +struct MakeBlockStates { + property_definitions: PropertyDefinitions, + block_definitions: BlockDefinitions, +} + +impl Parse for PropertyDefinition { + fn parse(input: ParseStream) -> Result { + // "face" => Face { + // Floor, + // Wall, + // Ceiling + // }, + + // if you're wondering, the reason it's in quotes is because `type` is + // a keyword in rust so if we don't put it in quotes it results in a + // syntax error + let name = input.parse()?; + input.parse::]>()?; + let struct_name = input.parse()?; + + let content; + braced!(content in input); + let variants = content.parse_terminated(Ident::parse)?; + + input.parse::()?; + Ok(PropertyDefinition { + name, + struct_name, + variants, + }) + } +} + +impl Parse for PropertyDefinitions { + fn parse(input: ParseStream) -> Result { + let mut property_definitions = Vec::new(); + while !input.is_empty() { + property_definitions.push(input.parse()?); + } + + Ok(PropertyDefinitions { + properties: property_definitions, + }) + } +} + +impl Parse for BlockDefinition { + fn parse(input: ParseStream) -> Result { + // acacia_button => BlockBehavior::default(), { + // Facing=North, + // Powered=False, + // Face=Wall, + // }, + let name = input.parse()?; + input.parse::]>()?; + let behavior = input.parse()?; + + input.parse::()?; + let content; + braced!(content in input); + + let mut properties_and_defaults = Vec::new(); + + loop { + let property = match content.parse() { + Ok(property) => property, + Err(_) => break, + }; + content.parse::()?; + let property_default = content.parse()?; + properties_and_defaults.push(PropertyAndDefault { + struct_name: property, + default: property_default, + }); + if content.parse::().is_err() { + break; + } + } + input.parse::()?; + Ok(BlockDefinition { + name, + behavior, + properties_and_defaults, + }) + } +} + +impl Parse for BlockDefinitions { + fn parse(input: ParseStream) -> Result { + let mut blocks = Vec::new(); + while !input.is_empty() { + blocks.push(input.parse()?); + } + + Ok(BlockDefinitions { blocks }) + } +} + +impl Parse for MakeBlockStates { + fn parse(input: ParseStream) -> Result { + // Properties => { ... } Blocks => { ... } + let properties_ident = input.parse::()?; + assert_eq!(properties_ident.to_string(), "Properties"); + input.parse::]>()?; + let content; + braced!(content in input); + let properties = content.parse()?; + + input.parse::()?; + + let blocks_ident = input.parse::()?; + assert_eq!(blocks_ident.to_string(), "Blocks"); + input.parse::]>()?; + let content; + braced!(content in input); + let blocks = content.parse()?; + + Ok(MakeBlockStates { + property_definitions: properties, + block_definitions: blocks, + }) + } +} + +#[proc_macro] +pub fn make_block_states(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as MakeBlockStates); + + let mut property_enums = quote! {}; + let mut properties_map = HashMap::new(); + let mut property_struct_names_to_names = HashMap::new(); + + let mut state_id: usize = 0; + + for property in &input.property_definitions.properties { + let mut property_enum_variants = quote! {}; + let mut property_from_number_variants = quote! {}; + let mut property_enum_variant_names = Vec::new(); + + let property_struct_name = &property.struct_name; + + property_struct_names_to_names.insert( + property_struct_name.to_string(), + property.name.clone().value(), + ); + + for i in 0..property.variants.len() { + let variant = &property.variants[i]; + + let i_lit = syn::Lit::Int(syn::LitInt::new( + &i.to_string(), + proc_macro2::Span::call_site(), + )); + + property_enum_variants.extend(quote! { + #variant = #i_lit, + }); + + // i_lit is used here instead of i because otherwise it says 0size + // in the expansion and that looks uglier + property_from_number_variants.extend(quote! { + #i_lit => #property_struct_name::#variant, + }); + + property_enum_variant_names.push(variant.to_string()); + } + + property_enums.extend(quote! { + #[derive(Debug, Clone, Copy)] + pub enum #property_struct_name { + #property_enum_variants + } + + impl From for #property_struct_name { + fn from(value: usize) -> Self { + match value { + #property_from_number_variants + _ => panic!("Invalid property value: {}", value), + } + } + } + }); + properties_map.insert( + property_struct_name.to_string(), + property_enum_variant_names, + ); + } + + let mut block_state_enum_variants = quote! {}; + let mut block_structs = quote! {}; + let mut from_state_to_block_match = quote! {}; + for block in &input.block_definitions.blocks { + let block_property_names = &block + .properties_and_defaults + .iter() + .map(|p| p.struct_name.to_string()) + .collect::>(); + let mut block_properties_vec = Vec::new(); + for property_name in block_property_names { + let property_variants = properties_map + .get(property_name) + .expect(format!("Property '{}' not found", property_name).as_str()) + .clone(); + block_properties_vec.push(property_variants); + } + + let mut properties_with_name: Vec = + Vec::with_capacity(block.properties_and_defaults.len()); + for property in &block.properties_and_defaults { + let index: Option = if block + .properties_and_defaults + .iter() + .filter(|p| p.struct_name == property.struct_name) + .count() + > 1 + { + Some( + properties_with_name + .iter() + .filter(|p| p.struct_name == property.struct_name) + .count(), + ) + } else { + None + }; + let mut property_name = property_struct_names_to_names + .get(&property.struct_name.to_string()) + .expect(format!("Property '{}' is bad", property.struct_name).as_str()) + .clone(); + if let Some(index) = index { + property_name.push_str(&format!("_{}", &index.to_string())); + } + properties_with_name + .push(property.into_property_with_name_and_default(property_name.clone())); + } + + // pub face: properties::Face, + // pub facing: properties::Facing, + // pub powered: properties::Powered, + // or + // pub has_bottle_0: HasBottle, + // pub has_bottle_1: HasBottle, + // pub has_bottle_2: HasBottle, + let mut block_struct_fields = quote! {}; + for PropertyWithNameAndDefault { + struct_name, name, .. + } in &properties_with_name + { + // let property_name_snake = + // Ident::new(&property.to_string(), proc_macro2::Span::call_site()); + let name_ident = Ident::new(&name, proc_macro2::Span::call_site()); + block_struct_fields.extend(quote! { + pub #name_ident: #struct_name, + }) + } + + let block_name_pascal_case = Ident::new( + &to_pascal_case(&block.name.to_string()), + proc_macro2::Span::call_site(), + ); + let block_struct_name = Ident::new( + &format!("{}Block", block_name_pascal_case), + proc_macro2::Span::call_site(), + ); + + let mut from_block_to_state_match_inner = quote! {}; + + let first_state_id = state_id; + + // if there's no properties, then the block is just a single state + if block_properties_vec.len() == 0 { + block_state_enum_variants.extend(quote! { + #block_name_pascal_case, + }); + state_id += 1; + } + for combination in combinations_of(&block_properties_vec) { + state_id += 1; + let variant_name = Ident::new( + &format!( + "{}_{}", + block_name_pascal_case, + combination + .iter() + .map(|v| v.to_string()) + .collect::>() + .join("") + ), + proc_macro2::Span::call_site(), + ); + block_state_enum_variants.extend(quote! { + #variant_name, + }); + + // face: properties::Face::Floor, + // facing: properties::Facing::North, + // powered: properties::Powered::True, + let mut from_block_to_state_combination_match_inner = quote! {}; + for i in 0..properties_with_name.len() { + let property = &properties_with_name[i]; + let property_name = &property.name; + let property_name_ident = Ident::new(property_name, proc_macro2::Span::call_site()); + let property_struct_name_ident = &property.struct_name; + let variant = + Ident::new(&combination[i].to_string(), proc_macro2::Span::call_site()); + + from_block_to_state_combination_match_inner.extend(quote! { + #property_name_ident: #property_struct_name_ident::#variant, + }); + } + + from_block_to_state_match_inner.extend(quote! { + #block_struct_name { + #from_block_to_state_combination_match_inner + } => BlockState::#variant_name, + }); + } + + // 7035..=7058 => { + // let b = b - 7035; + // &AcaciaButtonBlock { + // powered: Powered::from((b / 1) % 2), + // facing: Facing::from((b / 2) % 4), + // face: Face::from((b / 8) % 3), + // } + // } + let mut from_state_to_block_inner = quote! {}; + let mut division = 1usize; + for i in (0..properties_with_name.len()).rev() { + let PropertyWithNameAndDefault { + struct_name: property_struct_name_ident, + name: property_name, + .. + } = &properties_with_name[i]; + + let property_variants = &block_properties_vec[i]; + let property_variants_count = property_variants.len(); + let property_name_ident = Ident::new(property_name, proc_macro2::Span::call_site()); + from_state_to_block_inner.extend(quote! { + #property_name_ident: #property_struct_name_ident::from((b / #division) % #property_variants_count), + }); + + division *= property_variants_count; + } + + let last_state_id = state_id - 1; + from_state_to_block_match.extend(quote! { + #first_state_id..=#last_state_id => { + let b = b - #first_state_id; + Box::new(#block_struct_name { + #from_state_to_block_inner + }) + }, + }); + + let mut block_default_fields = quote! {}; + for PropertyWithNameAndDefault { + struct_name: struct_name_ident, + name, + default: property_default, + } in properties_with_name + { + let name_ident = Ident::new(&name, proc_macro2::Span::call_site()); + block_default_fields.extend(quote! { + #name_ident: #struct_name_ident::#property_default, + }) + } + + let block_behavior = &block.behavior; + let block_id = block.name.to_string(); + + let from_block_to_state_match = if block.properties_and_defaults.len() > 0 { + quote! { + match b { + #from_block_to_state_match_inner + } + } + } else { + quote! { BlockState::#block_name_pascal_case } + }; + + let block_struct = quote! { + #[derive(Debug)] + pub struct #block_struct_name { + #block_struct_fields + } + + impl Block for #block_struct_name { + fn behavior(&self) -> BlockBehavior { + #block_behavior + } + fn id(&self) -> &'static str { + #block_id + } + } + + impl From<#block_struct_name> for BlockState { + fn from(b: #block_struct_name) -> Self { + #from_block_to_state_match + } + } + + impl Default for #block_struct_name { + fn default() -> Self { + Self { + #block_default_fields + } + } + } + }; + + block_structs.extend(block_struct); + } + + let last_state_id = (state_id - 1) as u32; + quote! { + #property_enums + + #[repr(u32)] + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + pub enum BlockState { + #block_state_enum_variants + } + + #block_structs + + impl From for Box { + fn from(b: BlockState) -> Self { + let b = b as usize; + match b { + #from_state_to_block_match + _ => panic!("Invalid block state: {}", b), + } + } + } + + impl BlockState { + /// Returns the highest possible state + #[inline] + pub fn max_state() -> u32 { + #last_state_id + } + } + + } + .into() +} diff --git a/azalea-block/block-macros/src/utils.rs b/azalea-block/block-macros/src/utils.rs new file mode 100644 index 00000000..019fd60f --- /dev/null +++ b/azalea-block/block-macros/src/utils.rs @@ -0,0 +1,42 @@ +pub fn combinations_of(items: &[Vec]) -> Vec> { + let mut combinations = Vec::new(); + if items.len() == 0 { + return combinations; + }; + if items.len() == 1 { + for item in &items[0] { + combinations.push(vec![item.clone()]); + } + return combinations; + }; + + for i in 0..items[0].len() { + let item = &items[0][i]; + for other_combinations in combinations_of(&items[1..]) { + let mut combination = Vec::new(); + combination.push(item.clone()); + combination.extend(other_combinations); + combinations.push(combination); + } + } + + combinations +} + +pub fn to_pascal_case(s: &str) -> String { + let mut result = String::new(); + let mut prev_was_underscore = true; // set to true by default so the first character is capitalized + for c in s.chars() { + if c == '_' { + prev_was_underscore = true; + } else { + if prev_was_underscore { + result.push(c.to_ascii_uppercase()); + prev_was_underscore = false; + } else { + result.push(c); + } + } + } + result +} diff --git a/azalea-block/src/behavior.rs b/azalea-block/src/behavior.rs new file mode 100644 index 00000000..949f3bd8 --- /dev/null +++ b/azalea-block/src/behavior.rs @@ -0,0 +1,12 @@ +#[derive(Default)] +pub struct BlockBehavior { + pub has_collision: bool, +} + +impl BlockBehavior { + #[inline] + pub fn no_collision(mut self) -> Self { + self.has_collision = false; + self + } +} diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs new file mode 100644 index 00000000..05973797 --- /dev/null +++ b/azalea-block/src/blocks.rs @@ -0,0 +1,4954 @@ +use crate::BlockBehavior; +use block_macros::make_block_states; + +pub trait Block { + fn behavior(&self) -> BlockBehavior; + fn id(&self) -> &'static str; +} + +make_block_states! { + Properties => { + "snowy" => Snowy { + True, + False, + }, + "stage" => OakSaplingStage { + _0, + _1, + }, + "stage" => SpruceSaplingStage { + _0, + _1, + }, + "stage" => BirchSaplingStage { + _0, + _1, + }, + "stage" => JungleSaplingStage { + _0, + _1, + }, + "stage" => AcaciaSaplingStage { + _0, + _1, + }, + "stage" => DarkOakSaplingStage { + _0, + _1, + }, + "age" => MangrovePropaguleAge { + _0, + _1, + _2, + _3, + _4, + }, + "hanging" => Hanging { + True, + False, + }, + "stage" => MangrovePropaguleStage { + _0, + _1, + }, + "waterlogged" => Waterlogged { + True, + False, + }, + "level" => WaterLevel { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "level" => LavaLevel { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "axis" => Axis { + X, + Y, + Z, + }, + "distance" => OakLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "persistent" => Persistent { + True, + False, + }, + "distance" => SpruceLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "distance" => BirchLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "distance" => JungleLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "distance" => AcaciaLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "distance" => DarkOakLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "distance" => MangroveLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "distance" => AzaleaLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "distance" => FloweringAzaleaLeavesDistance { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "facing" => FacingCubic { + North, + East, + South, + West, + Up, + Down, + }, + "triggered" => Triggered { + True, + False, + }, + "instrument" => Instrument { + Harp, + Basedrum, + Snare, + Hat, + Bass, + Flute, + Bell, + Guitar, + Chime, + Xylophone, + IronXylophone, + CowBell, + Didgeridoo, + Bit, + Banjo, + Pling, + }, + "note" => NoteBlockNote { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + _16, + _17, + _18, + _19, + _20, + _21, + _22, + _23, + _24, + }, + "powered" => Powered { + True, + False, + }, + "facing" => FacingCardinal { + North, + South, + West, + East, + }, + "occupied" => Occupied { + True, + False, + }, + "part" => Part { + Head, + Foot, + }, + "shape" => RailShape { + NorthSouth, + EastWest, + AscendingEast, + AscendingWest, + AscendingNorth, + AscendingSouth, + }, + "extended" => Extended { + True, + False, + }, + "half" => Half { + Upper, + Lower, + }, + "kind" => PistonType { + Normal, + Sticky, + }, + "short" => Short { + True, + False, + }, + "unstable" => Unstable { + True, + False, + }, + "age" => FireAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "east" => East { + True, + False, + }, + "north" => North { + True, + False, + }, + "south" => South { + True, + False, + }, + "up" => Up { + True, + False, + }, + "west" => West { + True, + False, + }, + "half" => TopBottom { + Top, + Bottom, + }, + "shape" => StairShape { + Straight, + InnerLeft, + InnerRight, + OuterLeft, + OuterRight, + }, + "kind" => ChestType { + Single, + Left, + Right, + }, + "east" => WireEast { + Up, + Side, + None, + }, + "north" => WireNorth { + Up, + Side, + None, + }, + "power" => RedstoneWirePower { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "south" => WireSouth { + Up, + Side, + None, + }, + "west" => WireWest { + Up, + Side, + None, + }, + "age" => WheatAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "moisture" => FarmlandMoisture { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "lit" => Lit { + True, + False, + }, + "rotation" => OakSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => SpruceSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => BirchSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => AcaciaSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => JungleSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => DarkOakSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => MangroveSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "hinge" => Hinge { + Left, + Right, + }, + "open" => Open { + True, + False, + }, + "shape" => Shape { + NorthSouth, + EastWest, + AscendingEast, + AscendingWest, + AscendingNorth, + AscendingSouth, + SouthEast, + SouthWest, + NorthWest, + NorthEast, + }, + "face" => Face { + Floor, + Wall, + Ceiling, + }, + "layers" => SnowLayers { + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + }, + "age" => CactusAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "age" => SugarCaneAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "has_record" => HasRecord { + True, + False, + }, + "axis" => AxisXZ { + X, + Z, + }, + "bites" => CakeBites { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + }, + "delay" => RepeaterDelay { + _1, + _2, + _3, + _4, + }, + "locked" => Locked { + True, + False, + }, + "down" => Down { + True, + False, + }, + "age" => PumpkinStemAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "age" => MelonStemAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "berries" => TrueFalse { + True, + False, + }, + "in_wall" => InWall { + True, + False, + }, + "age" => NetherWartAge { + _0, + _1, + _2, + _3, + }, + "has_bottle" => HasBottle { + True, + False, + }, + "level" => WaterCauldronLevel { + _1, + _2, + _3, + }, + "level" => PowderSnowCauldronLevel { + _1, + _2, + _3, + }, + "eye" => HasEye { + True, + False, + }, + "age" => CocoaAge { + _0, + _1, + _2, + }, + "attached" => Attached { + True, + False, + }, + "disarmed" => Disarmed { + True, + False, + }, + "conditional" => Conditional { + True, + False, + }, + "east" => EastWall { + None, + Low, + Tall, + }, + "north" => NorthWall { + None, + Low, + Tall, + }, + "south" => SouthWall { + None, + Low, + Tall, + }, + "west" => WestWall { + None, + Low, + Tall, + }, + "age" => CarrotsAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "age" => PotatoesAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "rotation" => SkeletonSkullRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => WitherSkeletonSkullRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => ZombieHeadRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => PlayerHeadRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => CreeperHeadRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => DragonHeadRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "power" => LightWeightedPressurePlatePower { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "power" => HeavyWeightedPressurePlatePower { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "mode" => ComparatorType { + Compare, + Subtract, + }, + "inverted" => Inverted { + True, + False, + }, + "power" => DaylightDetectorPower { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "enabled" => Enabled { + True, + False, + }, + "facing" => Facing { + Down, + North, + South, + West, + East, + }, + "level" => LightLevel { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "kind" => Type { + Top, + Bottom, + Double, + }, + "rotation" => WhiteBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => OrangeBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => MagentaBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => LightBlueBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => YellowBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => LimeBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => PinkBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => GrayBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => LightGrayBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => CyanBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => PurpleBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => BlueBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => BrownBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => GreenBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => RedBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => BlackBannerRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "age" => ChorusFlowerAge { + _0, + _1, + _2, + _3, + _4, + _5, + }, + "age" => BeetrootsAge { + _0, + _1, + _2, + _3, + }, + "age" => FrostedIceAge { + _0, + _1, + _2, + _3, + }, + "age" => KelpAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + _16, + _17, + _18, + _19, + _20, + _21, + _22, + _23, + _24, + _25, + }, + "eggs" => TurtleEggEggs { + _1, + _2, + _3, + _4, + }, + "hatch" => TurtleEggHatch { + _0, + _1, + _2, + }, + "pickles" => SeaPicklePickles { + _1, + _2, + _3, + _4, + }, + "age" => BambooAge { + _0, + _1, + }, + "leaves" => Leaves { + None, + Small, + Large, + }, + "stage" => BambooStage { + _0, + _1, + }, + "drag" => DragDown { + True, + False, + }, + "bottom" => Bottom { + True, + False, + }, + "distance" => ScaffoldingDistance { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + }, + "has_book" => HasBook { + True, + False, + }, + "attachment" => Attachment { + Floor, + Ceiling, + SingleWall, + DoubleWall, + }, + "signal_fire" => SignalFire { + True, + False, + }, + "age" => SweetBerryBushAge { + _0, + _1, + _2, + _3, + }, + "age" => WeepingVinesAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + _16, + _17, + _18, + _19, + _20, + _21, + _22, + _23, + _24, + _25, + }, + "age" => TwistingVinesAge { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + _16, + _17, + _18, + _19, + _20, + _21, + _22, + _23, + _24, + _25, + }, + "rotation" => CrimsonSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "rotation" => WarpedSignRotation { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "mode" => Mode { + Save, + Load, + Corner, + Data, + }, + "orientation" => Orientation { + DownEast, + DownNorth, + DownSouth, + DownWest, + UpEast, + UpNorth, + UpSouth, + UpWest, + WestUp, + EastUp, + NorthUp, + SouthUp, + }, + "level" => ComposterLevel { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + }, + "power" => TargetOutputPower { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "honey_level" => BeeNestHoneyLevel { + _0, + _1, + _2, + _3, + _4, + _5, + }, + "honey_level" => BeehiveHoneyLevel { + _0, + _1, + _2, + _3, + _4, + _5, + }, + "charges" => RespawnAnchorCharge { + _0, + _1, + _2, + _3, + _4, + }, + "candles" => CandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => WhiteCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => OrangeCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => MagentaCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => LightBlueCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => YellowCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => LimeCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => PinkCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => GrayCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => LightGrayCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => CyanCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => PurpleCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => BlueCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => BrownCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => GreenCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => RedCandleCandles { + _1, + _2, + _3, + _4, + }, + "candles" => BlackCandleCandles { + _1, + _2, + _3, + _4, + }, + "power" => SculkSensorPower { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + }, + "sculk_sensor_phase" => Phase { + Inactive, + Active, + Cooldown, + }, + "bloom" => Pulse { + True, + False, + }, + "can_summon" => CanSummon { + True, + False, + }, + "shrieking" => Shrieking { + True, + False, + }, + "thickness" => Thickness { + TipMerge, + Tip, + Frustum, + Middle, + Base, + }, + "vertical_direction" => TipDirection { + Up, + Down, + }, + "age" => _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25 { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _10, + _11, + _12, + _13, + _14, + _15, + _16, + _17, + _18, + _19, + _20, + _21, + _22, + _23, + _24, + _25, + }, + "tilt" => Tilt { + None, + Unstable, + Partial, + Full, + }, + "axis" => XYZ { + X, + Y, + Z, + }, + }, + Blocks => { + air => BlockBehavior::default(), { + }, + stone => BlockBehavior::default(), { + }, + granite => BlockBehavior::default(), { + }, + polished_granite => BlockBehavior::default(), { + }, + diorite => BlockBehavior::default(), { + }, + polished_diorite => BlockBehavior::default(), { + }, + andesite => BlockBehavior::default(), { + }, + polished_andesite => BlockBehavior::default(), { + }, + grass_block => BlockBehavior::default(), { + Snowy=False, + }, + dirt => BlockBehavior::default(), { + }, + coarse_dirt => BlockBehavior::default(), { + }, + podzol => BlockBehavior::default(), { + Snowy=False, + }, + cobblestone => BlockBehavior::default(), { + }, + oak_planks => BlockBehavior::default(), { + }, + spruce_planks => BlockBehavior::default(), { + }, + birch_planks => BlockBehavior::default(), { + }, + jungle_planks => BlockBehavior::default(), { + }, + acacia_planks => BlockBehavior::default(), { + }, + dark_oak_planks => BlockBehavior::default(), { + }, + mangrove_planks => BlockBehavior::default(), { + }, + oak_sapling => BlockBehavior::default(), { + OakSaplingStage=_0, + }, + spruce_sapling => BlockBehavior::default(), { + SpruceSaplingStage=_0, + }, + birch_sapling => BlockBehavior::default(), { + BirchSaplingStage=_0, + }, + jungle_sapling => BlockBehavior::default(), { + JungleSaplingStage=_0, + }, + acacia_sapling => BlockBehavior::default(), { + AcaciaSaplingStage=_0, + }, + dark_oak_sapling => BlockBehavior::default(), { + DarkOakSaplingStage=_0, + }, + mangrove_propagule => BlockBehavior::default(), { + MangrovePropaguleAge=_0, + Hanging=False, + MangrovePropaguleStage=_0, + Waterlogged=False, + }, + bedrock => BlockBehavior::default(), { + }, + water => BlockBehavior::default(), { + WaterLevel=_0, + }, + lava => BlockBehavior::default(), { + LavaLevel=_0, + }, + sand => BlockBehavior::default(), { + }, + red_sand => BlockBehavior::default(), { + }, + gravel => BlockBehavior::default(), { + }, + gold_ore => BlockBehavior::default(), { + }, + deepslate_gold_ore => BlockBehavior::default(), { + }, + iron_ore => BlockBehavior::default(), { + }, + deepslate_iron_ore => BlockBehavior::default(), { + }, + coal_ore => BlockBehavior::default(), { + }, + deepslate_coal_ore => BlockBehavior::default(), { + }, + nether_gold_ore => BlockBehavior::default(), { + }, + oak_log => BlockBehavior::default(), { + Axis=Y, + }, + spruce_log => BlockBehavior::default(), { + Axis=Y, + }, + birch_log => BlockBehavior::default(), { + Axis=Y, + }, + jungle_log => BlockBehavior::default(), { + Axis=Y, + }, + acacia_log => BlockBehavior::default(), { + Axis=Y, + }, + dark_oak_log => BlockBehavior::default(), { + Axis=Y, + }, + mangrove_log => BlockBehavior::default(), { + Axis=Y, + }, + mangrove_roots => BlockBehavior::default(), { + Waterlogged=False, + }, + muddy_mangrove_roots => BlockBehavior::default(), { + Axis=Y, + }, + stripped_spruce_log => BlockBehavior::default(), { + Axis=Y, + }, + stripped_birch_log => BlockBehavior::default(), { + Axis=Y, + }, + stripped_jungle_log => BlockBehavior::default(), { + Axis=Y, + }, + stripped_acacia_log => BlockBehavior::default(), { + Axis=Y, + }, + stripped_dark_oak_log => BlockBehavior::default(), { + Axis=Y, + }, + stripped_oak_log => BlockBehavior::default(), { + Axis=Y, + }, + stripped_mangrove_log => BlockBehavior::default(), { + Axis=Y, + }, + oak_wood => BlockBehavior::default(), { + Axis=Y, + }, + spruce_wood => BlockBehavior::default(), { + Axis=Y, + }, + birch_wood => BlockBehavior::default(), { + Axis=Y, + }, + jungle_wood => BlockBehavior::default(), { + Axis=Y, + }, + acacia_wood => BlockBehavior::default(), { + Axis=Y, + }, + dark_oak_wood => BlockBehavior::default(), { + Axis=Y, + }, + mangrove_wood => BlockBehavior::default(), { + Axis=Y, + }, + stripped_oak_wood => BlockBehavior::default(), { + Axis=Y, + }, + stripped_spruce_wood => BlockBehavior::default(), { + Axis=Y, + }, + stripped_birch_wood => BlockBehavior::default(), { + Axis=Y, + }, + stripped_jungle_wood => BlockBehavior::default(), { + Axis=Y, + }, + stripped_acacia_wood => BlockBehavior::default(), { + Axis=Y, + }, + stripped_dark_oak_wood => BlockBehavior::default(), { + Axis=Y, + }, + stripped_mangrove_wood => BlockBehavior::default(), { + Axis=Y, + }, + oak_leaves => BlockBehavior::default(), { + OakLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + spruce_leaves => BlockBehavior::default(), { + SpruceLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + birch_leaves => BlockBehavior::default(), { + BirchLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + jungle_leaves => BlockBehavior::default(), { + JungleLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + acacia_leaves => BlockBehavior::default(), { + AcaciaLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + dark_oak_leaves => BlockBehavior::default(), { + DarkOakLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + mangrove_leaves => BlockBehavior::default(), { + MangroveLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + azalea_leaves => BlockBehavior::default(), { + AzaleaLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + flowering_azalea_leaves => BlockBehavior::default(), { + FloweringAzaleaLeavesDistance=_7, + Persistent=False, + Waterlogged=False, + }, + sponge => BlockBehavior::default(), { + }, + wet_sponge => BlockBehavior::default(), { + }, + glass => BlockBehavior::default(), { + }, + lapis_ore => BlockBehavior::default(), { + }, + deepslate_lapis_ore => BlockBehavior::default(), { + }, + lapis_block => BlockBehavior::default(), { + }, + dispenser => BlockBehavior::default(), { + FacingCubic=North, + Triggered=False, + }, + sandstone => BlockBehavior::default(), { + }, + chiseled_sandstone => BlockBehavior::default(), { + }, + cut_sandstone => BlockBehavior::default(), { + }, + note_block => BlockBehavior::default(), { + Instrument=Harp, + NoteBlockNote=_0, + Powered=False, + }, + white_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + orange_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + magenta_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + light_blue_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + yellow_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + lime_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + pink_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + gray_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + light_gray_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + cyan_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + purple_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + blue_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + brown_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + green_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + red_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + black_bed => BlockBehavior::default(), { + FacingCardinal=North, + Occupied=False, + Part=Foot, + }, + powered_rail => BlockBehavior::default(), { + Powered=False, + RailShape=NorthSouth, + Waterlogged=False, + }, + detector_rail => BlockBehavior::default(), { + Powered=False, + RailShape=NorthSouth, + Waterlogged=False, + }, + sticky_piston => BlockBehavior::default(), { + Extended=False, + FacingCubic=North, + }, + cobweb => BlockBehavior::default(), { + }, + grass => BlockBehavior::default(), { + }, + fern => BlockBehavior::default(), { + }, + dead_bush => BlockBehavior::default(), { + }, + seagrass => BlockBehavior::default(), { + }, + tall_seagrass => BlockBehavior::default(), { + Half=Lower, + }, + piston => BlockBehavior::default(), { + Extended=False, + FacingCubic=North, + }, + piston_head => BlockBehavior::default(), { + PistonType=Normal, + FacingCubic=North, + Short=False, + }, + white_wool => BlockBehavior::default(), { + }, + orange_wool => BlockBehavior::default(), { + }, + magenta_wool => BlockBehavior::default(), { + }, + light_blue_wool => BlockBehavior::default(), { + }, + yellow_wool => BlockBehavior::default(), { + }, + lime_wool => BlockBehavior::default(), { + }, + pink_wool => BlockBehavior::default(), { + }, + gray_wool => BlockBehavior::default(), { + }, + light_gray_wool => BlockBehavior::default(), { + }, + cyan_wool => BlockBehavior::default(), { + }, + purple_wool => BlockBehavior::default(), { + }, + blue_wool => BlockBehavior::default(), { + }, + brown_wool => BlockBehavior::default(), { + }, + green_wool => BlockBehavior::default(), { + }, + red_wool => BlockBehavior::default(), { + }, + black_wool => BlockBehavior::default(), { + }, + moving_piston => BlockBehavior::default(), { + PistonType=Normal, + FacingCubic=North, + }, + dandelion => BlockBehavior::default(), { + }, + poppy => BlockBehavior::default(), { + }, + blue_orchid => BlockBehavior::default(), { + }, + allium => BlockBehavior::default(), { + }, + azure_bluet => BlockBehavior::default(), { + }, + red_tulip => BlockBehavior::default(), { + }, + orange_tulip => BlockBehavior::default(), { + }, + white_tulip => BlockBehavior::default(), { + }, + pink_tulip => BlockBehavior::default(), { + }, + oxeye_daisy => BlockBehavior::default(), { + }, + cornflower => BlockBehavior::default(), { + }, + wither_rose => BlockBehavior::default(), { + }, + lily_of_the_valley => BlockBehavior::default(), { + }, + brown_mushroom => BlockBehavior::default(), { + }, + red_mushroom => BlockBehavior::default(), { + }, + gold_block => BlockBehavior::default(), { + }, + iron_block => BlockBehavior::default(), { + }, + bricks => BlockBehavior::default(), { + }, + tnt => BlockBehavior::default(), { + Unstable=False, + }, + bookshelf => BlockBehavior::default(), { + }, + mossy_cobblestone => BlockBehavior::default(), { + }, + obsidian => BlockBehavior::default(), { + }, + torch => BlockBehavior::default(), { + }, + wall_torch => BlockBehavior::default(), { + FacingCardinal=North, + }, + fire => BlockBehavior::default(), { + FireAge=_0, + East=False, + North=False, + South=False, + Up=False, + West=False, + }, + soul_fire => BlockBehavior::default(), { + }, + spawner => BlockBehavior::default(), { + }, + oak_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + chest => BlockBehavior::default(), { + ChestType=Single, + FacingCardinal=North, + Waterlogged=False, + }, + redstone_wire => BlockBehavior::default(), { + WireEast=None, + WireNorth=None, + RedstoneWirePower=_0, + WireSouth=None, + WireWest=None, + }, + diamond_ore => BlockBehavior::default(), { + }, + deepslate_diamond_ore => BlockBehavior::default(), { + }, + diamond_block => BlockBehavior::default(), { + }, + crafting_table => BlockBehavior::default(), { + }, + wheat => BlockBehavior::default(), { + WheatAge=_0, + }, + farmland => BlockBehavior::default(), { + FarmlandMoisture=_0, + }, + furnace => BlockBehavior::default(), { + FacingCardinal=North, + Lit=False, + }, + oak_sign => BlockBehavior::default(), { + OakSignRotation=_0, + Waterlogged=False, + }, + spruce_sign => BlockBehavior::default(), { + SpruceSignRotation=_0, + Waterlogged=False, + }, + birch_sign => BlockBehavior::default(), { + BirchSignRotation=_0, + Waterlogged=False, + }, + acacia_sign => BlockBehavior::default(), { + AcaciaSignRotation=_0, + Waterlogged=False, + }, + jungle_sign => BlockBehavior::default(), { + JungleSignRotation=_0, + Waterlogged=False, + }, + dark_oak_sign => BlockBehavior::default(), { + DarkOakSignRotation=_0, + Waterlogged=False, + }, + mangrove_sign => BlockBehavior::default(), { + MangroveSignRotation=_0, + Waterlogged=False, + }, + oak_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + ladder => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + rail => BlockBehavior::default(), { + Shape=NorthSouth, + Waterlogged=False, + }, + cobblestone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + oak_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + spruce_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + birch_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + acacia_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + jungle_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + dark_oak_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + mangrove_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + lever => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + stone_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + iron_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + oak_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + spruce_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + birch_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + jungle_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + acacia_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + dark_oak_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + mangrove_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + redstone_ore => BlockBehavior::default(), { + Lit=False, + }, + deepslate_redstone_ore => BlockBehavior::default(), { + Lit=False, + }, + redstone_torch => BlockBehavior::default(), { + Lit=True, + }, + redstone_wall_torch => BlockBehavior::default(), { + FacingCardinal=North, + Lit=True, + }, + stone_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + snow => BlockBehavior::default(), { + SnowLayers=_1, + }, + ice => BlockBehavior::default(), { + }, + snow_block => BlockBehavior::default(), { + }, + cactus => BlockBehavior::default(), { + CactusAge=_0, + }, + clay => BlockBehavior::default(), { + }, + sugar_cane => BlockBehavior::default(), { + SugarCaneAge=_0, + }, + jukebox => BlockBehavior::default(), { + HasRecord=False, + }, + oak_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + pumpkin => BlockBehavior::default(), { + }, + netherrack => BlockBehavior::default(), { + }, + soul_sand => BlockBehavior::default(), { + }, + soul_soil => BlockBehavior::default(), { + }, + basalt => BlockBehavior::default(), { + Axis=Y, + }, + polished_basalt => BlockBehavior::default(), { + Axis=Y, + }, + soul_torch => BlockBehavior::default(), { + }, + soul_wall_torch => BlockBehavior::default(), { + FacingCardinal=North, + }, + glowstone => BlockBehavior::default(), { + }, + nether_portal => BlockBehavior::default(), { + AxisXZ=X, + }, + carved_pumpkin => BlockBehavior::default(), { + FacingCardinal=North, + }, + jack_o_lantern => BlockBehavior::default(), { + FacingCardinal=North, + }, + cake => BlockBehavior::default(), { + CakeBites=_0, + }, + repeater => BlockBehavior::default(), { + RepeaterDelay=_1, + FacingCardinal=North, + Locked=False, + Powered=False, + }, + white_stained_glass => BlockBehavior::default(), { + }, + orange_stained_glass => BlockBehavior::default(), { + }, + magenta_stained_glass => BlockBehavior::default(), { + }, + light_blue_stained_glass => BlockBehavior::default(), { + }, + yellow_stained_glass => BlockBehavior::default(), { + }, + lime_stained_glass => BlockBehavior::default(), { + }, + pink_stained_glass => BlockBehavior::default(), { + }, + gray_stained_glass => BlockBehavior::default(), { + }, + light_gray_stained_glass => BlockBehavior::default(), { + }, + cyan_stained_glass => BlockBehavior::default(), { + }, + purple_stained_glass => BlockBehavior::default(), { + }, + blue_stained_glass => BlockBehavior::default(), { + }, + brown_stained_glass => BlockBehavior::default(), { + }, + green_stained_glass => BlockBehavior::default(), { + }, + red_stained_glass => BlockBehavior::default(), { + }, + black_stained_glass => BlockBehavior::default(), { + }, + oak_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + spruce_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + birch_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + jungle_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + acacia_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + dark_oak_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + mangrove_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + stone_bricks => BlockBehavior::default(), { + }, + mossy_stone_bricks => BlockBehavior::default(), { + }, + cracked_stone_bricks => BlockBehavior::default(), { + }, + chiseled_stone_bricks => BlockBehavior::default(), { + }, + packed_mud => BlockBehavior::default(), { + }, + mud_bricks => BlockBehavior::default(), { + }, + infested_stone => BlockBehavior::default(), { + }, + infested_cobblestone => BlockBehavior::default(), { + }, + infested_stone_bricks => BlockBehavior::default(), { + }, + infested_mossy_stone_bricks => BlockBehavior::default(), { + }, + infested_cracked_stone_bricks => BlockBehavior::default(), { + }, + infested_chiseled_stone_bricks => BlockBehavior::default(), { + }, + brown_mushroom_block => BlockBehavior::default(), { + Down=True, + East=True, + North=True, + South=True, + Up=True, + West=True, + }, + red_mushroom_block => BlockBehavior::default(), { + Down=True, + East=True, + North=True, + South=True, + Up=True, + West=True, + }, + mushroom_stem => BlockBehavior::default(), { + Down=True, + East=True, + North=True, + South=True, + Up=True, + West=True, + }, + iron_bars => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + chain => BlockBehavior::default(), { + Axis=Y, + Waterlogged=False, + }, + glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + melon => BlockBehavior::default(), { + }, + attached_pumpkin_stem => BlockBehavior::default(), { + FacingCardinal=North, + }, + attached_melon_stem => BlockBehavior::default(), { + FacingCardinal=North, + }, + pumpkin_stem => BlockBehavior::default(), { + PumpkinStemAge=_0, + }, + melon_stem => BlockBehavior::default(), { + MelonStemAge=_0, + }, + vine => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Up=False, + West=False, + }, + glow_lichen => BlockBehavior::default(), { + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + }, + oak_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + stone_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + mud_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + mycelium => BlockBehavior::default(), { + Snowy=False, + }, + lily_pad => BlockBehavior::default(), { + }, + nether_bricks => BlockBehavior::default(), { + }, + nether_brick_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + nether_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + nether_wart => BlockBehavior::default(), { + NetherWartAge=_0, + }, + enchanting_table => BlockBehavior::default(), { + }, + brewing_stand => BlockBehavior::default(), { + HasBottle=False, + HasBottle=False, + HasBottle=False, + }, + cauldron => BlockBehavior::default(), { + }, + water_cauldron => BlockBehavior::default(), { + WaterCauldronLevel=_1, + }, + lava_cauldron => BlockBehavior::default(), { + }, + powder_snow_cauldron => BlockBehavior::default(), { + PowderSnowCauldronLevel=_1, + }, + end_portal => BlockBehavior::default(), { + }, + end_portal_frame => BlockBehavior::default(), { + HasEye=False, + FacingCardinal=North, + }, + end_stone => BlockBehavior::default(), { + }, + dragon_egg => BlockBehavior::default(), { + }, + redstone_lamp => BlockBehavior::default(), { + Lit=False, + }, + cocoa => BlockBehavior::default(), { + CocoaAge=_0, + FacingCardinal=North, + }, + sandstone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + emerald_ore => BlockBehavior::default(), { + }, + deepslate_emerald_ore => BlockBehavior::default(), { + }, + ender_chest => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + tripwire_hook => BlockBehavior::default(), { + Attached=False, + FacingCardinal=North, + Powered=False, + }, + tripwire => BlockBehavior::default(), { + Attached=False, + Disarmed=False, + East=False, + North=False, + Powered=False, + South=False, + West=False, + }, + emerald_block => BlockBehavior::default(), { + }, + spruce_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + birch_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + jungle_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + command_block => BlockBehavior::default(), { + Conditional=False, + FacingCubic=North, + }, + beacon => BlockBehavior::default(), { + }, + cobblestone_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + mossy_cobblestone_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + flower_pot => BlockBehavior::default(), { + }, + potted_oak_sapling => BlockBehavior::default(), { + }, + potted_spruce_sapling => BlockBehavior::default(), { + }, + potted_birch_sapling => BlockBehavior::default(), { + }, + potted_jungle_sapling => BlockBehavior::default(), { + }, + potted_acacia_sapling => BlockBehavior::default(), { + }, + potted_dark_oak_sapling => BlockBehavior::default(), { + }, + potted_mangrove_propagule => BlockBehavior::default(), { + }, + potted_fern => BlockBehavior::default(), { + }, + potted_dandelion => BlockBehavior::default(), { + }, + potted_poppy => BlockBehavior::default(), { + }, + potted_blue_orchid => BlockBehavior::default(), { + }, + potted_allium => BlockBehavior::default(), { + }, + potted_azure_bluet => BlockBehavior::default(), { + }, + potted_red_tulip => BlockBehavior::default(), { + }, + potted_orange_tulip => BlockBehavior::default(), { + }, + potted_white_tulip => BlockBehavior::default(), { + }, + potted_pink_tulip => BlockBehavior::default(), { + }, + potted_oxeye_daisy => BlockBehavior::default(), { + }, + potted_cornflower => BlockBehavior::default(), { + }, + potted_lily_of_the_valley => BlockBehavior::default(), { + }, + potted_wither_rose => BlockBehavior::default(), { + }, + potted_red_mushroom => BlockBehavior::default(), { + }, + potted_brown_mushroom => BlockBehavior::default(), { + }, + potted_dead_bush => BlockBehavior::default(), { + }, + potted_cactus => BlockBehavior::default(), { + }, + carrots => BlockBehavior::default(), { + CarrotsAge=_0, + }, + potatoes => BlockBehavior::default(), { + PotatoesAge=_0, + }, + oak_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + spruce_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + birch_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + jungle_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + acacia_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + dark_oak_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + mangrove_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + skeleton_skull => BlockBehavior::default(), { + SkeletonSkullRotation=_0, + }, + skeleton_wall_skull => BlockBehavior::default(), { + FacingCardinal=North, + }, + wither_skeleton_skull => BlockBehavior::default(), { + WitherSkeletonSkullRotation=_0, + }, + wither_skeleton_wall_skull => BlockBehavior::default(), { + FacingCardinal=North, + }, + zombie_head => BlockBehavior::default(), { + ZombieHeadRotation=_0, + }, + zombie_wall_head => BlockBehavior::default(), { + FacingCardinal=North, + }, + player_head => BlockBehavior::default(), { + PlayerHeadRotation=_0, + }, + player_wall_head => BlockBehavior::default(), { + FacingCardinal=North, + }, + creeper_head => BlockBehavior::default(), { + CreeperHeadRotation=_0, + }, + creeper_wall_head => BlockBehavior::default(), { + FacingCardinal=North, + }, + dragon_head => BlockBehavior::default(), { + DragonHeadRotation=_0, + }, + dragon_wall_head => BlockBehavior::default(), { + FacingCardinal=North, + }, + anvil => BlockBehavior::default(), { + FacingCardinal=North, + }, + chipped_anvil => BlockBehavior::default(), { + FacingCardinal=North, + }, + damaged_anvil => BlockBehavior::default(), { + FacingCardinal=North, + }, + trapped_chest => BlockBehavior::default(), { + ChestType=Single, + FacingCardinal=North, + Waterlogged=False, + }, + light_weighted_pressure_plate => BlockBehavior::default(), { + LightWeightedPressurePlatePower=_0, + }, + heavy_weighted_pressure_plate => BlockBehavior::default(), { + HeavyWeightedPressurePlatePower=_0, + }, + comparator => BlockBehavior::default(), { + FacingCardinal=North, + ComparatorType=Compare, + Powered=False, + }, + daylight_detector => BlockBehavior::default(), { + Inverted=False, + DaylightDetectorPower=_0, + }, + redstone_block => BlockBehavior::default(), { + }, + nether_quartz_ore => BlockBehavior::default(), { + }, + hopper => BlockBehavior::default(), { + Enabled=True, + Facing=Down, + }, + quartz_block => BlockBehavior::default(), { + }, + chiseled_quartz_block => BlockBehavior::default(), { + }, + quartz_pillar => BlockBehavior::default(), { + Axis=Y, + }, + quartz_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + activator_rail => BlockBehavior::default(), { + Powered=False, + RailShape=NorthSouth, + Waterlogged=False, + }, + dropper => BlockBehavior::default(), { + FacingCubic=North, + Triggered=False, + }, + white_terracotta => BlockBehavior::default(), { + }, + orange_terracotta => BlockBehavior::default(), { + }, + magenta_terracotta => BlockBehavior::default(), { + }, + light_blue_terracotta => BlockBehavior::default(), { + }, + yellow_terracotta => BlockBehavior::default(), { + }, + lime_terracotta => BlockBehavior::default(), { + }, + pink_terracotta => BlockBehavior::default(), { + }, + gray_terracotta => BlockBehavior::default(), { + }, + light_gray_terracotta => BlockBehavior::default(), { + }, + cyan_terracotta => BlockBehavior::default(), { + }, + purple_terracotta => BlockBehavior::default(), { + }, + blue_terracotta => BlockBehavior::default(), { + }, + brown_terracotta => BlockBehavior::default(), { + }, + green_terracotta => BlockBehavior::default(), { + }, + red_terracotta => BlockBehavior::default(), { + }, + black_terracotta => BlockBehavior::default(), { + }, + white_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + orange_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + magenta_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + light_blue_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + yellow_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + lime_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + pink_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + gray_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + light_gray_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + cyan_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + purple_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + blue_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + brown_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + green_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + red_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + black_stained_glass_pane => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + acacia_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + dark_oak_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + mangrove_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + slime_block => BlockBehavior::default(), { + }, + barrier => BlockBehavior::default(), { + }, + light => BlockBehavior::default(), { + LightLevel=_15, + Waterlogged=False, + }, + iron_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + prismarine => BlockBehavior::default(), { + }, + prismarine_bricks => BlockBehavior::default(), { + }, + dark_prismarine => BlockBehavior::default(), { + }, + prismarine_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + prismarine_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + dark_prismarine_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + prismarine_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + prismarine_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + dark_prismarine_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + sea_lantern => BlockBehavior::default(), { + }, + hay_block => BlockBehavior::default(), { + Axis=Y, + }, + white_carpet => BlockBehavior::default(), { + }, + orange_carpet => BlockBehavior::default(), { + }, + magenta_carpet => BlockBehavior::default(), { + }, + light_blue_carpet => BlockBehavior::default(), { + }, + yellow_carpet => BlockBehavior::default(), { + }, + lime_carpet => BlockBehavior::default(), { + }, + pink_carpet => BlockBehavior::default(), { + }, + gray_carpet => BlockBehavior::default(), { + }, + light_gray_carpet => BlockBehavior::default(), { + }, + cyan_carpet => BlockBehavior::default(), { + }, + purple_carpet => BlockBehavior::default(), { + }, + blue_carpet => BlockBehavior::default(), { + }, + brown_carpet => BlockBehavior::default(), { + }, + green_carpet => BlockBehavior::default(), { + }, + red_carpet => BlockBehavior::default(), { + }, + black_carpet => BlockBehavior::default(), { + }, + terracotta => BlockBehavior::default(), { + }, + coal_block => BlockBehavior::default(), { + }, + packed_ice => BlockBehavior::default(), { + }, + sunflower => BlockBehavior::default(), { + Half=Lower, + }, + lilac => BlockBehavior::default(), { + Half=Lower, + }, + rose_bush => BlockBehavior::default(), { + Half=Lower, + }, + peony => BlockBehavior::default(), { + Half=Lower, + }, + tall_grass => BlockBehavior::default(), { + Half=Lower, + }, + large_fern => BlockBehavior::default(), { + Half=Lower, + }, + white_banner => BlockBehavior::default(), { + WhiteBannerRotation=_0, + }, + orange_banner => BlockBehavior::default(), { + OrangeBannerRotation=_0, + }, + magenta_banner => BlockBehavior::default(), { + MagentaBannerRotation=_0, + }, + light_blue_banner => BlockBehavior::default(), { + LightBlueBannerRotation=_0, + }, + yellow_banner => BlockBehavior::default(), { + YellowBannerRotation=_0, + }, + lime_banner => BlockBehavior::default(), { + LimeBannerRotation=_0, + }, + pink_banner => BlockBehavior::default(), { + PinkBannerRotation=_0, + }, + gray_banner => BlockBehavior::default(), { + GrayBannerRotation=_0, + }, + light_gray_banner => BlockBehavior::default(), { + LightGrayBannerRotation=_0, + }, + cyan_banner => BlockBehavior::default(), { + CyanBannerRotation=_0, + }, + purple_banner => BlockBehavior::default(), { + PurpleBannerRotation=_0, + }, + blue_banner => BlockBehavior::default(), { + BlueBannerRotation=_0, + }, + brown_banner => BlockBehavior::default(), { + BrownBannerRotation=_0, + }, + green_banner => BlockBehavior::default(), { + GreenBannerRotation=_0, + }, + red_banner => BlockBehavior::default(), { + RedBannerRotation=_0, + }, + black_banner => BlockBehavior::default(), { + BlackBannerRotation=_0, + }, + white_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + orange_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + magenta_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + light_blue_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + yellow_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + lime_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + pink_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + gray_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + light_gray_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + cyan_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + purple_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + blue_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + brown_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + green_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + red_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + black_wall_banner => BlockBehavior::default(), { + FacingCardinal=North, + }, + red_sandstone => BlockBehavior::default(), { + }, + chiseled_red_sandstone => BlockBehavior::default(), { + }, + cut_red_sandstone => BlockBehavior::default(), { + }, + red_sandstone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + oak_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + spruce_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + birch_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + jungle_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + acacia_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + dark_oak_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + mangrove_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + stone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + smooth_stone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + sandstone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + cut_sandstone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + petrified_oak_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + cobblestone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + stone_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + mud_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + nether_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + quartz_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + red_sandstone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + cut_red_sandstone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + purpur_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + smooth_stone => BlockBehavior::default(), { + }, + smooth_sandstone => BlockBehavior::default(), { + }, + smooth_quartz => BlockBehavior::default(), { + }, + smooth_red_sandstone => BlockBehavior::default(), { + }, + spruce_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + birch_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + jungle_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + acacia_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + dark_oak_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + mangrove_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + spruce_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + birch_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + jungle_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + acacia_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + dark_oak_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + mangrove_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + spruce_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + birch_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + jungle_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + acacia_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + dark_oak_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + mangrove_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + end_rod => BlockBehavior::default(), { + FacingCubic=Up, + }, + chorus_plant => BlockBehavior::default(), { + Down=False, + East=False, + North=False, + South=False, + Up=False, + West=False, + }, + chorus_flower => BlockBehavior::default(), { + ChorusFlowerAge=_0, + }, + purpur_block => BlockBehavior::default(), { + }, + purpur_pillar => BlockBehavior::default(), { + Axis=Y, + }, + purpur_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + end_stone_bricks => BlockBehavior::default(), { + }, + beetroots => BlockBehavior::default(), { + BeetrootsAge=_0, + }, + dirt_path => BlockBehavior::default(), { + }, + end_gateway => BlockBehavior::default(), { + }, + repeating_command_block => BlockBehavior::default(), { + Conditional=False, + FacingCubic=North, + }, + chain_command_block => BlockBehavior::default(), { + Conditional=False, + FacingCubic=North, + }, + frosted_ice => BlockBehavior::default(), { + FrostedIceAge=_0, + }, + magma_block => BlockBehavior::default(), { + }, + nether_wart_block => BlockBehavior::default(), { + }, + red_nether_bricks => BlockBehavior::default(), { + }, + bone_block => BlockBehavior::default(), { + Axis=Y, + }, + structure_void => BlockBehavior::default(), { + }, + observer => BlockBehavior::default(), { + FacingCubic=South, + Powered=False, + }, + shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + white_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + orange_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + magenta_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + light_blue_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + yellow_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + lime_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + pink_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + gray_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + light_gray_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + cyan_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + purple_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + blue_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + brown_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + green_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + red_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + black_shulker_box => BlockBehavior::default(), { + FacingCubic=Up, + }, + white_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + orange_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + magenta_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + light_blue_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + yellow_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + lime_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + pink_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + gray_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + light_gray_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + cyan_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + purple_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + blue_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + brown_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + green_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + red_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + black_glazed_terracotta => BlockBehavior::default(), { + FacingCardinal=North, + }, + white_concrete => BlockBehavior::default(), { + }, + orange_concrete => BlockBehavior::default(), { + }, + magenta_concrete => BlockBehavior::default(), { + }, + light_blue_concrete => BlockBehavior::default(), { + }, + yellow_concrete => BlockBehavior::default(), { + }, + lime_concrete => BlockBehavior::default(), { + }, + pink_concrete => BlockBehavior::default(), { + }, + gray_concrete => BlockBehavior::default(), { + }, + light_gray_concrete => BlockBehavior::default(), { + }, + cyan_concrete => BlockBehavior::default(), { + }, + purple_concrete => BlockBehavior::default(), { + }, + blue_concrete => BlockBehavior::default(), { + }, + brown_concrete => BlockBehavior::default(), { + }, + green_concrete => BlockBehavior::default(), { + }, + red_concrete => BlockBehavior::default(), { + }, + black_concrete => BlockBehavior::default(), { + }, + white_concrete_powder => BlockBehavior::default(), { + }, + orange_concrete_powder => BlockBehavior::default(), { + }, + magenta_concrete_powder => BlockBehavior::default(), { + }, + light_blue_concrete_powder => BlockBehavior::default(), { + }, + yellow_concrete_powder => BlockBehavior::default(), { + }, + lime_concrete_powder => BlockBehavior::default(), { + }, + pink_concrete_powder => BlockBehavior::default(), { + }, + gray_concrete_powder => BlockBehavior::default(), { + }, + light_gray_concrete_powder => BlockBehavior::default(), { + }, + cyan_concrete_powder => BlockBehavior::default(), { + }, + purple_concrete_powder => BlockBehavior::default(), { + }, + blue_concrete_powder => BlockBehavior::default(), { + }, + brown_concrete_powder => BlockBehavior::default(), { + }, + green_concrete_powder => BlockBehavior::default(), { + }, + red_concrete_powder => BlockBehavior::default(), { + }, + black_concrete_powder => BlockBehavior::default(), { + }, + kelp => BlockBehavior::default(), { + KelpAge=_0, + }, + kelp_plant => BlockBehavior::default(), { + }, + dried_kelp_block => BlockBehavior::default(), { + }, + turtle_egg => BlockBehavior::default(), { + TurtleEggEggs=_1, + TurtleEggHatch=_0, + }, + dead_tube_coral_block => BlockBehavior::default(), { + }, + dead_brain_coral_block => BlockBehavior::default(), { + }, + dead_bubble_coral_block => BlockBehavior::default(), { + }, + dead_fire_coral_block => BlockBehavior::default(), { + }, + dead_horn_coral_block => BlockBehavior::default(), { + }, + tube_coral_block => BlockBehavior::default(), { + }, + brain_coral_block => BlockBehavior::default(), { + }, + bubble_coral_block => BlockBehavior::default(), { + }, + fire_coral_block => BlockBehavior::default(), { + }, + horn_coral_block => BlockBehavior::default(), { + }, + dead_tube_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_brain_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_bubble_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_fire_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_horn_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + tube_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + brain_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + bubble_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + fire_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + horn_coral => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_tube_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_brain_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_bubble_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_fire_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_horn_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + tube_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + brain_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + bubble_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + fire_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + horn_coral_fan => BlockBehavior::default(), { + Waterlogged=True, + }, + dead_tube_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + dead_brain_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + dead_bubble_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + dead_fire_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + dead_horn_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + tube_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + brain_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + bubble_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + fire_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + horn_coral_wall_fan => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=True, + }, + sea_pickle => BlockBehavior::default(), { + SeaPicklePickles=_1, + Waterlogged=True, + }, + blue_ice => BlockBehavior::default(), { + }, + conduit => BlockBehavior::default(), { + Waterlogged=True, + }, + bamboo_sapling => BlockBehavior::default(), { + }, + bamboo => BlockBehavior::default(), { + BambooAge=_0, + Leaves=None, + BambooStage=_0, + }, + potted_bamboo => BlockBehavior::default(), { + }, + void_air => BlockBehavior::default(), { + }, + cave_air => BlockBehavior::default(), { + }, + bubble_column => BlockBehavior::default(), { + DragDown=True, + }, + polished_granite_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + smooth_red_sandstone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + mossy_stone_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + polished_diorite_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + mossy_cobblestone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + end_stone_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + stone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + smooth_sandstone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + smooth_quartz_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + granite_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + andesite_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + red_nether_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + polished_andesite_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + diorite_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + polished_granite_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + smooth_red_sandstone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + mossy_stone_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + polished_diorite_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + mossy_cobblestone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + end_stone_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + smooth_sandstone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + smooth_quartz_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + granite_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + andesite_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + red_nether_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + polished_andesite_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + diorite_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + prismarine_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + red_sandstone_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + mossy_stone_brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + granite_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + stone_brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + mud_brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + nether_brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + andesite_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + red_nether_brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + sandstone_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + end_stone_brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + diorite_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + scaffolding => BlockBehavior::default(), { + Bottom=False, + ScaffoldingDistance=_7, + Waterlogged=False, + }, + loom => BlockBehavior::default(), { + FacingCardinal=North, + }, + barrel => BlockBehavior::default(), { + FacingCubic=North, + Open=False, + }, + smoker => BlockBehavior::default(), { + FacingCardinal=North, + Lit=False, + }, + blast_furnace => BlockBehavior::default(), { + FacingCardinal=North, + Lit=False, + }, + cartography_table => BlockBehavior::default(), { + }, + fletching_table => BlockBehavior::default(), { + }, + grindstone => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + }, + lectern => BlockBehavior::default(), { + FacingCardinal=North, + HasBook=False, + Powered=False, + }, + smithing_table => BlockBehavior::default(), { + }, + stonecutter => BlockBehavior::default(), { + FacingCardinal=North, + }, + bell => BlockBehavior::default(), { + Attachment=Floor, + FacingCardinal=North, + Powered=False, + }, + lantern => BlockBehavior::default(), { + Hanging=False, + Waterlogged=False, + }, + soul_lantern => BlockBehavior::default(), { + Hanging=False, + Waterlogged=False, + }, + campfire => BlockBehavior::default(), { + FacingCardinal=North, + Lit=True, + SignalFire=False, + Waterlogged=False, + }, + soul_campfire => BlockBehavior::default(), { + FacingCardinal=North, + Lit=True, + SignalFire=False, + Waterlogged=False, + }, + sweet_berry_bush => BlockBehavior::default(), { + SweetBerryBushAge=_0, + }, + warped_stem => BlockBehavior::default(), { + Axis=Y, + }, + stripped_warped_stem => BlockBehavior::default(), { + Axis=Y, + }, + warped_hyphae => BlockBehavior::default(), { + Axis=Y, + }, + stripped_warped_hyphae => BlockBehavior::default(), { + Axis=Y, + }, + warped_nylium => BlockBehavior::default(), { + }, + warped_fungus => BlockBehavior::default(), { + }, + warped_wart_block => BlockBehavior::default(), { + }, + warped_roots => BlockBehavior::default(), { + }, + nether_sprouts => BlockBehavior::default(), { + }, + crimson_stem => BlockBehavior::default(), { + Axis=Y, + }, + stripped_crimson_stem => BlockBehavior::default(), { + Axis=Y, + }, + crimson_hyphae => BlockBehavior::default(), { + Axis=Y, + }, + stripped_crimson_hyphae => BlockBehavior::default(), { + Axis=Y, + }, + crimson_nylium => BlockBehavior::default(), { + }, + crimson_fungus => BlockBehavior::default(), { + }, + shroomlight => BlockBehavior::default(), { + }, + weeping_vines => BlockBehavior::default(), { + WeepingVinesAge=_0, + }, + weeping_vines_plant => BlockBehavior::default(), { + }, + twisting_vines => BlockBehavior::default(), { + TwistingVinesAge=_0, + }, + twisting_vines_plant => BlockBehavior::default(), { + }, + crimson_roots => BlockBehavior::default(), { + }, + crimson_planks => BlockBehavior::default(), { + }, + warped_planks => BlockBehavior::default(), { + }, + crimson_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + warped_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + crimson_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + warped_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + crimson_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + warped_fence => BlockBehavior::default(), { + East=False, + North=False, + South=False, + Waterlogged=False, + West=False, + }, + crimson_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + warped_trapdoor => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + Open=False, + Powered=False, + Waterlogged=False, + }, + crimson_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + warped_fence_gate => BlockBehavior::default(), { + FacingCardinal=North, + InWall=False, + Open=False, + Powered=False, + }, + crimson_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + warped_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + crimson_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + warped_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + crimson_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + warped_door => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Hinge=Left, + Open=False, + Powered=False, + }, + crimson_sign => BlockBehavior::default(), { + CrimsonSignRotation=_0, + Waterlogged=False, + }, + warped_sign => BlockBehavior::default(), { + WarpedSignRotation=_0, + Waterlogged=False, + }, + crimson_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + warped_wall_sign => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + structure_block => BlockBehavior::default(), { + Mode=Load, + }, + jigsaw => BlockBehavior::default(), { + Orientation=NorthUp, + }, + composter => BlockBehavior::default(), { + ComposterLevel=_0, + }, + target => BlockBehavior::default(), { + TargetOutputPower=_0, + }, + bee_nest => BlockBehavior::default(), { + FacingCardinal=North, + BeeNestHoneyLevel=_0, + }, + beehive => BlockBehavior::default(), { + FacingCardinal=North, + BeehiveHoneyLevel=_0, + }, + honey_block => BlockBehavior::default(), { + }, + honeycomb_block => BlockBehavior::default(), { + }, + netherite_block => BlockBehavior::default(), { + }, + ancient_debris => BlockBehavior::default(), { + }, + crying_obsidian => BlockBehavior::default(), { + }, + respawn_anchor => BlockBehavior::default(), { + RespawnAnchorCharge=_0, + }, + potted_crimson_fungus => BlockBehavior::default(), { + }, + potted_warped_fungus => BlockBehavior::default(), { + }, + potted_crimson_roots => BlockBehavior::default(), { + }, + potted_warped_roots => BlockBehavior::default(), { + }, + lodestone => BlockBehavior::default(), { + }, + blackstone => BlockBehavior::default(), { + }, + blackstone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + blackstone_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + blackstone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + polished_blackstone => BlockBehavior::default(), { + }, + polished_blackstone_bricks => BlockBehavior::default(), { + }, + cracked_polished_blackstone_bricks => BlockBehavior::default(), { + }, + chiseled_polished_blackstone => BlockBehavior::default(), { + }, + polished_blackstone_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + polished_blackstone_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + polished_blackstone_brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + gilded_blackstone => BlockBehavior::default(), { + }, + polished_blackstone_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + polished_blackstone_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + polished_blackstone_pressure_plate => BlockBehavior::default(), { + Powered=False, + }, + polished_blackstone_button => BlockBehavior::default(), { + Face=Wall, + FacingCardinal=North, + Powered=False, + }, + polished_blackstone_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + chiseled_nether_bricks => BlockBehavior::default(), { + }, + cracked_nether_bricks => BlockBehavior::default(), { + }, + quartz_bricks => BlockBehavior::default(), { + }, + candle => BlockBehavior::default(), { + CandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + white_candle => BlockBehavior::default(), { + WhiteCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + orange_candle => BlockBehavior::default(), { + OrangeCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + magenta_candle => BlockBehavior::default(), { + MagentaCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + light_blue_candle => BlockBehavior::default(), { + LightBlueCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + yellow_candle => BlockBehavior::default(), { + YellowCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + lime_candle => BlockBehavior::default(), { + LimeCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + pink_candle => BlockBehavior::default(), { + PinkCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + gray_candle => BlockBehavior::default(), { + GrayCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + light_gray_candle => BlockBehavior::default(), { + LightGrayCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + cyan_candle => BlockBehavior::default(), { + CyanCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + purple_candle => BlockBehavior::default(), { + PurpleCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + blue_candle => BlockBehavior::default(), { + BlueCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + brown_candle => BlockBehavior::default(), { + BrownCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + green_candle => BlockBehavior::default(), { + GreenCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + red_candle => BlockBehavior::default(), { + RedCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + black_candle => BlockBehavior::default(), { + BlackCandleCandles=_1, + Lit=False, + Waterlogged=False, + }, + candle_cake => BlockBehavior::default(), { + Lit=False, + }, + white_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + orange_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + magenta_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + light_blue_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + yellow_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + lime_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + pink_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + gray_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + light_gray_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + cyan_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + purple_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + blue_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + brown_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + green_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + red_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + black_candle_cake => BlockBehavior::default(), { + Lit=False, + }, + amethyst_block => BlockBehavior::default(), { + }, + budding_amethyst => BlockBehavior::default(), { + }, + amethyst_cluster => BlockBehavior::default(), { + FacingCubic=Up, + Waterlogged=False, + }, + large_amethyst_bud => BlockBehavior::default(), { + FacingCubic=Up, + Waterlogged=False, + }, + medium_amethyst_bud => BlockBehavior::default(), { + FacingCubic=Up, + Waterlogged=False, + }, + small_amethyst_bud => BlockBehavior::default(), { + FacingCubic=Up, + Waterlogged=False, + }, + tuff => BlockBehavior::default(), { + }, + calcite => BlockBehavior::default(), { + }, + tinted_glass => BlockBehavior::default(), { + }, + powder_snow => BlockBehavior::default(), { + }, + sculk_sensor => BlockBehavior::default(), { + SculkSensorPower=_0, + Phase=Inactive, + Waterlogged=False, + }, + sculk => BlockBehavior::default(), { + }, + sculk_vein => BlockBehavior::default(), { + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + TrueFalse=False, + }, + sculk_catalyst => BlockBehavior::default(), { + Pulse=False, + }, + sculk_shrieker => BlockBehavior::default(), { + CanSummon=False, + Shrieking=False, + Waterlogged=False, + }, + oxidized_copper => BlockBehavior::default(), { + }, + weathered_copper => BlockBehavior::default(), { + }, + exposed_copper => BlockBehavior::default(), { + }, + copper_block => BlockBehavior::default(), { + }, + copper_ore => BlockBehavior::default(), { + }, + deepslate_copper_ore => BlockBehavior::default(), { + }, + oxidized_cut_copper => BlockBehavior::default(), { + }, + weathered_cut_copper => BlockBehavior::default(), { + }, + exposed_cut_copper => BlockBehavior::default(), { + }, + cut_copper => BlockBehavior::default(), { + }, + oxidized_cut_copper_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + weathered_cut_copper_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + exposed_cut_copper_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + cut_copper_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + oxidized_cut_copper_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + weathered_cut_copper_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + exposed_cut_copper_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + cut_copper_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + waxed_copper_block => BlockBehavior::default(), { + }, + waxed_weathered_copper => BlockBehavior::default(), { + }, + waxed_exposed_copper => BlockBehavior::default(), { + }, + waxed_oxidized_copper => BlockBehavior::default(), { + }, + waxed_oxidized_cut_copper => BlockBehavior::default(), { + }, + waxed_weathered_cut_copper => BlockBehavior::default(), { + }, + waxed_exposed_cut_copper => BlockBehavior::default(), { + }, + waxed_cut_copper => BlockBehavior::default(), { + }, + waxed_oxidized_cut_copper_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + waxed_weathered_cut_copper_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + waxed_exposed_cut_copper_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + waxed_cut_copper_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + waxed_oxidized_cut_copper_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + waxed_weathered_cut_copper_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + waxed_exposed_cut_copper_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + waxed_cut_copper_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + lightning_rod => BlockBehavior::default(), { + FacingCubic=Up, + Powered=False, + Waterlogged=False, + }, + pointed_dripstone => BlockBehavior::default(), { + Thickness=Tip, + TipDirection=Up, + Waterlogged=False, + }, + dripstone_block => BlockBehavior::default(), { + }, + cave_vines => BlockBehavior::default(), { + _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25=_0, + TrueFalse=False, + }, + cave_vines_plant => BlockBehavior::default(), { + TrueFalse=False, + }, + spore_blossom => BlockBehavior::default(), { + }, + azalea => BlockBehavior::default(), { + }, + flowering_azalea => BlockBehavior::default(), { + }, + moss_carpet => BlockBehavior::default(), { + }, + moss_block => BlockBehavior::default(), { + }, + big_dripleaf => BlockBehavior::default(), { + FacingCardinal=North, + Tilt=None, + Waterlogged=False, + }, + big_dripleaf_stem => BlockBehavior::default(), { + FacingCardinal=North, + Waterlogged=False, + }, + small_dripleaf => BlockBehavior::default(), { + FacingCardinal=North, + Half=Lower, + Waterlogged=False, + }, + hanging_roots => BlockBehavior::default(), { + Waterlogged=False, + }, + rooted_dirt => BlockBehavior::default(), { + }, + mud => BlockBehavior::default(), { + }, + deepslate => BlockBehavior::default(), { + Axis=Y, + }, + cobbled_deepslate => BlockBehavior::default(), { + }, + cobbled_deepslate_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + cobbled_deepslate_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + cobbled_deepslate_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + polished_deepslate => BlockBehavior::default(), { + }, + polished_deepslate_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + polished_deepslate_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + polished_deepslate_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + deepslate_tiles => BlockBehavior::default(), { + }, + deepslate_tile_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + deepslate_tile_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + deepslate_tile_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + deepslate_bricks => BlockBehavior::default(), { + }, + deepslate_brick_stairs => BlockBehavior::default(), { + FacingCardinal=North, + TopBottom=Bottom, + StairShape=Straight, + Waterlogged=False, + }, + deepslate_brick_slab => BlockBehavior::default(), { + Type=Bottom, + Waterlogged=False, + }, + deepslate_brick_wall => BlockBehavior::default(), { + EastWall=None, + NorthWall=None, + SouthWall=None, + Up=True, + Waterlogged=False, + WestWall=None, + }, + chiseled_deepslate => BlockBehavior::default(), { + }, + cracked_deepslate_bricks => BlockBehavior::default(), { + }, + cracked_deepslate_tiles => BlockBehavior::default(), { + }, + infested_deepslate => BlockBehavior::default(), { + XYZ=Y, + }, + smooth_basalt => BlockBehavior::default(), { + }, + raw_iron_block => BlockBehavior::default(), { + }, + raw_copper_block => BlockBehavior::default(), { + }, + raw_gold_block => BlockBehavior::default(), { + }, + potted_azalea_bush => BlockBehavior::default(), { + }, + potted_flowering_azalea_bush => BlockBehavior::default(), { + }, + ochre_froglight => BlockBehavior::default(), { + Axis=Y, + }, + verdant_froglight => BlockBehavior::default(), { + Axis=Y, + }, + pearlescent_froglight => BlockBehavior::default(), { + Axis=Y, + }, + frogspawn => BlockBehavior::default(), { + }, + reinforced_deepslate => BlockBehavior::default(), { + }, + } +} diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs new file mode 100644 index 00000000..a6de1e92 --- /dev/null +++ b/azalea-block/src/lib.rs @@ -0,0 +1,47 @@ +mod behavior; +mod blocks; + +pub use behavior::BlockBehavior; +pub use blocks::*; + +use std::mem; + +impl BlockState { + /// Transmutes a u32 to a block state. UB if the value is not a valid block + /// state. + #[inline] + pub unsafe fn from_u32_unsafe(state_id: u32) -> Self { + mem::transmute::(state_id) + } + + #[inline] + pub fn is_valid_state(state_id: u32) -> bool { + state_id <= Self::max_state() + } +} + +impl TryFrom for BlockState { + type Error = (); + + /// Safely converts a state id to a block state. + fn try_from(state_id: u32) -> Result { + if Self::is_valid_state(state_id) { + Ok(unsafe { Self::from_u32_unsafe(state_id) }) + } else { + Err(()) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_from_u32() { + assert_eq!(BlockState::try_from(0).unwrap(), BlockState::Air); + + assert!(BlockState::try_from(BlockState::max_state()).is_ok()); + assert!(BlockState::try_from(BlockState::max_state() + 1).is_err()); + } +} diff --git a/azalea-client/src/connect.rs b/azalea-client/src/connect.rs index cb2bec9c..1551ca69 100755 --- a/azalea-client/src/connect.rs +++ b/azalea-client/src/connect.rs @@ -1,5 +1,5 @@ use crate::Player; -use azalea_core::{resource_location::ResourceLocation, ChunkPos}; +use azalea_core::{resource_location::ResourceLocation, ChunkPos, EntityPos}; use azalea_protocol::{ connect::{GameConnection, HandshakeConnection}, packets::{ @@ -351,6 +351,11 @@ impl Client { } GamePacket::ClientboundAddEntityPacket(p) => { println!("Got add entity packet {:?}", p); + let pos = EntityPos { + x: p.x, + y: p.y, + z: p.z, + }; } GamePacket::ClientboundSetEntityDataPacket(p) => { // println!("Got set entity data packet {:?}", p); @@ -447,6 +452,9 @@ impl Client { GamePacket::ClientboundServerDataPacket(p) => { println!("Got server data packet {:?}", p); } + GamePacket::ClientboundSetEquipmentPacket(p) => { + println!("Got set equipment packet {:?}", p); + } _ => panic!("Unexpected packet {:?}", packet), } } diff --git a/azalea-client/src/entity.rs b/azalea-client/src/entity.rs index ed8aa68d..d91f556f 100644 --- a/azalea-client/src/entity.rs +++ b/azalea-client/src/entity.rs @@ -1,5 +1,8 @@ -#[derive(Default)] +use azalea_core::EntityPos; + +#[derive(Default, Debug)] pub struct Entity { /// The incremental numerical id of the entity. pub id: u32, + pub pos: EntityPos, } diff --git a/azalea-client/src/player.rs b/azalea-client/src/player.rs index fc54ff93..04d34f6d 100644 --- a/azalea-client/src/player.rs +++ b/azalea-client/src/player.rs @@ -1,6 +1,6 @@ use crate::Entity; -#[derive(Default)] +#[derive(Default, Debug)] pub struct Player { /// The entity attached to the player. There's some useful fields here. pub entity: Entity, diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs index cdb32ea9..a2632871 100755 --- a/azalea-core/src/lib.rs +++ b/azalea-core/src/lib.rs @@ -11,9 +11,7 @@ mod slot; pub use slot::{Slot, SlotData}; mod position; -pub use position::{ - BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos, GlobalPos, -}; +pub use position::*; mod direction; pub use direction::Direction; diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index d5c97eab..24be5f6a 100644 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -147,6 +147,23 @@ pub struct GlobalPos { pub dimension: ResourceLocation, } +#[derive(Debug, Clone, Default)] +pub struct EntityPos { + pub x: f64, + pub y: f64, + pub z: f64, +} + +impl From<&EntityPos> for BlockPos { + fn from(pos: &EntityPos) -> Self { + BlockPos { + x: pos.x as i32, + y: pos.y as i32, + z: pos.z as i32, + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/azalea-protocol/src/packets/game/clientbound_add_entity_packet.rs b/azalea-protocol/src/packets/game/clientbound_add_entity_packet.rs index 8a8a713e..9ef7e05c 100644 --- a/azalea-protocol/src/packets/game/clientbound_add_entity_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_add_entity_packet.rs @@ -3,6 +3,7 @@ use uuid::Uuid; #[derive(Clone, Debug, McBuf, GamePacket)] pub struct ClientboundAddEntityPacket { + /// The id of the entity. #[var] pub id: u32, pub uuid: Uuid, diff --git a/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs new file mode 100644 index 00000000..3acbd58f --- /dev/null +++ b/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs @@ -0,0 +1,74 @@ +use azalea_core::Slot; +use packet_macros::{GamePacket, McBuf}; + +use crate::mc_buf::{McBufReadable, McBufWritable}; + +#[derive(Clone, Debug, McBuf, GamePacket)] +pub struct ClientboundSetEquipmentPacket { + #[var] + pub entity: i32, + pub slots: EquipmentSlots, +} + +#[derive(Clone, Debug)] +pub struct EquipmentSlots { + pub slots: Vec<(EquipmentSlot, Slot)>, +} + +impl McBufReadable for EquipmentSlots { + fn read_into(buf: &mut impl std::io::Read) -> Result { + let mut slots = vec![]; + + loop { + let equipment_byte = u8::read_into(buf)?; + let equipment_slot = EquipmentSlot::from_byte(equipment_byte & 127) + .ok_or_else(|| format!("Invalid equipment slot byte {}", equipment_byte))?; + let item = Slot::read_into(buf)?; + slots.push((equipment_slot, item)); + if equipment_byte & 128 == 0 { + break; + }; + } + + Ok(EquipmentSlots { slots }) + } +} +impl McBufWritable for EquipmentSlots { + fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { + for i in 0..self.slots.len() { + let (equipment_slot, item) = &self.slots[i]; + let mut equipment_byte = *equipment_slot as u8; + if i != self.slots.len() - 1 { + equipment_byte |= 128; + } + equipment_byte.write_into(buf)?; + item.write_into(buf)?; + } + + Ok(()) + } +} + +#[derive(Clone, Debug, Copy, McBuf)] +pub enum EquipmentSlot { + MainHand = 0, + OffHand = 1, + Feet = 2, + Legs = 3, + Chest = 4, + Head = 5, +} + +impl EquipmentSlot { + pub fn from_byte(byte: u8) -> Option { + match byte { + 0 => Some(EquipmentSlot::MainHand), + 1 => Some(EquipmentSlot::OffHand), + 2 => Some(EquipmentSlot::Feet), + 3 => Some(EquipmentSlot::Legs), + 4 => Some(EquipmentSlot::Chest), + 5 => Some(EquipmentSlot::Head), + _ => None, + } + } +} diff --git a/azalea-protocol/src/packets/game/clientbound_sound_packet.rs b/azalea-protocol/src/packets/game/clientbound_sound_packet.rs index 797f03de..fbc5830b 100644 --- a/azalea-protocol/src/packets/game/clientbound_sound_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_sound_packet.rs @@ -3,7 +3,7 @@ use packet_macros::{GamePacket, McBuf}; #[derive(Clone, Debug, McBuf, GamePacket)] pub struct ClientboundSoundPacket { #[var] - /// TODO: use the sound registry instead of just being a u32 + // TODO: use the sound registry instead of just being a u32 pub sound: u32, pub source: SoundSource, pub x: i32, @@ -11,6 +11,8 @@ pub struct ClientboundSoundPacket { pub z: i32, pub volume: f32, pub pitch: f32, + /// Seed used to pick sound varient. + pub seed: u64, } #[derive(Clone, Debug, Copy, McBuf)] diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index eee36788..c4435636 100755 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -37,6 +37,7 @@ pub mod clientbound_set_default_spawn_position_packet; pub mod clientbound_set_display_chat_preview_packet; pub mod clientbound_set_entity_data_packet; pub mod clientbound_set_entity_link_packet; +pub mod clientbound_set_equipment_packet; pub mod clientbound_set_experience_packet; pub mod clientbound_set_health_packet; pub mod clientbound_set_time_packet; @@ -104,6 +105,7 @@ declare_state_packets!( 0x4b: clientbound_set_display_chat_preview_packet::ClientboundSetDisplayChatPreviewPacket, 0x4d: clientbound_set_entity_data_packet::ClientboundSetEntityDataPacket, 0x4f: clientbound_entity_velocity_packet::ClientboundEntityVelocityPacket, + 0x50: clientbound_set_equipment_packet::ClientboundSetEquipmentPacket, 0x51: clientbound_set_experience_packet::ClientboundSetExperiencePacket, 0x52: clientbound_set_health_packet::ClientboundSetHealthPacket, 0x59: clientbound_set_time_packet::ClientboundSetTimePacket, diff --git a/azalea-world/Cargo.toml b/azalea-world/Cargo.toml index e8d81ac3..79e6155d 100644 --- a/azalea-world/Cargo.toml +++ b/azalea-world/Cargo.toml @@ -9,3 +9,4 @@ version = "0.1.0" azalea-core = {path = "../azalea-core"} azalea-nbt = {path = "../azalea-nbt"} azalea-protocol = {path = "../azalea-protocol"} +azalea-block = {path = "../azalea-block"} diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index aba52aef..0dc81f9a 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -77,8 +77,8 @@ pub struct BitStorage { mask: u64, size: usize, values_per_long: u8, - divide_mul: i32, - divide_add: i32, + divide_mul: u64, + divide_add: u64, divide_shift: i32, } @@ -138,16 +138,16 @@ impl BitStorage { mask, size, values_per_long: values_per_long as u8, - divide_mul, - divide_add, + divide_mul: divide_mul as u32 as u64, + divide_add: divide_add as u32 as u64, divide_shift, }) } pub fn cell_index(&self, index: u64) -> usize { // as unsigned wrap - let first = self.divide_mul as u32 as u64; - let second = self.divide_add as u64; + let first = self.divide_mul; + let second = self.divide_add; (((index * first) + second) >> 32 >> self.divide_shift) .try_into() @@ -188,6 +188,12 @@ impl BitStorage { let bit_index = (index - cell_index * self.values_per_long as usize) * self.bits; *cell = *cell & !(self.mask << bit_index) | (value & self.mask) << bit_index; } + + /// The number of entries. + #[inline] + pub fn size(&self) -> usize { + self.size + } } #[cfg(test)] diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 766c61f0..e651e455 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -4,6 +4,7 @@ mod bit_storage; mod palette; use crate::palette::PalettedContainerType; +use azalea_block::BlockState; use azalea_core::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos}; use azalea_protocol::mc_buf::{McBufReadable, McBufWritable}; pub use bit_storage::BitStorage; @@ -57,7 +58,7 @@ impl World { self.storage.view_center = *pos; } - pub fn get_block_state(&self, pos: &BlockPos) -> Option { + pub fn get_block_state(&self, pos: &BlockPos) -> Option { self.storage.get_block_state(pos, self.min_y) } } @@ -122,7 +123,7 @@ impl ChunkStorage { && (chunk_pos.z - self.view_center.z).unsigned_abs() <= self.chunk_radius } - pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option { + pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option { let chunk_pos = ChunkPos::from(pos); println!("chunk_pos {:?} block_pos {:?}", chunk_pos, pos); let chunk = &self[&chunk_pos]; @@ -175,7 +176,7 @@ impl Chunk { (y.div_floor(16) - min_section_index) as u32 } - pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> u32 { + pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> BlockState { let section_index = self.section_index(pos.y, min_y); // TODO: make sure the section exists let section = &self.sections[section_index as usize]; @@ -204,12 +205,25 @@ pub struct Section { impl McBufReadable for Section { fn read_into(buf: &mut impl Read) -> Result { let block_count = u16::read_into(buf)?; + // this is commented out because the vanilla server is wrong // assert!( // block_count <= 16 * 16 * 16, // "A section has more blocks than what should be possible. This is a bug!" // ); + let states = PalettedContainer::read_with_type(buf, &PalettedContainerType::BlockStates)?; + + for i in 0..states.storage.size() { + if !BlockState::is_valid_state(states.storage.get(i) as u32) { + return Err(format!( + "Invalid block state {} (index {}) found in section.", + states.storage.get(i), + i + )); + } + } + let biomes = PalettedContainer::read_with_type(buf, &PalettedContainerType::Biomes)?; Ok(Section { block_count, @@ -229,9 +243,11 @@ impl McBufWritable for Section { } impl Section { - // TODO: return a BlockState instead of a u32 - fn get(&self, pos: ChunkSectionBlockPos) -> u32 { + fn get(&self, pos: ChunkSectionBlockPos) -> BlockState { + // TODO: use the unsafe method and do the check earlier self.states .get(pos.x as usize, pos.y as usize, pos.z as usize) + .try_into() + .expect("Invalid block state.") } } diff --git a/bot/src/main.rs b/bot/src/main.rs index 8ad74ec4..2618675e 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -6,7 +6,7 @@ async fn main() { println!("Hello, world!"); // let address = "95.111.249.143:10000"; - let address = "localhost:65519"; + let address = "localhost:51028"; // let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // .await // .unwrap(); @@ -21,6 +21,10 @@ async fn main() { // TODO: have a "loaded" or "ready" event that fires when all chunks are loaded Event::Login => {} Event::Chat(p) => { + let state = client.state.lock().await; + let world = state.world.as_ref().unwrap(); + // println!("{:?}", state.player.entity); + // world.get_block_state(state.player.entity.pos); // println!("{}", p.message.to_ansi(None)); // if p.message.to_ansi(None) == " ok" { // let state = client.state.lock().await; diff --git a/codegen/genblocks.py b/codegen/genblocks.py new file mode 100644 index 00000000..9e35f7f3 --- /dev/null +++ b/codegen/genblocks.py @@ -0,0 +1,28 @@ +import lib.code.version +import lib.code.packet +import lib.code.blocks +import lib.code.utils +import lib.download +import lib.extract +import lib.utils +import sys +import os + +version_id = lib.code.version.get_version_id() + +lib.download.get_burger() +lib.download.get_client_jar(version_id) + +print('Generating data with burger') +os.system( + f'cd {lib.utils.get_dir_location("downloads/Burger")} && python munch.py ../client-{version_id}.jar --output ../burger-{version_id}.json --toppings blockstates' +) +print('Ok') + +mappings = lib.download.get_mappings_for_version(version_id) +block_states_burger = lib.extract.get_block_states_burger(version_id) +ordered_blocks = lib.extract.get_ordered_blocks_burger(version_id) +block_states_report = lib.extract.get_block_states_report(version_id) + +lib.code.blocks.generate_blocks( + block_states_burger, block_states_report, ordered_blocks, mappings) diff --git a/codegen/lib/code/blocks.py b/codegen/lib/code/blocks.py new file mode 100644 index 00000000..4ab4917f --- /dev/null +++ b/codegen/lib/code/blocks.py @@ -0,0 +1,185 @@ +from typing import Optional +from lib.utils import to_snake_case, upper_first_letter, get_dir_location, to_camel_case +from ..mappings import Mappings +import re + +BLOCKS_RS_DIR = get_dir_location('../azalea-block/src/blocks.rs') + +# Terminology: +# - Property: A property of a block, like "direction" +# - Variant: A potential state of a property, like "up" +# - State: A possible state of a block, a combination of variants +# - Block: Has properties and states. + + +def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: list[str], mappings: Mappings): + with open(BLOCKS_RS_DIR, 'r') as f: + existing_code = f.read().splitlines() + + new_make_block_states_macro_code = [] + new_make_block_states_macro_code.append('make_block_states! {') + + def get_property_struct_name(property: Optional[dict], block_data_burger: dict, property_variants: list[str]) -> str: + # these are hardcoded because otherwise they cause conflicts + # some names inspired by https://github.com/feather-rs/feather/blob/main/feather/blocks/src/generated/table.rs + if property_variants == ['north', 'east', 'south', 'west', 'up', 'down']: + return 'FacingCubic' + if property_variants == ['north', 'south', 'west', 'east']: + return 'FacingCardinal' + if property_variants == ['top', 'bottom']: + return 'TopBottom' + if property_variants == ['north_south', 'east_west', 'ascending_east', 'ascending_west', 'ascending_north', 'ascending_south']: + return 'RailShape' + if property_variants == ['straight', 'inner_left', 'inner_right', 'outer_left', 'outer_right']: + return 'StairShape' + if property_variants == ['normal', 'sticky']: + return 'PistonType' + if property_variants == ['x', 'z']: + return 'AxisXZ' + if property_variants == ['single', 'left', 'right']: + return 'ChestType' + if property_variants == ['compare', 'subtract']: + return 'ComparatorType' + + if property is None: + return ''.join(map(to_camel_case, property_variants)) + + property_name = None + for class_name in [block_data_burger['class']] + block_data_burger['super']: + property_name = mappings.get_field( + class_name, property['field_name']) + if property_name: + break + assert property_name + property_name = to_camel_case(property_name.lower()) + if property['type'] == 'int': + property_name = to_camel_case( + block_data_burger['text_id']) + property_name + + # if property_variants == ['none', 'low', 'tall']: + + if property_variants == ['up', 'side', 'none']: + property_name = 'Wire' + to_camel_case(property_name) + + return property_name + + # Find properties + properties = {} + + # This dict looks like { 'FloweringAzaleaLeavesDistance': 'distance' } + property_struct_names_to_names = {} + for block_id in ordered_blocks: + block_data_burger = blocks_burger[block_id] + block_data_report = blocks_report[f'minecraft:{block_id}'] + + block_properties = {} + for property_name in list(block_data_report.get('properties', {}).keys()): + property_burger = None + for property in block_data_burger.get('states', []): + if property['name'] == property_name: + property_burger = property + break + + property_variants = block_data_report['properties'][property_name] + + if property_burger is None: + print( + 'Warning: The reports have states for a block, but Burger doesn\'t!', block_data_burger) + + property_struct_name = get_property_struct_name( + property_burger, block_data_burger, property_variants) + + if property_struct_name in properties: + if not properties[property_struct_name] == property_variants: + raise Exception( + 'There are multiple enums with the same name! ' + f'Name: {property_struct_name}, variants: {property_variants}/{properties[property_struct_name]}. ' + 'This can be fixed by hardcoding a name in the get_property_struct_name function.' + ) + + block_properties[property_struct_name] = property_variants + + # if the name ends with _, remove that part + ending = property_name.split('_')[-1] + if ending.isdigit(): + property_name = property_name[:-(len(ending) + 1)] + + # `type` is a reserved keyword, so we use kind instead ¯\_(ツ)_/¯ + if property_name == 'type': + property_name = 'kind' + property_struct_names_to_names[property_struct_name] = property_name + + properties.update(block_properties) + + # Property codegen + new_make_block_states_macro_code.append(' Properties => {') + for property_struct_name, property_variants in properties.items(): + # "face" => Face { + # Floor, + # Wall, + # Ceiling, + # }, + property_name = property_struct_names_to_names[property_struct_name] + new_make_block_states_macro_code.append( + f' "{property_name}" => {property_struct_name} {{') + + for variant in property_variants: + new_make_block_states_macro_code.append( + f' {to_camel_case(variant)},') + + new_make_block_states_macro_code.append( + f' }},') + new_make_block_states_macro_code.append(' },') + + # Block codegen + new_make_block_states_macro_code.append(' Blocks => {') + for block_id in ordered_blocks: + block_data_burger = blocks_burger[block_id] + block_data_report = blocks_report['minecraft:' + block_id] + + block_properties = block_data_burger.get('states', []) + block_properties_burger = block_data_burger.get('states', []) + + default_property_variants: dict[str, str] = {} + for state in block_data_report['states']: + if state.get('default'): + default_property_variants = state.get('properties', {}) + + # TODO: use burger to generate the blockbehavior + new_make_block_states_macro_code.append( + f' {block_id} => BlockBehavior::default(), {{') + for property_name in list(block_data_report.get('properties', {}).keys()): + property_burger = None + for property in block_data_burger.get('states', []): + if property['name'] == property_name: + property_burger = property + break + + property_default = default_property_variants.get(property_name) + property_variants = block_data_report['properties'][property_name] + + property_struct_name = get_property_struct_name( + property_burger, block_data_burger, property_variants) + assert property_default is not None + new_make_block_states_macro_code.append( + f' {property_struct_name}={to_camel_case(property_default)},') + new_make_block_states_macro_code.append(' },') + new_make_block_states_macro_code.append(' }') + new_make_block_states_macro_code.append('}') + + new_code = [] + in_macro = False + for line in existing_code: + if line == 'make_block_states! {': + in_macro = True + elif line == '}': + if in_macro: + in_macro = False + new_code.extend(new_make_block_states_macro_code) + continue + if in_macro: + continue + new_code.append(line) + + with open(BLOCKS_RS_DIR, 'w') as f: + f.write('\n'.join(new_code)) diff --git a/codegen/lib/code/packet.py b/codegen/lib/code/packet.py index 36e0ba0c..2aabf39a 100644 --- a/codegen/lib/code/packet.py +++ b/codegen/lib/code/packet.py @@ -1,6 +1,6 @@ -from .utils import burger_type_to_rust_type, write_packet_file -from ..utils import padded_hex, to_snake_case, to_camel_case -from ..mappings import Mappings +from lib.code.utils import burger_type_to_rust_type, write_packet_file +from lib.utils import padded_hex, to_snake_case, to_camel_case, get_dir_location +from lib.mappings import Mappings import os @@ -74,7 +74,8 @@ def generate_packet(burger_packets, mappings: Mappings, target_packet_id, target '\n'.join(generated_packet_code)) print() - mod_rs_dir = f'../azalea-protocol/src/packets/{state}/mod.rs' + mod_rs_dir = get_dir_location( + f'../azalea-protocol/src/packets/{state}/mod.rs') with open(mod_rs_dir, 'r') as f: mod_rs = f.read().splitlines() diff --git a/codegen/lib/code/utils.py b/codegen/lib/code/utils.py index 28a5ef3c..ecfff4fb 100644 --- a/codegen/lib/code/utils.py +++ b/codegen/lib/code/utils.py @@ -1,4 +1,5 @@ +from lib.utils import get_dir_location import os # utilities specifically for codegen @@ -67,9 +68,9 @@ def burger_type_to_rust_type(burger_type): def write_packet_file(state, packet_name_snake_case, code): - with open(f'../azalea-protocol/src/packets/{state}/{packet_name_snake_case}.rs', 'w') as f: + with open(get_dir_location(f'../azalea-protocol/src/packets/{state}/{packet_name_snake_case}.rs'), 'w') as f: f.write(code) def fmt(): - os.system('cd .. && cargo fmt') + os.system(f'cd {get_dir_location("..")} && cargo fmt') diff --git a/codegen/lib/code/version.py b/codegen/lib/code/version.py index e131a598..511d30d1 100644 --- a/codegen/lib/code/version.py +++ b/codegen/lib/code/version.py @@ -1,7 +1,8 @@ +from lib.utils import get_dir_location import re import os -README_DIR = os.path.join(os.path.dirname(__file__), '../../../README.md') +README_DIR = get_dir_location('../README.md') VERSION_REGEX = r'\*Currently supported Minecraft version: `(.*)`.\*' diff --git a/codegen/lib/download.py b/codegen/lib/download.py index 7d14a3a3..e05d9a93 100644 --- a/codegen/lib/download.py +++ b/codegen/lib/download.py @@ -1,39 +1,40 @@ +from lib.utils import get_dir_location from .mappings import Mappings import requests import json import os # make sure the downloads directory exists -if not os.path.exists('downloads'): - os.mkdir('downloads') +if not os.path.exists(get_dir_location('downloads')): + os.mkdir(get_dir_location('downloads')) def get_burger(): - if not os.path.exists('downloads/Burger'): + if not os.path.exists(get_dir_location('downloads/Burger')): print('\033[92mDownloading Burger...\033[m') os.system( - 'cd downloads && git clone https://github.com/pokechu22/Burger && cd Burger && git pull') + f'cd {get_dir_location("downloads")} && git clone https://github.com/pokechu22/Burger && cd Burger && git pull') print('\033[92mInstalling dependencies...\033[m') os.system('cd downloads/Burger && pip install six jawa') def get_version_manifest(): - if not os.path.exists(f'downloads/version_manifest.json'): + if not os.path.exists(get_dir_location(f'downloads/version_manifest.json')): print( f'\033[92mDownloading version manifest...\033[m') version_manifest_data = requests.get( 'https://launchermeta.mojang.com/mc/game/version_manifest.json').json() - with open(f'downloads/version_manifest.json', 'w') as f: + with open(get_dir_location(f'downloads/version_manifest.json'), 'w') as f: json.dump(version_manifest_data, f) else: - with open(f'downloads/version_manifest.json', 'r') as f: + with open(get_dir_location(f'downloads/version_manifest.json'), 'r') as f: version_manifest_data = json.load(f) return version_manifest_data def get_version_data(version_id: str): - if not os.path.exists(f'downloads/{version_id}.json'): + if not os.path.exists(get_dir_location(f'downloads/{version_id}.json')): version_manifest_data = get_version_manifest() print( @@ -45,46 +46,43 @@ def get_version_data(version_id: str): raise ValueError( f'No version with id {version_id} found. Maybe delete downloads/version_manifest.json and try again?') package_data = requests.get(package_url).json() - with open(f'downloads/{version_id}.json', 'w') as f: + with open(get_dir_location(f'downloads/{version_id}.json'), 'w') as f: json.dump(package_data, f) else: - with open(f'downloads/{version_id}.json', 'r') as f: + with open(get_dir_location(f'downloads/{version_id}.json'), 'r') as f: package_data = json.load(f) return package_data def get_client_jar(version_id: str): - if not os.path.exists(f'downloads/client-{version_id}.jar'): + if not os.path.exists(get_dir_location(f'downloads/client-{version_id}.jar')): package_data = get_version_data(version_id) print('\033[92mDownloading client jar...\033[m') client_jar_url = package_data['downloads']['client']['url'] - with open(f'downloads/client-{version_id}.jar', 'wb') as f: + with open(get_dir_location(f'downloads/client-{version_id}.jar'), 'wb') as f: f.write(requests.get(client_jar_url).content) -def get_burger_data_for_version(version_id: str): - if not os.path.exists(f'downloads/burger-{version_id}.json'): - get_burger() - get_client_jar(version_id) - - os.system( - f'cd downloads/Burger && python munch.py ../client-{version_id}.jar --output ../burger-{version_id}.json' - ) - with open(f'downloads/burger-{version_id}.json', 'r') as f: - return json.load(f) +def get_server_jar(version_id: str): + if not os.path.exists(get_dir_location(f'downloads/server-{version_id}.jar')): + package_data = get_version_data(version_id) + print('\033[92mDownloading server jar...\033[m') + server_jar_url = package_data['downloads']['server']['url'] + with open(get_dir_location(f'downloads/server-{version_id}.jar'), 'wb') as f: + f.write(requests.get(server_jar_url).content) def get_mappings_for_version(version_id: str): - if not os.path.exists(f'downloads/mappings-{version_id}.txt'): + if not os.path.exists(get_dir_location(f'downloads/mappings-{version_id}.txt')): package_data = get_version_data(version_id) client_mappings_url = package_data['downloads']['client_mappings']['url'] mappings_text = requests.get(client_mappings_url).text - with open(f'downloads/mappings-{version_id}.txt', 'w') as f: + with open(get_dir_location(f'downloads/mappings-{version_id}.txt'), 'w') as f: f.write(mappings_text) else: - with open(f'downloads/mappings-{version_id}.txt', 'r') as f: + with open(get_dir_location(f'downloads/mappings-{version_id}.txt'), 'r') as f: mappings_text = f.read() return Mappings.parse(mappings_text) diff --git a/codegen/lib/extract.py b/codegen/lib/extract.py new file mode 100644 index 00000000..40263779 --- /dev/null +++ b/codegen/lib/extract.py @@ -0,0 +1,44 @@ +# Extracting data from the Minecraft jars + +from lib.download import get_server_jar, get_burger, get_client_jar +from lib.utils import get_dir_location +import json +import os + + +def generate_data_from_server_jar(version_id: str): + if os.path.exists(get_dir_location(f'downloads/generated-{version_id}')): + return + + get_server_jar(version_id) + os.system( + f'cd {get_dir_location(f"downloads")} && java -DbundlerMainClass=net.minecraft.data.Main -jar {get_dir_location(f"downloads/server-{version_id}.jar")} --all --output \"{get_dir_location(f"downloads/generated-{version_id}")}\"' + ) + + +def get_block_states_report(version_id: str): + generate_data_from_server_jar(version_id) + with open(get_dir_location(f'downloads/generated-{version_id}/reports/blocks.json'), 'r') as f: + return json.load(f) + + +def get_block_states_burger(version_id: str): + burger_data = get_burger_data_for_version(version_id) + return burger_data[0]['blocks']['block'] + + +def get_ordered_blocks_burger(version_id: str): + burger_data = get_burger_data_for_version(version_id) + return burger_data[0]['blocks']['ordered_blocks'] + + +def get_burger_data_for_version(version_id: str): + if not os.path.exists(get_dir_location(f'downloads/burger-{version_id}.json')): + get_burger() + get_client_jar(version_id) + + os.system( + f'cd {get_dir_location("downloads/Burger")} && python munch.py ../client-{version_id}.jar --output ../burger-{version_id}.json' + ) + with open(get_dir_location(f'downloads/burger-{version_id}.json'), 'r') as f: + return json.load(f) diff --git a/codegen/lib/utils.py b/codegen/lib/utils.py index c185c0e5..3887bb35 100644 --- a/codegen/lib/utils.py +++ b/codegen/lib/utils.py @@ -1,4 +1,5 @@ import re +import os # utilities that could be used for things other than codegen @@ -10,8 +11,15 @@ def to_snake_case(name: str): def to_camel_case(name: str): s = re.sub('_([a-z])', lambda m: m.group(1).upper(), name) - return s[0].upper() + s[1:] + s = upper_first_letter(s) + # if the first character is a number, we need to add an underscore + # maybe we could convert it to the number name (like 2 would become "two")? + if s[0].isdigit(): + s = f'_{s}' + return s +def upper_first_letter(name: str): + return name[0].upper() + name[1:] def padded_hex(n: int): return f'0x{n:02x}' @@ -44,3 +52,7 @@ def group_packets(packets: list[PacketIdentifier]): packet_groups[key] = [] packet_groups[key].append(packet.packet_id) return packet_groups + + +def get_dir_location(name: str): + return os.path.join(os.path.dirname(__file__), '..', name) diff --git a/codegen/migrate.py b/codegen/migrate.py index 98b701bf..cdffb2de 100644 --- a/codegen/migrate.py +++ b/codegen/migrate.py @@ -4,17 +4,18 @@ import lib.code.utils import lib.code.version import lib.code.packet import lib.download +import lib.extract import sys import os old_version_id = lib.code.version.get_version_id() old_mappings = lib.download.get_mappings_for_version(old_version_id) -old_burger_data = lib.download.get_burger_data_for_version(old_version_id) +old_burger_data = lib.extract.get_burger_data_for_version(old_version_id) old_packet_list = list(old_burger_data[0]['packets']['packet'].values()) new_version_id = sys.argv[1] new_mappings = lib.download.get_mappings_for_version(new_version_id) -new_burger_data = lib.download.get_burger_data_for_version(new_version_id) +new_burger_data = lib.extract.get_burger_data_for_version(new_version_id) new_packet_list = list(new_burger_data[0]['packets']['packet'].values()) diff --git a/codegen/newpacket.py b/codegen/newpacket.py index 2e4c77d7..48d97640 100644 --- a/codegen/newpacket.py +++ b/codegen/newpacket.py @@ -1,17 +1,22 @@ -from lib import download, code # type: ignore +import lib.code.version +import lib.code.packet +import lib.code.utils +import lib.download +import lib.extract import sys -import os -mappings = download.get_mappings_for_version('1.18.2') -burger_data = download.get_burger_data_for_version('1.18.2') +version_id = lib.code.version.get_version_id() + +mappings = lib.download.get_mappings_for_version(version_id) +burger_data = lib.extract.get_burger_data_for_version(version_id) burger_packets_data = burger_data[0]['packets']['packet'] packet_id, direction, state = int(sys.argv[1]), sys.argv[2], sys.argv[3] print( f'Generating code for packet id: {packet_id} with direction {direction} and state {state}') -code.packetcodegen.generate_packet(burger_packets_data, mappings, - packet_id, direction, state) +lib.code.packet.generate_packet(burger_packets_data, mappings, + packet_id, direction, state) -code.fmt() +lib.code.utils.fmt() print('Done!') diff --git a/examples/craft_dig_straight_down.rs b/examples/craft_dig_straight_down.rs index 79985672..1d1a89f6 100644 --- a/examples/craft_dig_straight_down.rs +++ b/examples/craft_dig_straight_down.rs @@ -14,7 +14,7 @@ loop { pathfinder::Goals::NearXZ(5, azalea::BlockXZ(0, 0)) ).await; let chest = bot.open_chest(&bot.world.find_one_block(|b| b.id == "minecraft:chest")).await.unwrap(); - bot.take_amount(&chest, 3, |i| i.id == "#minecraft:planks").await; + bot.take_amount(&chest, 5, |i| i.id == "#minecraft:planks").await; // when rust adds async drop this won't be necessary chest.close().await;