From 7405427199e5a994d4a6a706f84434a69cb7a7d9 Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Fri, 14 Jul 2023 22:20:40 -0500 Subject: [PATCH] Mining (#95) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * more mining stuff * initialize azalea-tags crate * more mining stuff 2 * mining in ecs * well technically mining works but no codegen for how long it takes to mine each block yet * rename downloads to __cache__ it was bothering me since it's not *just* downloads * codegen block behavior * fix not sending packet to finish breaking block * mining animation 🎉 * clippy * cleanup, move Client::mine into a client extension * add azalea/src/mining.rs --------- Co-authored-by: mat --- Cargo.lock | 129 +- Cargo.toml | 1 + azalea-block/azalea-block-macros/src/lib.rs | 35 +- azalea-block/src/behavior.rs | 36 +- azalea-block/src/generated.rs | 2010 +++++----- azalea-block/src/lib.rs | 80 +- azalea-buf/src/read.rs | 15 +- azalea-client/Cargo.toml | 1 + azalea-client/src/account.rs | 5 +- azalea-client/src/client.rs | 28 +- azalea-client/src/entity_query.rs | 6 +- azalea-client/src/events.rs | 2 +- azalea-client/src/interact.rs | 88 +- azalea-client/src/inventory.rs | 25 +- azalea-client/src/lib.rs | 2 +- azalea-client/src/local_player.rs | 10 +- azalea-client/src/mining.rs | 541 ++- azalea-client/src/movement.rs | 31 +- azalea-client/src/packet_handling.rs | 41 +- azalea-client/src/player.rs | 2 +- azalea-core/src/lib.rs | 63 +- azalea-core/src/math.rs | 56 + .../src/{particle/mod.rs => particle.rs} | 0 azalea-core/src/tier.rs | 46 + azalea-entity/Cargo.toml | 25 + .../src}/attributes.rs | 0 .../src/entity => azalea-entity/src}/data.rs | 2 +- .../src}/dimensions.rs | 0 azalea-entity/src/effects.rs | 26 + azalea-entity/src/enchantments.rs | 8 + .../src/entity => azalea-entity/src}/info.rs | 58 +- .../entity/mod.rs => azalea-entity/src/lib.rs | 34 +- .../entity => azalea-entity/src}/metadata.rs | 2 +- azalea-entity/src/mining.rs | 170 + azalea-entity/src/systems.rs | 181 + azalea-inventory/src/lib.rs | 4 +- azalea-physics/Cargo.toml | 1 + azalea-physics/src/clip.rs | 2 +- azalea-physics/src/collision/mergers.rs | 5 +- azalea-physics/src/collision/mod.rs | 10 +- azalea-physics/src/collision/shape.rs | 2 +- .../src/collision/world_collisions.rs | 4 +- azalea-physics/src/lib.rs | 23 +- azalea-protocol/Cargo.toml | 1 + .../game/clientbound_add_entity_packet.rs | 2 +- .../game/clientbound_add_player_packet.rs | 2 +- .../clientbound_level_particles_packet.rs | 2 +- .../clientbound_set_entity_data_packet.rs | 2 +- .../clientbound_update_attributes_packet.rs | 2 +- .../game/clientbound_update_recipes_packet.rs | 10 +- azalea-registry/Cargo.toml | 1 + azalea-registry/src/lib.rs | 2 + azalea-registry/src/tags/blocks.rs | 3374 +++++++++++++++++ azalea-registry/src/tags/fluids.rs | 12 + azalea-registry/src/tags/items.rs | 1379 +++++++ azalea-registry/src/tags/mod.rs | 3 + azalea-world/src/container.rs | 13 +- azalea-world/src/lib.rs | 1 - azalea-world/src/world.rs | 212 +- azalea/Cargo.toml | 1 + azalea/examples/testbot.rs | 21 +- azalea/src/bot.rs | 5 +- azalea/src/lib.rs | 4 +- azalea/src/mining.rs | 40 + azalea/src/pathfinder/mod.rs | 12 +- azalea/src/prelude.rs | 4 +- azalea/src/swarm/events.rs | 2 +- codegen/.gitignore | 4 +- codegen/genblocks.py | 2 +- codegen/genregistries.py | 26 +- codegen/lib/code/blocks.py | 24 +- codegen/lib/code/shapes.py | 2 +- codegen/lib/code/tags.py | 35 + codegen/lib/download.py | 76 +- codegen/lib/extract.py | 35 +- codegen/migrate.py | 5 +- 76 files changed, 7523 insertions(+), 1603 deletions(-) create mode 100644 azalea-core/src/math.rs rename azalea-core/src/{particle/mod.rs => particle.rs} (100%) create mode 100644 azalea-core/src/tier.rs create mode 100644 azalea-entity/Cargo.toml rename {azalea-world/src/entity => azalea-entity/src}/attributes.rs (100%) rename {azalea-world/src/entity => azalea-entity/src}/data.rs (98%) rename {azalea-world/src/entity => azalea-entity/src}/dimensions.rs (100%) create mode 100644 azalea-entity/src/effects.rs create mode 100644 azalea-entity/src/enchantments.rs rename {azalea-world/src/entity => azalea-entity/src}/info.rs (87%) rename azalea-world/src/entity/mod.rs => azalea-entity/src/lib.rs (93%) rename {azalea-world/src/entity => azalea-entity/src}/metadata.rs (99%) create mode 100644 azalea-entity/src/mining.rs create mode 100644 azalea-entity/src/systems.rs create mode 100644 azalea-registry/src/tags/blocks.rs create mode 100644 azalea-registry/src/tags/fluids.rs create mode 100644 azalea-registry/src/tags/items.rs create mode 100644 azalea-registry/src/tags/mod.rs create mode 100644 azalea/src/mining.rs create mode 100644 codegen/lib/code/tags.py diff --git a/Cargo.lock b/Cargo.lock index ec106c39..e3a9ab65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,9 +87,9 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "async-channel" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0122885821398cc923ece939e24d1056a2384ee719432397fa9db87230ff11" +checksum = "62b74f44609f0f91493e3082d3734d98497e094777144380ea4db9f9905dd5b6" dependencies = [ "flate2", "futures-core", @@ -178,6 +178,7 @@ dependencies = [ "azalea-chat", "azalea-client", "azalea-core", + "azalea-entity", "azalea-inventory", "azalea-physics", "azalea-protocol", @@ -293,6 +294,7 @@ dependencies = [ "azalea-chat", "azalea-core", "azalea-crypto", + "azalea-entity", "azalea-inventory", "azalea-nbt", "azalea-physics", @@ -349,6 +351,29 @@ dependencies = [ "uuid", ] +[[package]] +name = "azalea-entity" +version = "0.1.0" +dependencies = [ + "azalea-block", + "azalea-buf", + "azalea-chat", + "azalea-core", + "azalea-inventory", + "azalea-nbt", + "azalea-registry", + "azalea-world", + "bevy_app", + "bevy_ecs", + "derive_more", + "enum-as-inner 0.6.0", + "log", + "nohash-hasher", + "parking_lot", + "thiserror", + "uuid", +] + [[package]] name = "azalea-inventory" version = "0.7.0" @@ -401,6 +426,7 @@ version = "0.7.0" dependencies = [ "azalea-block", "azalea-core", + "azalea-entity", "azalea-inventory", "azalea-registry", "azalea-world", @@ -426,6 +452,7 @@ dependencies = [ "azalea-chat", "azalea-core", "azalea-crypto", + "azalea-entity", "azalea-inventory", "azalea-nbt", "azalea-protocol-macros", @@ -465,6 +492,7 @@ version = "0.7.0" dependencies = [ "azalea-buf", "azalea-registry-macros", + "once_cell", "serde", ] @@ -933,9 +961,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" [[package]] name = "convert_case" @@ -945,9 +973,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -1058,9 +1086,9 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "der" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17" +checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" dependencies = [ "const-oid", "pem-rfc7468", @@ -1151,15 +1179,15 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.3.25" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" +checksum = "f94c0e13118e7d7533271f754a168ae8400e6a1cc043f2bfd53cc7290f1a1de3" dependencies = [ "serde", ] @@ -1531,10 +1559,11 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ + "futures-util", "http", "hyper", "rustls", @@ -1612,9 +1641,9 @@ checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "is-terminal" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", "rustix", @@ -1632,9 +1661,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "js-sys" @@ -1783,9 +1812,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -1808,9 +1837,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" dependencies = [ "byteorder", "lazy_static", @@ -2153,7 +2182,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata 0.3.2", - "regex-syntax 0.7.3", + "regex-syntax 0.7.4", ] [[package]] @@ -2173,7 +2202,7 @@ checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.3", + "regex-syntax 0.7.4", ] [[package]] @@ -2184,9 +2213,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "reqwest" @@ -2299,9 +2328,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.1" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc6396159432b5c8490d4e301d8c705f61860b8b6c863bf79942ce5401968f3" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" dependencies = [ "bitflags 2.3.3", "errno", @@ -2312,9 +2341,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.2" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" dependencies = [ "log", "ring", @@ -2333,9 +2362,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.100.1" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" dependencies = [ "ring", "untrusted", @@ -2343,15 +2372,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "same-file" @@ -2386,27 +2415,27 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.170" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56657f512baabca8f840542f9ca8152aecf182c473c26e46e58d6aab4f6e439" +checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c5113243e4a3a1c96587342d067f3e6b0f50790b6cf40d2868eb647a3eef0e" +checksum = "5a16be4fe5320ade08736447e3198294a5ea9a6d44dde6f35f0a5e06859c427a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.170" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77d477848e6b23adba0db397777d5aad864555bc17fd9c89abb3b8009788b7b8" +checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" dependencies = [ "proc-macro2", "quote", @@ -2415,9 +2444,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" +checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" dependencies = [ "itoa", "ryu", @@ -2723,9 +2752,9 @@ checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ "indexmap 2.0.0", "toml_datetime", @@ -3162,9 +3191,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index ac961997..c9bbddbb 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ members = [ "azalea-physics", "azalea-registry", "azalea-inventory", + "azalea-entity", ] resolver = "2" diff --git a/azalea-block/azalea-block-macros/src/lib.rs b/azalea-block/azalea-block-macros/src/lib.rs index c12f7b86..11510a0a 100755 --- a/azalea-block/azalea-block-macros/src/lib.rs +++ b/azalea-block/azalea-block-macros/src/lib.rs @@ -312,6 +312,9 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { let mut from_registry_block_to_blockstate_match = quote! {}; let mut from_registry_block_to_blockstates_match = quote! {}; + // a list of block state ids that are waterlogged + let mut waterlogged_state_ids: Vec = Vec::new(); + for block in &input.block_definitions.blocks { let block_property_names = &block .properties_and_defaults @@ -448,15 +451,21 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { is_default = false; } - let property_type = if property.is_enum { + let property_value = if property.is_enum { quote! {properties::#property_struct_name_ident::#variant} } else { quote! {#variant} }; from_block_to_state_combination_match_inner.extend(quote! { - #property_name: #property_type, + #property_name: #property_value, }); + + // if "waterlogged" is a property and it's true for this state then add it to + // waterlogged_state_ids + if property_name == "waterlogged" && property_value.to_string() == "true" { + waterlogged_state_ids.push(state_id) + } } from_block_to_state_match_inner.extend(quote! { @@ -473,7 +482,16 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { } let Some(default_state_id) = default_state_id else { - let defaults = properties_with_name.iter().map(|p| if let TokenTree::Ident(i) = p.default.clone().into_iter().last().unwrap() { i.to_string() } else { panic!() }).collect::>(); + let defaults = properties_with_name + .iter() + .map(|p| { + if let TokenTree::Ident(i) = p.default.clone().into_iter().last().unwrap() { + i.to_string() + } else { + panic!() + } + }) + .collect::>(); panic!("Couldn't get default state id for {block_name_pascal_case}, combinations={block_properties_vec:?}, defaults={defaults:?}") }; @@ -570,6 +588,9 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { fn as_block_state(&self) -> BlockState { #from_block_to_state_match } + fn as_registry_block(&self) -> azalea_registry::Block { + azalea_registry::Block::#block_name_pascal_case + } } impl From<#block_struct_name> for BlockState { @@ -590,6 +611,8 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { block_structs.extend(block_struct); } + let waterlogged_state_ids_match = quote! { #(#waterlogged_state_ids)|* }; + let last_state_id = state_id - 1; let mut generated = quote! { impl BlockState { @@ -598,6 +621,12 @@ pub fn make_block_states(input: TokenStream) -> TokenStream { pub fn max_state() -> u32 { #last_state_id } + + /// Whether the given block state is waterlogged. This checks for + /// the `waterlogged` field, so it'll return false for water. + pub fn waterlogged(&self) -> bool { + matches!(self.id, #waterlogged_state_ids_match) + } } pub mod properties { diff --git a/azalea-block/src/behavior.rs b/azalea-block/src/behavior.rs index 18854fff..498ba06f 100755 --- a/azalea-block/src/behavior.rs +++ b/azalea-block/src/behavior.rs @@ -1,35 +1,55 @@ pub struct BlockBehavior { - pub has_collision: bool, pub friction: f32, pub jump_factor: f32, + pub destroy_time: f32, + pub explosion_resistance: f32, + pub requires_correct_tool_for_drops: bool, } impl Default for BlockBehavior { fn default() -> Self { Self { - has_collision: true, friction: 0.6, jump_factor: 1.0, + destroy_time: 0., + explosion_resistance: 0., + requires_correct_tool_for_drops: false, } } } impl BlockBehavior { - #[inline] - pub fn no_collision(mut self) -> Self { - self.has_collision = false; - self + pub fn new() -> Self { + Self::default() } - #[inline] pub fn friction(mut self, friction: f32) -> Self { self.friction = friction; self } - #[inline] pub fn jump_factor(mut self, jump_factor: f32) -> Self { self.jump_factor = jump_factor; self } + + pub fn destroy_time(mut self, destroy_time: f32) -> Self { + self.destroy_time = destroy_time; + self + } + + pub fn explosion_resistance(mut self, explosion_resistance: f32) -> Self { + self.explosion_resistance = f32::max(0., explosion_resistance); + self + } + + pub fn strength(self, destroy_time: f32, explosion_resistance: f32) -> Self { + self.destroy_time(destroy_time) + .explosion_resistance(explosion_resistance) + } + + pub fn requires_correct_tool_for_drops(mut self) -> Self { + self.requires_correct_tool_for_drops = true; + self + } } diff --git a/azalea-block/src/generated.rs b/azalea-block/src/generated.rs index e2faed85..f5c8eee5 100755 --- a/azalea-block/src/generated.rs +++ b/azalea-block/src/generated.rs @@ -1506,7 +1506,7 @@ make_block_states! { _1, _2, }, - "age" => SnifferEggAge { + "hatch" => SnifferEggHatch { _0, _1, _2, @@ -1928,414 +1928,414 @@ make_block_states! { "cracked" => bool, }, 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(), { + air => BlockBehavior::new(), {}, + stone => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + granite => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + polished_granite => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + diorite => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + polished_diorite => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + andesite => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + polished_andesite => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + grass_block => BlockBehavior::new().strength(0.6, 0.6), { snowy: false, }, - dirt => BlockBehavior::default(), {}, - coarse_dirt => BlockBehavior::default(), {}, - podzol => BlockBehavior::default(), { + dirt => BlockBehavior::new().strength(0.5, 0.5), {}, + coarse_dirt => BlockBehavior::new().strength(0.5, 0.5), {}, + podzol => BlockBehavior::new().strength(0.5, 0.5), { 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(), {}, - cherry_planks => BlockBehavior::default(), {}, - dark_oak_planks => BlockBehavior::default(), {}, - mangrove_planks => BlockBehavior::default(), {}, - bamboo_planks => BlockBehavior::default(), {}, - bamboo_mosaic => BlockBehavior::default(), {}, - oak_sapling => BlockBehavior::default(), { + cobblestone => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + oak_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + spruce_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + birch_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + jungle_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + acacia_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + cherry_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + dark_oak_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + mangrove_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + bamboo_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + bamboo_mosaic => BlockBehavior::new().strength(2.0, 3.0), {}, + oak_sapling => BlockBehavior::new(), { stage: OakSaplingStage::_0, }, - spruce_sapling => BlockBehavior::default(), { + spruce_sapling => BlockBehavior::new(), { stage: SpruceSaplingStage::_0, }, - birch_sapling => BlockBehavior::default(), { + birch_sapling => BlockBehavior::new(), { stage: BirchSaplingStage::_0, }, - jungle_sapling => BlockBehavior::default(), { + jungle_sapling => BlockBehavior::new(), { stage: JungleSaplingStage::_0, }, - acacia_sapling => BlockBehavior::default(), { + acacia_sapling => BlockBehavior::new(), { stage: AcaciaSaplingStage::_0, }, - cherry_sapling => BlockBehavior::default(), { + cherry_sapling => BlockBehavior::new(), { stage: CherrySaplingStage::_0, }, - dark_oak_sapling => BlockBehavior::default(), { + dark_oak_sapling => BlockBehavior::new(), { stage: DarkOakSaplingStage::_0, }, - mangrove_propagule => BlockBehavior::default(), { + mangrove_propagule => BlockBehavior::new(), { age: MangrovePropaguleAge::_0, hanging: false, stage: MangrovePropaguleStage::_0, waterlogged: false, }, - bedrock => BlockBehavior::default(), {}, - water => BlockBehavior::default(), { + bedrock => BlockBehavior::new().strength(-1.0, 3600000.0), {}, + water => BlockBehavior::new().strength(100.0, 100.0), { level: WaterLevel::_0, }, - lava => BlockBehavior::default(), { + lava => BlockBehavior::new().strength(100.0, 100.0), { level: LavaLevel::_0, }, - sand => BlockBehavior::default(), {}, - suspicious_sand => BlockBehavior::default(), { + sand => BlockBehavior::new().strength(0.5, 0.5), {}, + suspicious_sand => BlockBehavior::new().strength(0.25, 0.25), { dusted: SuspiciousSandDusted::_0, }, - red_sand => BlockBehavior::default(), {}, - gravel => BlockBehavior::default(), {}, - suspicious_gravel => BlockBehavior::default(), { + red_sand => BlockBehavior::new().strength(0.5, 0.5), {}, + gravel => BlockBehavior::new().strength(0.6, 0.6), {}, + suspicious_gravel => BlockBehavior::new().strength(0.25, 0.25), { dusted: SuspiciousGravelDusted::_0, }, - 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(), { + gold_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + deepslate_gold_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.5, 3.0), {}, + iron_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + deepslate_iron_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.5, 3.0), {}, + coal_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + deepslate_coal_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.5, 3.0), {}, + nether_gold_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + oak_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - spruce_log => BlockBehavior::default(), { + spruce_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - birch_log => BlockBehavior::default(), { + birch_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - jungle_log => BlockBehavior::default(), { + jungle_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - acacia_log => BlockBehavior::default(), { + acacia_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - cherry_log => BlockBehavior::default(), { + cherry_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - dark_oak_log => BlockBehavior::default(), { + dark_oak_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - mangrove_log => BlockBehavior::default(), { + mangrove_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - mangrove_roots => BlockBehavior::default(), { + mangrove_roots => BlockBehavior::new().strength(0.7, 0.7), { waterlogged: false, }, - muddy_mangrove_roots => BlockBehavior::default(), { + muddy_mangrove_roots => BlockBehavior::new().strength(0.7, 0.7), { axis: Axis::Y, }, - bamboo_block => BlockBehavior::default(), { + bamboo_block => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_spruce_log => BlockBehavior::default(), { + stripped_spruce_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_birch_log => BlockBehavior::default(), { + stripped_birch_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_jungle_log => BlockBehavior::default(), { + stripped_jungle_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_acacia_log => BlockBehavior::default(), { + stripped_acacia_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_cherry_log => BlockBehavior::default(), { + stripped_cherry_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_dark_oak_log => BlockBehavior::default(), { + stripped_dark_oak_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_oak_log => BlockBehavior::default(), { + stripped_oak_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_mangrove_log => BlockBehavior::default(), { + stripped_mangrove_log => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_bamboo_block => BlockBehavior::default(), { + stripped_bamboo_block => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - oak_wood => BlockBehavior::default(), { + oak_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - spruce_wood => BlockBehavior::default(), { + spruce_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - birch_wood => BlockBehavior::default(), { + birch_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - jungle_wood => BlockBehavior::default(), { + jungle_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - acacia_wood => BlockBehavior::default(), { + acacia_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - cherry_wood => BlockBehavior::default(), { + cherry_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - dark_oak_wood => BlockBehavior::default(), { + dark_oak_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - mangrove_wood => BlockBehavior::default(), { + mangrove_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_oak_wood => BlockBehavior::default(), { + stripped_oak_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_spruce_wood => BlockBehavior::default(), { + stripped_spruce_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_birch_wood => BlockBehavior::default(), { + stripped_birch_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_jungle_wood => BlockBehavior::default(), { + stripped_jungle_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_acacia_wood => BlockBehavior::default(), { + stripped_acacia_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_cherry_wood => BlockBehavior::default(), { + stripped_cherry_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_dark_oak_wood => BlockBehavior::default(), { + stripped_dark_oak_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_mangrove_wood => BlockBehavior::default(), { + stripped_mangrove_wood => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - oak_leaves => BlockBehavior::default(), { + oak_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: OakLeavesDistance::_7, persistent: false, waterlogged: false, }, - spruce_leaves => BlockBehavior::default(), { + spruce_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: SpruceLeavesDistance::_7, persistent: false, waterlogged: false, }, - birch_leaves => BlockBehavior::default(), { + birch_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: BirchLeavesDistance::_7, persistent: false, waterlogged: false, }, - jungle_leaves => BlockBehavior::default(), { + jungle_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: JungleLeavesDistance::_7, persistent: false, waterlogged: false, }, - acacia_leaves => BlockBehavior::default(), { + acacia_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: AcaciaLeavesDistance::_7, persistent: false, waterlogged: false, }, - cherry_leaves => BlockBehavior::default(), { + cherry_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: CherryLeavesDistance::_7, persistent: false, waterlogged: false, }, - dark_oak_leaves => BlockBehavior::default(), { + dark_oak_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: DarkOakLeavesDistance::_7, persistent: false, waterlogged: false, }, - mangrove_leaves => BlockBehavior::default(), { + mangrove_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: MangroveLeavesDistance::_7, persistent: false, waterlogged: false, }, - azalea_leaves => BlockBehavior::default(), { + azalea_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: AzaleaLeavesDistance::_7, persistent: false, waterlogged: false, }, - flowering_azalea_leaves => BlockBehavior::default(), { + flowering_azalea_leaves => BlockBehavior::new().strength(0.2, 0.2), { distance: 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(), { + sponge => BlockBehavior::new().strength(0.6, 0.6), {}, + wet_sponge => BlockBehavior::new().strength(0.6, 0.6), {}, + glass => BlockBehavior::new().strength(0.3, 0.3), {}, + lapis_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + deepslate_lapis_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.5, 3.0), {}, + lapis_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + dispenser => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), { facing: FacingCubic::North, triggered: false, }, - sandstone => BlockBehavior::default(), {}, - chiseled_sandstone => BlockBehavior::default(), {}, - cut_sandstone => BlockBehavior::default(), {}, - note_block => BlockBehavior::default(), { + sandstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + chiseled_sandstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + cut_sandstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + note_block => BlockBehavior::new().strength(0.8, 0.8), { instrument: Sound::Harp, note: NoteBlockNote::_0, powered: false, }, - white_bed => BlockBehavior::default(), { + white_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - orange_bed => BlockBehavior::default(), { + orange_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - magenta_bed => BlockBehavior::default(), { + magenta_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - light_blue_bed => BlockBehavior::default(), { + light_blue_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - yellow_bed => BlockBehavior::default(), { + yellow_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - lime_bed => BlockBehavior::default(), { + lime_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - pink_bed => BlockBehavior::default(), { + pink_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - gray_bed => BlockBehavior::default(), { + gray_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - light_gray_bed => BlockBehavior::default(), { + light_gray_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - cyan_bed => BlockBehavior::default(), { + cyan_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - purple_bed => BlockBehavior::default(), { + purple_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - blue_bed => BlockBehavior::default(), { + blue_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - brown_bed => BlockBehavior::default(), { + brown_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - green_bed => BlockBehavior::default(), { + green_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - red_bed => BlockBehavior::default(), { + red_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - black_bed => BlockBehavior::default(), { + black_bed => BlockBehavior::new().strength(0.2, 0.2), { facing: FacingCardinal::North, occupied: false, part: Part::Foot, }, - powered_rail => BlockBehavior::default(), { + powered_rail => BlockBehavior::new().strength(0.7, 0.7), { powered: false, shape: RailShape::NorthSouth, waterlogged: false, }, - detector_rail => BlockBehavior::default(), { + detector_rail => BlockBehavior::new().strength(0.7, 0.7), { powered: false, shape: RailShape::NorthSouth, waterlogged: false, }, - sticky_piston => BlockBehavior::default(), { + sticky_piston => BlockBehavior::new().strength(1.5, 1.5), { extended: false, facing: FacingCubic::North, }, - cobweb => BlockBehavior::default(), {}, - grass => BlockBehavior::default(), {}, - fern => BlockBehavior::default(), {}, - dead_bush => BlockBehavior::default(), {}, - seagrass => BlockBehavior::default(), {}, - tall_seagrass => BlockBehavior::default(), { + cobweb => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.0, 4.0), {}, + grass => BlockBehavior::new(), {}, + fern => BlockBehavior::new(), {}, + dead_bush => BlockBehavior::new(), {}, + seagrass => BlockBehavior::new(), {}, + tall_seagrass => BlockBehavior::new(), { half: Half::Lower, }, - piston => BlockBehavior::default(), { + piston => BlockBehavior::new().strength(1.5, 1.5), { extended: false, facing: FacingCubic::North, }, - piston_head => BlockBehavior::default(), { + piston_head => BlockBehavior::new().strength(1.5, 1.5), { kind: PistonType::Normal, facing: 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(), { + white_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + orange_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + magenta_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + light_blue_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + yellow_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + lime_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + pink_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + gray_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + light_gray_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + cyan_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + purple_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + blue_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + brown_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + green_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + red_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + black_wool => BlockBehavior::new().strength(0.8, 0.8), {}, + moving_piston => BlockBehavior::new().destroy_time(-1.0), { kind: PistonType::Normal, facing: FacingCubic::North, }, - dandelion => BlockBehavior::default(), {}, - torchflower => 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(), { + dandelion => BlockBehavior::new(), {}, + torchflower => BlockBehavior::new(), {}, + poppy => BlockBehavior::new(), {}, + blue_orchid => BlockBehavior::new(), {}, + allium => BlockBehavior::new(), {}, + azure_bluet => BlockBehavior::new(), {}, + red_tulip => BlockBehavior::new(), {}, + orange_tulip => BlockBehavior::new(), {}, + white_tulip => BlockBehavior::new(), {}, + pink_tulip => BlockBehavior::new(), {}, + oxeye_daisy => BlockBehavior::new(), {}, + cornflower => BlockBehavior::new(), {}, + wither_rose => BlockBehavior::new(), {}, + lily_of_the_valley => BlockBehavior::new(), {}, + brown_mushroom => BlockBehavior::new(), {}, + red_mushroom => BlockBehavior::new(), {}, + gold_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + iron_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {}, + bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + tnt => BlockBehavior::new(), { unstable: false, }, - bookshelf => BlockBehavior::default(), {}, - chiseled_bookshelf => BlockBehavior::default(), { + bookshelf => BlockBehavior::new().strength(1.5, 1.5), {}, + chiseled_bookshelf => BlockBehavior::new().strength(1.5, 1.5), { facing: FacingCardinal::North, slot_0_occupied: false, slot_1_occupied: false, @@ -2344,13 +2344,13 @@ make_block_states! { slot_4_occupied: false, slot_5_occupied: false, }, - mossy_cobblestone => BlockBehavior::default(), {}, - obsidian => BlockBehavior::default(), {}, - torch => BlockBehavior::default(), {}, - wall_torch => BlockBehavior::default(), { + mossy_cobblestone => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + obsidian => BlockBehavior::new().requires_correct_tool_for_drops().strength(50.0, 1200.0), {}, + torch => BlockBehavior::new(), {}, + wall_torch => BlockBehavior::new(), { facing: FacingCardinal::North, }, - fire => BlockBehavior::default(), { + fire => BlockBehavior::new(), { age: FireAge::_0, east: false, north: false, @@ -2358,439 +2358,439 @@ make_block_states! { up: false, west: false, }, - soul_fire => BlockBehavior::default(), {}, - spawner => BlockBehavior::default(), {}, - oak_stairs => BlockBehavior::default(), { + soul_fire => BlockBehavior::new(), {}, + spawner => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 5.0), {}, + oak_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - chest => BlockBehavior::default(), { + chest => BlockBehavior::new().strength(2.5, 2.5), { kind: ChestType::Single, facing: FacingCardinal::North, waterlogged: false, }, - redstone_wire => BlockBehavior::default(), { + redstone_wire => BlockBehavior::new(), { east: WireEast::None, north: WireNorth::None, power: RedstoneWirePower::_0, south: WireSouth::None, west: WireWest::None, }, - diamond_ore => BlockBehavior::default(), {}, - deepslate_diamond_ore => BlockBehavior::default(), {}, - diamond_block => BlockBehavior::default(), {}, - crafting_table => BlockBehavior::default(), {}, - wheat => BlockBehavior::default(), { + diamond_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + deepslate_diamond_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.5, 3.0), {}, + diamond_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {}, + crafting_table => BlockBehavior::new().strength(2.5, 2.5), {}, + wheat => BlockBehavior::new(), { age: WheatAge::_0, }, - farmland => BlockBehavior::default(), { + farmland => BlockBehavior::new().strength(0.6, 0.6), { moisture: FarmlandMoisture::_0, }, - furnace => BlockBehavior::default(), { + furnace => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), { facing: FacingCardinal::North, lit: false, }, - oak_sign => BlockBehavior::default(), { + oak_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: OakSignRotation::_0, waterlogged: false, }, - spruce_sign => BlockBehavior::default(), { + spruce_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: SpruceSignRotation::_0, waterlogged: false, }, - birch_sign => BlockBehavior::default(), { + birch_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: BirchSignRotation::_0, waterlogged: false, }, - acacia_sign => BlockBehavior::default(), { + acacia_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: AcaciaSignRotation::_0, waterlogged: false, }, - cherry_sign => BlockBehavior::default(), { + cherry_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: CherrySignRotation::_0, waterlogged: false, }, - jungle_sign => BlockBehavior::default(), { + jungle_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: JungleSignRotation::_0, waterlogged: false, }, - dark_oak_sign => BlockBehavior::default(), { + dark_oak_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: DarkOakSignRotation::_0, waterlogged: false, }, - mangrove_sign => BlockBehavior::default(), { + mangrove_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: MangroveSignRotation::_0, waterlogged: false, }, - bamboo_sign => BlockBehavior::default(), { + bamboo_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: BambooSignRotation::_0, waterlogged: false, }, - oak_door => BlockBehavior::default(), { + oak_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - ladder => BlockBehavior::default(), { + ladder => BlockBehavior::new().strength(0.4, 0.4), { facing: FacingCardinal::North, waterlogged: false, }, - rail => BlockBehavior::default(), { + rail => BlockBehavior::new().strength(0.7, 0.7), { shape: Shape::NorthSouth, waterlogged: false, }, - cobblestone_stairs => BlockBehavior::default(), { + cobblestone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - oak_wall_sign => BlockBehavior::default(), { + oak_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - spruce_wall_sign => BlockBehavior::default(), { + spruce_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - birch_wall_sign => BlockBehavior::default(), { + birch_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - acacia_wall_sign => BlockBehavior::default(), { + acacia_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - cherry_wall_sign => BlockBehavior::default(), { + cherry_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - jungle_wall_sign => BlockBehavior::default(), { + jungle_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - dark_oak_wall_sign => BlockBehavior::default(), { + dark_oak_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - mangrove_wall_sign => BlockBehavior::default(), { + mangrove_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - bamboo_wall_sign => BlockBehavior::default(), { + bamboo_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - oak_hanging_sign => BlockBehavior::default(), { + oak_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: OakHangingSignRotation::_0, waterlogged: false, }, - spruce_hanging_sign => BlockBehavior::default(), { + spruce_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: SpruceHangingSignRotation::_0, waterlogged: false, }, - birch_hanging_sign => BlockBehavior::default(), { + birch_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: BirchHangingSignRotation::_0, waterlogged: false, }, - acacia_hanging_sign => BlockBehavior::default(), { + acacia_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: AcaciaHangingSignRotation::_0, waterlogged: false, }, - cherry_hanging_sign => BlockBehavior::default(), { + cherry_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: CherryHangingSignRotation::_0, waterlogged: false, }, - jungle_hanging_sign => BlockBehavior::default(), { + jungle_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: JungleHangingSignRotation::_0, waterlogged: false, }, - dark_oak_hanging_sign => BlockBehavior::default(), { + dark_oak_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: DarkOakHangingSignRotation::_0, waterlogged: false, }, - crimson_hanging_sign => BlockBehavior::default(), { + crimson_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: CrimsonHangingSignRotation::_0, waterlogged: false, }, - warped_hanging_sign => BlockBehavior::default(), { + warped_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: WarpedHangingSignRotation::_0, waterlogged: false, }, - mangrove_hanging_sign => BlockBehavior::default(), { + mangrove_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: MangroveHangingSignRotation::_0, waterlogged: false, }, - bamboo_hanging_sign => BlockBehavior::default(), { + bamboo_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { attached: false, rotation: BambooHangingSignRotation::_0, waterlogged: false, }, - oak_wall_hanging_sign => BlockBehavior::default(), { + oak_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - spruce_wall_hanging_sign => BlockBehavior::default(), { + spruce_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - birch_wall_hanging_sign => BlockBehavior::default(), { + birch_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - acacia_wall_hanging_sign => BlockBehavior::default(), { + acacia_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - cherry_wall_hanging_sign => BlockBehavior::default(), { + cherry_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - jungle_wall_hanging_sign => BlockBehavior::default(), { + jungle_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - dark_oak_wall_hanging_sign => BlockBehavior::default(), { + dark_oak_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - mangrove_wall_hanging_sign => BlockBehavior::default(), { + mangrove_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - crimson_wall_hanging_sign => BlockBehavior::default(), { + crimson_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - warped_wall_hanging_sign => BlockBehavior::default(), { + warped_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - bamboo_wall_hanging_sign => BlockBehavior::default(), { + bamboo_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - lever => BlockBehavior::default(), { + lever => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - stone_pressure_plate => BlockBehavior::default(), { + stone_pressure_plate => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.5, 0.5), { powered: false, }, - iron_door => BlockBehavior::default(), { + iron_door => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 5.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - oak_pressure_plate => BlockBehavior::default(), { + oak_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - spruce_pressure_plate => BlockBehavior::default(), { + spruce_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - birch_pressure_plate => BlockBehavior::default(), { + birch_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - jungle_pressure_plate => BlockBehavior::default(), { + jungle_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - acacia_pressure_plate => BlockBehavior::default(), { + acacia_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - cherry_pressure_plate => BlockBehavior::default(), { + cherry_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - dark_oak_pressure_plate => BlockBehavior::default(), { + dark_oak_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - mangrove_pressure_plate => BlockBehavior::default(), { + mangrove_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - bamboo_pressure_plate => BlockBehavior::default(), { + bamboo_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - redstone_ore => BlockBehavior::default(), { + redstone_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), { lit: false, }, - deepslate_redstone_ore => BlockBehavior::default(), { + deepslate_redstone_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.5, 3.0), { lit: false, }, - redstone_torch => BlockBehavior::default(), { + redstone_torch => BlockBehavior::new(), { lit: true, }, - redstone_wall_torch => BlockBehavior::default(), { + redstone_wall_torch => BlockBehavior::new(), { facing: FacingCardinal::North, lit: true, }, - stone_button => BlockBehavior::default(), { + stone_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - snow => BlockBehavior::default(), { + snow => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.1, 0.1), { layers: SnowLayers::_1, }, - ice => BlockBehavior::default(), {}, - snow_block => BlockBehavior::default(), {}, - cactus => BlockBehavior::default(), { + ice => BlockBehavior::new().strength(0.5, 0.5).friction(0.98), {}, + snow_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.2, 0.2), {}, + cactus => BlockBehavior::new().strength(0.4, 0.4), { age: CactusAge::_0, }, - clay => BlockBehavior::default(), {}, - sugar_cane => BlockBehavior::default(), { + clay => BlockBehavior::new().strength(0.6, 0.6), {}, + sugar_cane => BlockBehavior::new(), { age: SugarCaneAge::_0, }, - jukebox => BlockBehavior::default(), { + jukebox => BlockBehavior::new().strength(2.0, 6.0), { has_record: false, }, - oak_fence => BlockBehavior::default(), { + oak_fence => BlockBehavior::new().strength(2.0, 3.0), { 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(), { + pumpkin => BlockBehavior::new().strength(1.0, 1.0), {}, + netherrack => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.4, 0.4), {}, + soul_sand => BlockBehavior::new().strength(0.5, 0.5), {}, + soul_soil => BlockBehavior::new().strength(0.5, 0.5), {}, + basalt => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), { axis: Axis::Y, }, - polished_basalt => BlockBehavior::default(), { + polished_basalt => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), { axis: Axis::Y, }, - soul_torch => BlockBehavior::default(), {}, - soul_wall_torch => BlockBehavior::default(), { + soul_torch => BlockBehavior::new(), {}, + soul_wall_torch => BlockBehavior::new(), { facing: FacingCardinal::North, }, - glowstone => BlockBehavior::default(), {}, - nether_portal => BlockBehavior::default(), { + glowstone => BlockBehavior::new().strength(0.3, 0.3), {}, + nether_portal => BlockBehavior::new().destroy_time(-1.0), { axis: AxisXZ::X, }, - carved_pumpkin => BlockBehavior::default(), { + carved_pumpkin => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - jack_o_lantern => BlockBehavior::default(), { + jack_o_lantern => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - cake => BlockBehavior::default(), { + cake => BlockBehavior::new().strength(0.5, 0.5), { bites: CakeBites::_0, }, - repeater => BlockBehavior::default(), { + repeater => BlockBehavior::new(), { delay: RepeaterDelay::_1, facing: 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(), { + white_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + orange_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + magenta_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + light_blue_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + yellow_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + lime_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + pink_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + gray_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + light_gray_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + cyan_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + purple_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + blue_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + brown_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + green_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + red_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + black_stained_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + oak_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - spruce_trapdoor => BlockBehavior::default(), { + spruce_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - birch_trapdoor => BlockBehavior::default(), { + birch_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - jungle_trapdoor => BlockBehavior::default(), { + jungle_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - acacia_trapdoor => BlockBehavior::default(), { + acacia_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - cherry_trapdoor => BlockBehavior::default(), { + cherry_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - dark_oak_trapdoor => BlockBehavior::default(), { + dark_oak_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - mangrove_trapdoor => BlockBehavior::default(), { + mangrove_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - bamboo_trapdoor => BlockBehavior::default(), { + bamboo_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: 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(), { + stone_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + mossy_stone_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + cracked_stone_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + chiseled_stone_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + packed_mud => BlockBehavior::new().strength(1.0, 3.0), {}, + mud_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 3.0), {}, + infested_stone => BlockBehavior::new().strength(0.75, 0.75), {}, + infested_cobblestone => BlockBehavior::new().strength(1.0, 0.75), {}, + infested_stone_bricks => BlockBehavior::new().strength(0.75, 0.75), {}, + infested_mossy_stone_bricks => BlockBehavior::new().strength(0.75, 0.75), {}, + infested_cracked_stone_bricks => BlockBehavior::new().strength(0.75, 0.75), {}, + infested_chiseled_stone_bricks => BlockBehavior::new().strength(0.75, 0.75), {}, + brown_mushroom_block => BlockBehavior::new().strength(0.2, 0.2), { down: true, east: true, north: true, @@ -2798,7 +2798,7 @@ make_block_states! { up: true, west: true, }, - red_mushroom_block => BlockBehavior::default(), { + red_mushroom_block => BlockBehavior::new().strength(0.2, 0.2), { down: true, east: true, north: true, @@ -2806,7 +2806,7 @@ make_block_states! { up: true, west: true, }, - mushroom_stem => BlockBehavior::default(), { + mushroom_stem => BlockBehavior::new().strength(0.2, 0.2), { down: true, east: true, north: true, @@ -2814,45 +2814,45 @@ make_block_states! { up: true, west: true, }, - iron_bars => BlockBehavior::default(), { + iron_bars => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - chain => BlockBehavior::default(), { + chain => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), { axis: Axis::Y, waterlogged: false, }, - glass_pane => BlockBehavior::default(), { + glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - melon => BlockBehavior::default(), {}, - attached_pumpkin_stem => BlockBehavior::default(), { + melon => BlockBehavior::new().strength(1.0, 1.0), {}, + attached_pumpkin_stem => BlockBehavior::new(), { facing: FacingCardinal::North, }, - attached_melon_stem => BlockBehavior::default(), { + attached_melon_stem => BlockBehavior::new(), { facing: FacingCardinal::North, }, - pumpkin_stem => BlockBehavior::default(), { + pumpkin_stem => BlockBehavior::new(), { age: PumpkinStemAge::_0, }, - melon_stem => BlockBehavior::default(), { + melon_stem => BlockBehavior::new(), { age: MelonStemAge::_0, }, - vine => BlockBehavior::default(), { + vine => BlockBehavior::new().strength(0.2, 0.2), { east: false, north: false, south: false, up: false, west: false, }, - glow_lichen => BlockBehavior::default(), { + glow_lichen => BlockBehavior::new().strength(0.2, 0.2), { down: false, east: false, north: false, @@ -2861,97 +2861,97 @@ make_block_states! { waterlogged: false, west: false, }, - oak_fence_gate => BlockBehavior::default(), { + oak_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - brick_stairs => BlockBehavior::default(), { + brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - stone_brick_stairs => BlockBehavior::default(), { + stone_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - mud_brick_stairs => BlockBehavior::default(), { + mud_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - mycelium => BlockBehavior::default(), { + mycelium => BlockBehavior::new().strength(0.6, 0.6), { snowy: false, }, - lily_pad => BlockBehavior::default(), {}, - nether_bricks => BlockBehavior::default(), {}, - nether_brick_fence => BlockBehavior::default(), { + lily_pad => BlockBehavior::new(), {}, + nether_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + nether_brick_fence => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - nether_brick_stairs => BlockBehavior::default(), { + nether_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - nether_wart => BlockBehavior::default(), { + nether_wart => BlockBehavior::new(), { age: NetherWartAge::_0, }, - enchanting_table => BlockBehavior::default(), {}, - brewing_stand => BlockBehavior::default(), { + enchanting_table => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 1200.0), {}, + brewing_stand => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.5, 0.5), { has_bottle: false, has_bottle: false, has_bottle: false, }, - cauldron => BlockBehavior::default(), {}, - water_cauldron => BlockBehavior::default(), { + cauldron => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 2.0), {}, + water_cauldron => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 2.0), { level: WaterCauldronLevel::_1, }, - lava_cauldron => BlockBehavior::default(), {}, - powder_snow_cauldron => BlockBehavior::default(), { + lava_cauldron => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 2.0), {}, + powder_snow_cauldron => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 2.0), { level: PowderSnowCauldronLevel::_1, }, - end_portal => BlockBehavior::default(), {}, - end_portal_frame => BlockBehavior::default(), { + end_portal => BlockBehavior::new().strength(-1.0, 3600000.0), {}, + end_portal_frame => BlockBehavior::new().strength(-1.0, 3600000.0), { eye: false, facing: FacingCardinal::North, }, - end_stone => BlockBehavior::default(), {}, - dragon_egg => BlockBehavior::default(), {}, - redstone_lamp => BlockBehavior::default(), { + end_stone => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 9.0), {}, + dragon_egg => BlockBehavior::new().strength(3.0, 9.0), {}, + redstone_lamp => BlockBehavior::new().strength(0.3, 0.3), { lit: false, }, - cocoa => BlockBehavior::default(), { + cocoa => BlockBehavior::new().strength(0.2, 3.0), { age: CocoaAge::_0, facing: FacingCardinal::North, }, - sandstone_stairs => BlockBehavior::default(), { + sandstone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - emerald_ore => BlockBehavior::default(), {}, - deepslate_emerald_ore => BlockBehavior::default(), {}, - ender_chest => BlockBehavior::default(), { + emerald_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + deepslate_emerald_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.5, 3.0), {}, + ender_chest => BlockBehavior::new().requires_correct_tool_for_drops().strength(22.5, 600.0), { facing: FacingCardinal::North, waterlogged: false, }, - tripwire_hook => BlockBehavior::default(), { + tripwire_hook => BlockBehavior::new(), { attached: false, facing: FacingCardinal::North, powered: false, }, - tripwire => BlockBehavior::default(), { + tripwire => BlockBehavior::new(), { attached: false, disarmed: false, east: false, @@ -2960,31 +2960,31 @@ make_block_states! { south: false, west: false, }, - emerald_block => BlockBehavior::default(), {}, - spruce_stairs => BlockBehavior::default(), { + emerald_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {}, + spruce_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - birch_stairs => BlockBehavior::default(), { + birch_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - jungle_stairs => BlockBehavior::default(), { + jungle_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - command_block => BlockBehavior::default(), { + command_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(-1.0, 3600000.0), { conditional: false, facing: FacingCubic::North, }, - beacon => BlockBehavior::default(), {}, - cobblestone_wall => BlockBehavior::default(), { + beacon => BlockBehavior::new().strength(3.0, 3.0), {}, + cobblestone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -2992,7 +2992,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - mossy_cobblestone_wall => BlockBehavior::default(), { + mossy_cobblestone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -3000,802 +3000,802 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - flower_pot => BlockBehavior::default(), {}, - potted_torchflower => 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_cherry_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(), { + flower_pot => BlockBehavior::new(), {}, + potted_torchflower => BlockBehavior::new(), {}, + potted_oak_sapling => BlockBehavior::new(), {}, + potted_spruce_sapling => BlockBehavior::new(), {}, + potted_birch_sapling => BlockBehavior::new(), {}, + potted_jungle_sapling => BlockBehavior::new(), {}, + potted_acacia_sapling => BlockBehavior::new(), {}, + potted_cherry_sapling => BlockBehavior::new(), {}, + potted_dark_oak_sapling => BlockBehavior::new(), {}, + potted_mangrove_propagule => BlockBehavior::new(), {}, + potted_fern => BlockBehavior::new(), {}, + potted_dandelion => BlockBehavior::new(), {}, + potted_poppy => BlockBehavior::new(), {}, + potted_blue_orchid => BlockBehavior::new(), {}, + potted_allium => BlockBehavior::new(), {}, + potted_azure_bluet => BlockBehavior::new(), {}, + potted_red_tulip => BlockBehavior::new(), {}, + potted_orange_tulip => BlockBehavior::new(), {}, + potted_white_tulip => BlockBehavior::new(), {}, + potted_pink_tulip => BlockBehavior::new(), {}, + potted_oxeye_daisy => BlockBehavior::new(), {}, + potted_cornflower => BlockBehavior::new(), {}, + potted_lily_of_the_valley => BlockBehavior::new(), {}, + potted_wither_rose => BlockBehavior::new(), {}, + potted_red_mushroom => BlockBehavior::new(), {}, + potted_brown_mushroom => BlockBehavior::new(), {}, + potted_dead_bush => BlockBehavior::new(), {}, + potted_cactus => BlockBehavior::new(), {}, + carrots => BlockBehavior::new(), { age: CarrotsAge::_0, }, - potatoes => BlockBehavior::default(), { + potatoes => BlockBehavior::new(), { age: PotatoesAge::_0, }, - oak_button => BlockBehavior::default(), { + oak_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - spruce_button => BlockBehavior::default(), { + spruce_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - birch_button => BlockBehavior::default(), { + birch_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - jungle_button => BlockBehavior::default(), { + jungle_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - acacia_button => BlockBehavior::default(), { + acacia_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - cherry_button => BlockBehavior::default(), { + cherry_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - dark_oak_button => BlockBehavior::default(), { + dark_oak_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - mangrove_button => BlockBehavior::default(), { + mangrove_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - bamboo_button => BlockBehavior::default(), { + bamboo_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - skeleton_skull => BlockBehavior::default(), { + skeleton_skull => BlockBehavior::new().strength(1.0, 1.0), { rotation: SkeletonSkullRotation::_0, }, - skeleton_wall_skull => BlockBehavior::default(), { + skeleton_wall_skull => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - wither_skeleton_skull => BlockBehavior::default(), { + wither_skeleton_skull => BlockBehavior::new().strength(1.0, 1.0), { rotation: WitherSkeletonSkullRotation::_0, }, - wither_skeleton_wall_skull => BlockBehavior::default(), { + wither_skeleton_wall_skull => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - zombie_head => BlockBehavior::default(), { + zombie_head => BlockBehavior::new().strength(1.0, 1.0), { rotation: ZombieHeadRotation::_0, }, - zombie_wall_head => BlockBehavior::default(), { + zombie_wall_head => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - player_head => BlockBehavior::default(), { + player_head => BlockBehavior::new().strength(1.0, 1.0), { rotation: PlayerHeadRotation::_0, }, - player_wall_head => BlockBehavior::default(), { + player_wall_head => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - creeper_head => BlockBehavior::default(), { + creeper_head => BlockBehavior::new().strength(1.0, 1.0), { rotation: CreeperHeadRotation::_0, }, - creeper_wall_head => BlockBehavior::default(), { + creeper_wall_head => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - dragon_head => BlockBehavior::default(), { + dragon_head => BlockBehavior::new().strength(1.0, 1.0), { rotation: DragonHeadRotation::_0, }, - dragon_wall_head => BlockBehavior::default(), { + dragon_wall_head => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - piglin_head => BlockBehavior::default(), { + piglin_head => BlockBehavior::new().strength(1.0, 1.0), { rotation: PiglinHeadRotation::_0, }, - piglin_wall_head => BlockBehavior::default(), { + piglin_wall_head => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - anvil => BlockBehavior::default(), { + anvil => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 1200.0), { facing: FacingCardinal::North, }, - chipped_anvil => BlockBehavior::default(), { + chipped_anvil => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 1200.0), { facing: FacingCardinal::North, }, - damaged_anvil => BlockBehavior::default(), { + damaged_anvil => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 1200.0), { facing: FacingCardinal::North, }, - trapped_chest => BlockBehavior::default(), { + trapped_chest => BlockBehavior::new().strength(2.5, 2.5), { kind: ChestType::Single, facing: FacingCardinal::North, waterlogged: false, }, - light_weighted_pressure_plate => BlockBehavior::default(), { + light_weighted_pressure_plate => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.5, 0.5), { power: LightWeightedPressurePlatePower::_0, }, - heavy_weighted_pressure_plate => BlockBehavior::default(), { + heavy_weighted_pressure_plate => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.5, 0.5), { power: HeavyWeightedPressurePlatePower::_0, }, - comparator => BlockBehavior::default(), { + comparator => BlockBehavior::new(), { facing: FacingCardinal::North, mode: ComparatorType::Compare, powered: false, }, - daylight_detector => BlockBehavior::default(), { + daylight_detector => BlockBehavior::new().strength(0.2, 0.2), { inverted: false, power: DaylightDetectorPower::_0, }, - redstone_block => BlockBehavior::default(), {}, - nether_quartz_ore => BlockBehavior::default(), {}, - hopper => BlockBehavior::default(), { + redstone_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {}, + nether_quartz_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + hopper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 4.8), { enabled: true, facing: Facing::Down, }, - quartz_block => BlockBehavior::default(), {}, - chiseled_quartz_block => BlockBehavior::default(), {}, - quartz_pillar => BlockBehavior::default(), { + quartz_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + chiseled_quartz_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + quartz_pillar => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), { axis: Axis::Y, }, - quartz_stairs => BlockBehavior::default(), { + quartz_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - activator_rail => BlockBehavior::default(), { + activator_rail => BlockBehavior::new().strength(0.7, 0.7), { powered: false, shape: RailShape::NorthSouth, waterlogged: false, }, - dropper => BlockBehavior::default(), { + dropper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), { facing: 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(), { + white_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + orange_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + magenta_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + light_blue_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + yellow_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + lime_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + pink_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + gray_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + light_gray_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + cyan_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + purple_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + blue_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + brown_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + green_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + red_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + black_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + white_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - orange_stained_glass_pane => BlockBehavior::default(), { + orange_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - magenta_stained_glass_pane => BlockBehavior::default(), { + magenta_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - light_blue_stained_glass_pane => BlockBehavior::default(), { + light_blue_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - yellow_stained_glass_pane => BlockBehavior::default(), { + yellow_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - lime_stained_glass_pane => BlockBehavior::default(), { + lime_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - pink_stained_glass_pane => BlockBehavior::default(), { + pink_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - gray_stained_glass_pane => BlockBehavior::default(), { + gray_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - light_gray_stained_glass_pane => BlockBehavior::default(), { + light_gray_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - cyan_stained_glass_pane => BlockBehavior::default(), { + cyan_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - purple_stained_glass_pane => BlockBehavior::default(), { + purple_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - blue_stained_glass_pane => BlockBehavior::default(), { + blue_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - brown_stained_glass_pane => BlockBehavior::default(), { + brown_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - green_stained_glass_pane => BlockBehavior::default(), { + green_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - red_stained_glass_pane => BlockBehavior::default(), { + red_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - black_stained_glass_pane => BlockBehavior::default(), { + black_stained_glass_pane => BlockBehavior::new().strength(0.3, 0.3), { east: false, north: false, south: false, waterlogged: false, west: false, }, - acacia_stairs => BlockBehavior::default(), { + acacia_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - cherry_stairs => BlockBehavior::default(), { + cherry_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - dark_oak_stairs => BlockBehavior::default(), { + dark_oak_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - mangrove_stairs => BlockBehavior::default(), { + mangrove_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - bamboo_stairs => BlockBehavior::default(), { + bamboo_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - bamboo_mosaic_stairs => BlockBehavior::default(), { + bamboo_mosaic_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - slime_block => BlockBehavior::default(), {}, - barrier => BlockBehavior::default(), {}, - light => BlockBehavior::default(), { + slime_block => BlockBehavior::new().friction(0.8), {}, + barrier => BlockBehavior::new().strength(-1.0, 3600000.8), {}, + light => BlockBehavior::new().strength(-1.0, 3600000.8), { level: LightLevel::_15, waterlogged: false, }, - iron_trapdoor => BlockBehavior::default(), { + iron_trapdoor => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 5.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - prismarine => BlockBehavior::default(), {}, - prismarine_bricks => BlockBehavior::default(), {}, - dark_prismarine => BlockBehavior::default(), {}, - prismarine_stairs => BlockBehavior::default(), { + prismarine => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + prismarine_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + dark_prismarine => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + prismarine_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - prismarine_brick_stairs => BlockBehavior::default(), { + prismarine_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - dark_prismarine_stairs => BlockBehavior::default(), { + dark_prismarine_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - prismarine_slab => BlockBehavior::default(), { + prismarine_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - prismarine_brick_slab => BlockBehavior::default(), { + prismarine_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - dark_prismarine_slab => BlockBehavior::default(), { + dark_prismarine_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - sea_lantern => BlockBehavior::default(), {}, - hay_block => BlockBehavior::default(), { + sea_lantern => BlockBehavior::new().strength(0.3, 0.3), {}, + hay_block => BlockBehavior::new().strength(0.5, 0.5), { axis: 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(), { + white_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + orange_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + magenta_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + light_blue_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + yellow_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + lime_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + pink_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + gray_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + light_gray_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + cyan_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + purple_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + blue_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + brown_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + green_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + red_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + black_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + coal_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {}, + packed_ice => BlockBehavior::new().strength(0.5, 0.5).friction(0.98), {}, + sunflower => BlockBehavior::new(), { half: Half::Lower, }, - lilac => BlockBehavior::default(), { + lilac => BlockBehavior::new(), { half: Half::Lower, }, - rose_bush => BlockBehavior::default(), { + rose_bush => BlockBehavior::new(), { half: Half::Lower, }, - peony => BlockBehavior::default(), { + peony => BlockBehavior::new(), { half: Half::Lower, }, - tall_grass => BlockBehavior::default(), { + tall_grass => BlockBehavior::new(), { half: Half::Lower, }, - large_fern => BlockBehavior::default(), { + large_fern => BlockBehavior::new(), { half: Half::Lower, }, - white_banner => BlockBehavior::default(), { + white_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: WhiteBannerRotation::_0, }, - orange_banner => BlockBehavior::default(), { + orange_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: OrangeBannerRotation::_0, }, - magenta_banner => BlockBehavior::default(), { + magenta_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: MagentaBannerRotation::_0, }, - light_blue_banner => BlockBehavior::default(), { + light_blue_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: LightBlueBannerRotation::_0, }, - yellow_banner => BlockBehavior::default(), { + yellow_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: YellowBannerRotation::_0, }, - lime_banner => BlockBehavior::default(), { + lime_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: LimeBannerRotation::_0, }, - pink_banner => BlockBehavior::default(), { + pink_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: PinkBannerRotation::_0, }, - gray_banner => BlockBehavior::default(), { + gray_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: GrayBannerRotation::_0, }, - light_gray_banner => BlockBehavior::default(), { + light_gray_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: LightGrayBannerRotation::_0, }, - cyan_banner => BlockBehavior::default(), { + cyan_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: CyanBannerRotation::_0, }, - purple_banner => BlockBehavior::default(), { + purple_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: PurpleBannerRotation::_0, }, - blue_banner => BlockBehavior::default(), { + blue_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: BlueBannerRotation::_0, }, - brown_banner => BlockBehavior::default(), { + brown_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: BrownBannerRotation::_0, }, - green_banner => BlockBehavior::default(), { + green_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: GreenBannerRotation::_0, }, - red_banner => BlockBehavior::default(), { + red_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: RedBannerRotation::_0, }, - black_banner => BlockBehavior::default(), { + black_banner => BlockBehavior::new().strength(1.0, 1.0), { rotation: BlackBannerRotation::_0, }, - white_wall_banner => BlockBehavior::default(), { + white_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - orange_wall_banner => BlockBehavior::default(), { + orange_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - magenta_wall_banner => BlockBehavior::default(), { + magenta_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - light_blue_wall_banner => BlockBehavior::default(), { + light_blue_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - yellow_wall_banner => BlockBehavior::default(), { + yellow_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - lime_wall_banner => BlockBehavior::default(), { + lime_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - pink_wall_banner => BlockBehavior::default(), { + pink_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - gray_wall_banner => BlockBehavior::default(), { + gray_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - light_gray_wall_banner => BlockBehavior::default(), { + light_gray_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - cyan_wall_banner => BlockBehavior::default(), { + cyan_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - purple_wall_banner => BlockBehavior::default(), { + purple_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - blue_wall_banner => BlockBehavior::default(), { + blue_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - brown_wall_banner => BlockBehavior::default(), { + brown_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - green_wall_banner => BlockBehavior::default(), { + green_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - red_wall_banner => BlockBehavior::default(), { + red_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - black_wall_banner => BlockBehavior::default(), { + black_wall_banner => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, }, - red_sandstone => BlockBehavior::default(), {}, - chiseled_red_sandstone => BlockBehavior::default(), {}, - cut_red_sandstone => BlockBehavior::default(), {}, - red_sandstone_stairs => BlockBehavior::default(), { + red_sandstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + chiseled_red_sandstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + cut_red_sandstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + red_sandstone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - oak_slab => BlockBehavior::default(), { + oak_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - spruce_slab => BlockBehavior::default(), { + spruce_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - birch_slab => BlockBehavior::default(), { + birch_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - jungle_slab => BlockBehavior::default(), { + jungle_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - acacia_slab => BlockBehavior::default(), { + acacia_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - cherry_slab => BlockBehavior::default(), { + cherry_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - dark_oak_slab => BlockBehavior::default(), { + dark_oak_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - mangrove_slab => BlockBehavior::default(), { + mangrove_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - bamboo_slab => BlockBehavior::default(), { + bamboo_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - bamboo_mosaic_slab => BlockBehavior::default(), { + bamboo_mosaic_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - stone_slab => BlockBehavior::default(), { + stone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - smooth_stone_slab => BlockBehavior::default(), { + smooth_stone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - sandstone_slab => BlockBehavior::default(), { + sandstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - cut_sandstone_slab => BlockBehavior::default(), { + cut_sandstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - petrified_oak_slab => BlockBehavior::default(), { + petrified_oak_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - cobblestone_slab => BlockBehavior::default(), { + cobblestone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - brick_slab => BlockBehavior::default(), { + brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - stone_brick_slab => BlockBehavior::default(), { + stone_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - mud_brick_slab => BlockBehavior::default(), { + mud_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 3.0), { kind: Type::Bottom, waterlogged: false, }, - nether_brick_slab => BlockBehavior::default(), { + nether_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - quartz_slab => BlockBehavior::default(), { + quartz_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - red_sandstone_slab => BlockBehavior::default(), { + red_sandstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - cut_red_sandstone_slab => BlockBehavior::default(), { + cut_red_sandstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - purpur_slab => BlockBehavior::default(), { + purpur_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: 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(), { + smooth_stone => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + smooth_sandstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + smooth_quartz => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + smooth_red_sandstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + spruce_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - birch_fence_gate => BlockBehavior::default(), { + birch_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - jungle_fence_gate => BlockBehavior::default(), { + jungle_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - acacia_fence_gate => BlockBehavior::default(), { + acacia_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - cherry_fence_gate => BlockBehavior::default(), { + cherry_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - dark_oak_fence_gate => BlockBehavior::default(), { + dark_oak_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - mangrove_fence_gate => BlockBehavior::default(), { + mangrove_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - bamboo_fence_gate => BlockBehavior::default(), { + bamboo_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - spruce_fence => BlockBehavior::default(), { + spruce_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - birch_fence => BlockBehavior::default(), { + birch_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - jungle_fence => BlockBehavior::default(), { + jungle_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - acacia_fence => BlockBehavior::default(), { + acacia_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - cherry_fence => BlockBehavior::default(), { + cherry_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - dark_oak_fence => BlockBehavior::default(), { + dark_oak_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - mangrove_fence => BlockBehavior::default(), { + mangrove_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - bamboo_fence => BlockBehavior::default(), { + bamboo_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - spruce_door => BlockBehavior::default(), { + spruce_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - birch_door => BlockBehavior::default(), { + birch_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - jungle_door => BlockBehavior::default(), { + jungle_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - acacia_door => BlockBehavior::default(), { + acacia_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - cherry_door => BlockBehavior::default(), { + cherry_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - dark_oak_door => BlockBehavior::default(), { + dark_oak_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - mangrove_door => BlockBehavior::default(), { + mangrove_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - bamboo_door => BlockBehavior::default(), { + bamboo_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - end_rod => BlockBehavior::default(), { + end_rod => BlockBehavior::new(), { facing: FacingCubic::Up, }, - chorus_plant => BlockBehavior::default(), { + chorus_plant => BlockBehavior::new().strength(0.4, 0.4), { down: false, east: false, north: false, @@ -3803,467 +3803,467 @@ make_block_states! { up: false, west: false, }, - chorus_flower => BlockBehavior::default(), { + chorus_flower => BlockBehavior::new().strength(0.4, 0.4), { age: ChorusFlowerAge::_0, }, - purpur_block => BlockBehavior::default(), {}, - purpur_pillar => BlockBehavior::default(), { + purpur_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + purpur_pillar => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { axis: Axis::Y, }, - purpur_stairs => BlockBehavior::default(), { + purpur_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - end_stone_bricks => BlockBehavior::default(), {}, - torchflower_crop => BlockBehavior::default(), { + end_stone_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 9.0), {}, + torchflower_crop => BlockBehavior::new(), { age: TorchflowerCropAge::_0, }, - pitcher_crop => BlockBehavior::default(), { + pitcher_crop => BlockBehavior::new(), { age: _0_1_2_3_4::_0, half: UpperLower::Lower, }, - pitcher_plant => BlockBehavior::default(), { + pitcher_plant => BlockBehavior::new(), { half: Half::Lower, }, - beetroots => BlockBehavior::default(), { + beetroots => BlockBehavior::new(), { age: BeetrootsAge::_0, }, - dirt_path => BlockBehavior::default(), {}, - end_gateway => BlockBehavior::default(), {}, - repeating_command_block => BlockBehavior::default(), { + dirt_path => BlockBehavior::new().strength(0.65, 0.65), {}, + end_gateway => BlockBehavior::new().strength(-1.0, 3600000.0), {}, + repeating_command_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(-1.0, 3600000.0), { conditional: false, facing: FacingCubic::North, }, - chain_command_block => BlockBehavior::default(), { + chain_command_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(-1.0, 3600000.0), { conditional: false, facing: FacingCubic::North, }, - frosted_ice => BlockBehavior::default(), { + frosted_ice => BlockBehavior::new().strength(0.5, 0.5).friction(0.98), { age: FrostedIceAge::_0, }, - magma_block => BlockBehavior::default(), {}, - nether_wart_block => BlockBehavior::default(), {}, - red_nether_bricks => BlockBehavior::default(), {}, - bone_block => BlockBehavior::default(), { + magma_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.5, 0.5), {}, + nether_wart_block => BlockBehavior::new().strength(1.0, 1.0), {}, + red_nether_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + bone_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 2.0), { axis: Axis::Y, }, - structure_void => BlockBehavior::default(), {}, - observer => BlockBehavior::default(), { + structure_void => BlockBehavior::new(), {}, + observer => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), { facing: FacingCubic::South, powered: false, }, - shulker_box => BlockBehavior::default(), { + shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - white_shulker_box => BlockBehavior::default(), { + white_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - orange_shulker_box => BlockBehavior::default(), { + orange_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - magenta_shulker_box => BlockBehavior::default(), { + magenta_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - light_blue_shulker_box => BlockBehavior::default(), { + light_blue_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - yellow_shulker_box => BlockBehavior::default(), { + yellow_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - lime_shulker_box => BlockBehavior::default(), { + lime_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - pink_shulker_box => BlockBehavior::default(), { + pink_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - gray_shulker_box => BlockBehavior::default(), { + gray_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - light_gray_shulker_box => BlockBehavior::default(), { + light_gray_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - cyan_shulker_box => BlockBehavior::default(), { + cyan_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - purple_shulker_box => BlockBehavior::default(), { + purple_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - blue_shulker_box => BlockBehavior::default(), { + blue_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - brown_shulker_box => BlockBehavior::default(), { + brown_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - green_shulker_box => BlockBehavior::default(), { + green_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - red_shulker_box => BlockBehavior::default(), { + red_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - black_shulker_box => BlockBehavior::default(), { + black_shulker_box => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCubic::Up, }, - white_glazed_terracotta => BlockBehavior::default(), { + white_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - orange_glazed_terracotta => BlockBehavior::default(), { + orange_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - magenta_glazed_terracotta => BlockBehavior::default(), { + magenta_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - light_blue_glazed_terracotta => BlockBehavior::default(), { + light_blue_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - yellow_glazed_terracotta => BlockBehavior::default(), { + yellow_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - lime_glazed_terracotta => BlockBehavior::default(), { + lime_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - pink_glazed_terracotta => BlockBehavior::default(), { + pink_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - gray_glazed_terracotta => BlockBehavior::default(), { + gray_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - light_gray_glazed_terracotta => BlockBehavior::default(), { + light_gray_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - cyan_glazed_terracotta => BlockBehavior::default(), { + cyan_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - purple_glazed_terracotta => BlockBehavior::default(), { + purple_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - blue_glazed_terracotta => BlockBehavior::default(), { + blue_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - brown_glazed_terracotta => BlockBehavior::default(), { + brown_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - green_glazed_terracotta => BlockBehavior::default(), { + green_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - red_glazed_terracotta => BlockBehavior::default(), { + red_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: FacingCardinal::North, }, - black_glazed_terracotta => BlockBehavior::default(), { + black_glazed_terracotta => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.4, 1.4), { facing: 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(), { + white_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + orange_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + magenta_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + light_blue_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + yellow_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + lime_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + pink_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + gray_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + light_gray_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + cyan_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + purple_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + blue_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + brown_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + green_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + red_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + black_concrete => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.8, 1.8), {}, + white_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + orange_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + magenta_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + light_blue_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + yellow_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + lime_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + pink_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + gray_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + light_gray_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + cyan_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + purple_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + blue_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + brown_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + green_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + red_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + black_concrete_powder => BlockBehavior::new().strength(0.5, 0.5), {}, + kelp => BlockBehavior::new(), { age: KelpAge::_0, }, - kelp_plant => BlockBehavior::default(), {}, - dried_kelp_block => BlockBehavior::default(), {}, - turtle_egg => BlockBehavior::default(), { + kelp_plant => BlockBehavior::new(), {}, + dried_kelp_block => BlockBehavior::new().strength(0.5, 2.5), {}, + turtle_egg => BlockBehavior::new().strength(0.5, 0.5), { eggs: TurtleEggEggs::_1, hatch: TurtleEggHatch::_0, }, - sniffer_egg => BlockBehavior::default(), { - age: SnifferEggAge::_0, + sniffer_egg => BlockBehavior::new().strength(0.5, 0.5), { + hatch: SnifferEggHatch::_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(), { + dead_tube_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + dead_brain_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + dead_bubble_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + dead_fire_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + dead_horn_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + tube_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + brain_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + bubble_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + fire_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + horn_coral_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + dead_tube_coral => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - dead_brain_coral => BlockBehavior::default(), { + dead_brain_coral => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - dead_bubble_coral => BlockBehavior::default(), { + dead_bubble_coral => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - dead_fire_coral => BlockBehavior::default(), { + dead_fire_coral => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - dead_horn_coral => BlockBehavior::default(), { + dead_horn_coral => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - tube_coral => BlockBehavior::default(), { + tube_coral => BlockBehavior::new(), { waterlogged: true, }, - brain_coral => BlockBehavior::default(), { + brain_coral => BlockBehavior::new(), { waterlogged: true, }, - bubble_coral => BlockBehavior::default(), { + bubble_coral => BlockBehavior::new(), { waterlogged: true, }, - fire_coral => BlockBehavior::default(), { + fire_coral => BlockBehavior::new(), { waterlogged: true, }, - horn_coral => BlockBehavior::default(), { + horn_coral => BlockBehavior::new(), { waterlogged: true, }, - dead_tube_coral_fan => BlockBehavior::default(), { + dead_tube_coral_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - dead_brain_coral_fan => BlockBehavior::default(), { + dead_brain_coral_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - dead_bubble_coral_fan => BlockBehavior::default(), { + dead_bubble_coral_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - dead_fire_coral_fan => BlockBehavior::default(), { + dead_fire_coral_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - dead_horn_coral_fan => BlockBehavior::default(), { + dead_horn_coral_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { waterlogged: true, }, - tube_coral_fan => BlockBehavior::default(), { + tube_coral_fan => BlockBehavior::new(), { waterlogged: true, }, - brain_coral_fan => BlockBehavior::default(), { + brain_coral_fan => BlockBehavior::new(), { waterlogged: true, }, - bubble_coral_fan => BlockBehavior::default(), { + bubble_coral_fan => BlockBehavior::new(), { waterlogged: true, }, - fire_coral_fan => BlockBehavior::default(), { + fire_coral_fan => BlockBehavior::new(), { waterlogged: true, }, - horn_coral_fan => BlockBehavior::default(), { + horn_coral_fan => BlockBehavior::new(), { waterlogged: true, }, - dead_tube_coral_wall_fan => BlockBehavior::default(), { + dead_tube_coral_wall_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { facing: FacingCardinal::North, waterlogged: true, }, - dead_brain_coral_wall_fan => BlockBehavior::default(), { + dead_brain_coral_wall_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { facing: FacingCardinal::North, waterlogged: true, }, - dead_bubble_coral_wall_fan => BlockBehavior::default(), { + dead_bubble_coral_wall_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { facing: FacingCardinal::North, waterlogged: true, }, - dead_fire_coral_wall_fan => BlockBehavior::default(), { + dead_fire_coral_wall_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { facing: FacingCardinal::North, waterlogged: true, }, - dead_horn_coral_wall_fan => BlockBehavior::default(), { + dead_horn_coral_wall_fan => BlockBehavior::new().requires_correct_tool_for_drops(), { facing: FacingCardinal::North, waterlogged: true, }, - tube_coral_wall_fan => BlockBehavior::default(), { + tube_coral_wall_fan => BlockBehavior::new(), { facing: FacingCardinal::North, waterlogged: true, }, - brain_coral_wall_fan => BlockBehavior::default(), { + brain_coral_wall_fan => BlockBehavior::new(), { facing: FacingCardinal::North, waterlogged: true, }, - bubble_coral_wall_fan => BlockBehavior::default(), { + bubble_coral_wall_fan => BlockBehavior::new(), { facing: FacingCardinal::North, waterlogged: true, }, - fire_coral_wall_fan => BlockBehavior::default(), { + fire_coral_wall_fan => BlockBehavior::new(), { facing: FacingCardinal::North, waterlogged: true, }, - horn_coral_wall_fan => BlockBehavior::default(), { + horn_coral_wall_fan => BlockBehavior::new(), { facing: FacingCardinal::North, waterlogged: true, }, - sea_pickle => BlockBehavior::default(), { + sea_pickle => BlockBehavior::new(), { pickles: SeaPicklePickles::_1, waterlogged: true, }, - blue_ice => BlockBehavior::default(), {}, - conduit => BlockBehavior::default(), { + blue_ice => BlockBehavior::new().strength(2.8, 2.8).friction(0.989), {}, + conduit => BlockBehavior::new().strength(3.0, 3.0), { waterlogged: true, }, - bamboo_sapling => BlockBehavior::default(), {}, - bamboo => BlockBehavior::default(), { + bamboo_sapling => BlockBehavior::new().strength(1.0, 1.0), {}, + bamboo => BlockBehavior::new().strength(1.0, 1.0), { age: BambooAge::_0, leaves: Leaves::None, stage: BambooStage::_0, }, - potted_bamboo => BlockBehavior::default(), {}, - void_air => BlockBehavior::default(), {}, - cave_air => BlockBehavior::default(), {}, - bubble_column => BlockBehavior::default(), { + potted_bamboo => BlockBehavior::new(), {}, + void_air => BlockBehavior::new(), {}, + cave_air => BlockBehavior::new(), {}, + bubble_column => BlockBehavior::new(), { drag: true, }, - polished_granite_stairs => BlockBehavior::default(), { + polished_granite_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - smooth_red_sandstone_stairs => BlockBehavior::default(), { + smooth_red_sandstone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - mossy_stone_brick_stairs => BlockBehavior::default(), { + mossy_stone_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - polished_diorite_stairs => BlockBehavior::default(), { + polished_diorite_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - mossy_cobblestone_stairs => BlockBehavior::default(), { + mossy_cobblestone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - end_stone_brick_stairs => BlockBehavior::default(), { + end_stone_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 9.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - stone_stairs => BlockBehavior::default(), { + stone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - smooth_sandstone_stairs => BlockBehavior::default(), { + smooth_sandstone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - smooth_quartz_stairs => BlockBehavior::default(), { + smooth_quartz_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - granite_stairs => BlockBehavior::default(), { + granite_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - andesite_stairs => BlockBehavior::default(), { + andesite_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - red_nether_brick_stairs => BlockBehavior::default(), { + red_nether_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - polished_andesite_stairs => BlockBehavior::default(), { + polished_andesite_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - diorite_stairs => BlockBehavior::default(), { + diorite_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - polished_granite_slab => BlockBehavior::default(), { + polished_granite_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - smooth_red_sandstone_slab => BlockBehavior::default(), { + smooth_red_sandstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - mossy_stone_brick_slab => BlockBehavior::default(), { + mossy_stone_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - polished_diorite_slab => BlockBehavior::default(), { + polished_diorite_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - mossy_cobblestone_slab => BlockBehavior::default(), { + mossy_cobblestone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - end_stone_brick_slab => BlockBehavior::default(), { + end_stone_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 9.0), { kind: Type::Bottom, waterlogged: false, }, - smooth_sandstone_slab => BlockBehavior::default(), { + smooth_sandstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - smooth_quartz_slab => BlockBehavior::default(), { + smooth_quartz_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - granite_slab => BlockBehavior::default(), { + granite_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - andesite_slab => BlockBehavior::default(), { + andesite_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - red_nether_brick_slab => BlockBehavior::default(), { + red_nether_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - polished_andesite_slab => BlockBehavior::default(), { + polished_andesite_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - diorite_slab => BlockBehavior::default(), { + diorite_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - brick_wall => BlockBehavior::default(), { + brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4271,7 +4271,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - prismarine_wall => BlockBehavior::default(), { + prismarine_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4279,7 +4279,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - red_sandstone_wall => BlockBehavior::default(), { + red_sandstone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4287,7 +4287,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - mossy_stone_brick_wall => BlockBehavior::default(), { + mossy_stone_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4295,7 +4295,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - granite_wall => BlockBehavior::default(), { + granite_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4303,7 +4303,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - stone_brick_wall => BlockBehavior::default(), { + stone_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4311,7 +4311,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - mud_brick_wall => BlockBehavior::default(), { + mud_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 3.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4319,7 +4319,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - nether_brick_wall => BlockBehavior::default(), { + nether_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4327,7 +4327,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - andesite_wall => BlockBehavior::default(), { + andesite_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4335,7 +4335,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - red_nether_brick_wall => BlockBehavior::default(), { + red_nether_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4343,7 +4343,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - sandstone_wall => BlockBehavior::default(), { + sandstone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4351,7 +4351,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - end_stone_brick_wall => BlockBehavior::default(), { + end_stone_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 9.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4359,7 +4359,7 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - diorite_wall => BlockBehavior::default(), { + diorite_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4367,259 +4367,259 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - scaffolding => BlockBehavior::default(), { + scaffolding => BlockBehavior::new(), { bottom: false, distance: ScaffoldingDistance::_7, waterlogged: false, }, - loom => BlockBehavior::default(), { + loom => BlockBehavior::new().strength(2.5, 2.5), { facing: FacingCardinal::North, }, - barrel => BlockBehavior::default(), { + barrel => BlockBehavior::new().strength(2.5, 2.5), { facing: FacingCubic::North, open: false, }, - smoker => BlockBehavior::default(), { + smoker => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), { facing: FacingCardinal::North, lit: false, }, - blast_furnace => BlockBehavior::default(), { + blast_furnace => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), { facing: FacingCardinal::North, lit: false, }, - cartography_table => BlockBehavior::default(), {}, - fletching_table => BlockBehavior::default(), {}, - grindstone => BlockBehavior::default(), { + cartography_table => BlockBehavior::new().strength(2.5, 2.5), {}, + fletching_table => BlockBehavior::new().strength(2.5, 2.5), {}, + grindstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { face: Face::Wall, facing: FacingCardinal::North, }, - lectern => BlockBehavior::default(), { + lectern => BlockBehavior::new().strength(2.5, 2.5), { facing: FacingCardinal::North, has_book: false, powered: false, }, - smithing_table => BlockBehavior::default(), {}, - stonecutter => BlockBehavior::default(), { + smithing_table => BlockBehavior::new().strength(2.5, 2.5), {}, + stonecutter => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), { facing: FacingCardinal::North, }, - bell => BlockBehavior::default(), { + bell => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 5.0), { attachment: Attachment::Floor, facing: FacingCardinal::North, powered: false, }, - lantern => BlockBehavior::default(), { + lantern => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), { hanging: false, waterlogged: false, }, - soul_lantern => BlockBehavior::default(), { + soul_lantern => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), { hanging: false, waterlogged: false, }, - campfire => BlockBehavior::default(), { + campfire => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCardinal::North, lit: true, signal_fire: false, waterlogged: false, }, - soul_campfire => BlockBehavior::default(), { + soul_campfire => BlockBehavior::new().strength(2.0, 2.0), { facing: FacingCardinal::North, lit: true, signal_fire: false, waterlogged: false, }, - sweet_berry_bush => BlockBehavior::default(), { + sweet_berry_bush => BlockBehavior::new(), { age: SweetBerryBushAge::_0, }, - warped_stem => BlockBehavior::default(), { + warped_stem => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_warped_stem => BlockBehavior::default(), { + stripped_warped_stem => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - warped_hyphae => BlockBehavior::default(), { + warped_hyphae => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_warped_hyphae => BlockBehavior::default(), { + stripped_warped_hyphae => BlockBehavior::new().strength(2.0, 2.0), { axis: 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(), { + warped_nylium => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.4, 0.4), {}, + warped_fungus => BlockBehavior::new(), {}, + warped_wart_block => BlockBehavior::new().strength(1.0, 1.0), {}, + warped_roots => BlockBehavior::new(), {}, + nether_sprouts => BlockBehavior::new(), {}, + crimson_stem => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_crimson_stem => BlockBehavior::default(), { + stripped_crimson_stem => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - crimson_hyphae => BlockBehavior::default(), { + crimson_hyphae => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - stripped_crimson_hyphae => BlockBehavior::default(), { + stripped_crimson_hyphae => BlockBehavior::new().strength(2.0, 2.0), { axis: Axis::Y, }, - crimson_nylium => BlockBehavior::default(), {}, - crimson_fungus => BlockBehavior::default(), {}, - shroomlight => BlockBehavior::default(), {}, - weeping_vines => BlockBehavior::default(), { + crimson_nylium => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.4, 0.4), {}, + crimson_fungus => BlockBehavior::new(), {}, + shroomlight => BlockBehavior::new().strength(1.0, 1.0), {}, + weeping_vines => BlockBehavior::new(), { age: WeepingVinesAge::_0, }, - weeping_vines_plant => BlockBehavior::default(), {}, - twisting_vines => BlockBehavior::default(), { + weeping_vines_plant => BlockBehavior::new(), {}, + twisting_vines => BlockBehavior::new(), { age: TwistingVinesAge::_0, }, - twisting_vines_plant => BlockBehavior::default(), {}, - crimson_roots => BlockBehavior::default(), {}, - crimson_planks => BlockBehavior::default(), {}, - warped_planks => BlockBehavior::default(), {}, - crimson_slab => BlockBehavior::default(), { + twisting_vines_plant => BlockBehavior::new(), {}, + crimson_roots => BlockBehavior::new(), {}, + crimson_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + warped_planks => BlockBehavior::new().strength(2.0, 3.0), {}, + crimson_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - warped_slab => BlockBehavior::default(), { + warped_slab => BlockBehavior::new().strength(2.0, 3.0), { kind: Type::Bottom, waterlogged: false, }, - crimson_pressure_plate => BlockBehavior::default(), { + crimson_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - warped_pressure_plate => BlockBehavior::default(), { + warped_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), { powered: false, }, - crimson_fence => BlockBehavior::default(), { + crimson_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - warped_fence => BlockBehavior::default(), { + warped_fence => BlockBehavior::new().strength(2.0, 3.0), { east: false, north: false, south: false, waterlogged: false, west: false, }, - crimson_trapdoor => BlockBehavior::default(), { + crimson_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - warped_trapdoor => BlockBehavior::default(), { + warped_trapdoor => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, open: false, powered: false, waterlogged: false, }, - crimson_fence_gate => BlockBehavior::default(), { + crimson_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - warped_fence_gate => BlockBehavior::default(), { + warped_fence_gate => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, in_wall: false, open: false, powered: false, }, - crimson_stairs => BlockBehavior::default(), { + crimson_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - warped_stairs => BlockBehavior::default(), { + warped_stairs => BlockBehavior::new().strength(2.0, 3.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - crimson_button => BlockBehavior::default(), { + crimson_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - warped_button => BlockBehavior::default(), { + warped_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - crimson_door => BlockBehavior::default(), { + crimson_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - warped_door => BlockBehavior::default(), { + warped_door => BlockBehavior::new().strength(3.0, 3.0), { facing: FacingCardinal::North, half: Half::Lower, hinge: Hinge::Left, open: false, powered: false, }, - crimson_sign => BlockBehavior::default(), { + crimson_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: CrimsonSignRotation::_0, waterlogged: false, }, - warped_sign => BlockBehavior::default(), { + warped_sign => BlockBehavior::new().strength(1.0, 1.0), { rotation: WarpedSignRotation::_0, waterlogged: false, }, - crimson_wall_sign => BlockBehavior::default(), { + crimson_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - warped_wall_sign => BlockBehavior::default(), { + warped_wall_sign => BlockBehavior::new().strength(1.0, 1.0), { facing: FacingCardinal::North, waterlogged: false, }, - structure_block => BlockBehavior::default(), { + structure_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(-1.0, 3600000.0), { mode: Mode::Load, }, - jigsaw => BlockBehavior::default(), { + jigsaw => BlockBehavior::new().requires_correct_tool_for_drops().strength(-1.0, 3600000.0), { orientation: Orientation::NorthUp, }, - composter => BlockBehavior::default(), { + composter => BlockBehavior::new().strength(0.6, 0.6), { level: ComposterLevel::_0, }, - target => BlockBehavior::default(), { + target => BlockBehavior::new().strength(0.5, 0.5), { power: TargetOutputPower::_0, }, - bee_nest => BlockBehavior::default(), { + bee_nest => BlockBehavior::new().strength(0.3, 0.3), { facing: FacingCardinal::North, honey_level: BeeNestHoneyLevel::_0, }, - beehive => BlockBehavior::default(), { + beehive => BlockBehavior::new().strength(0.6, 0.6), { facing: FacingCardinal::North, honey_level: 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(), { + honey_block => BlockBehavior::new(), {}, + honeycomb_block => BlockBehavior::new().strength(0.6, 0.6), {}, + netherite_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(50.0, 1200.0), {}, + ancient_debris => BlockBehavior::new().requires_correct_tool_for_drops().strength(30.0, 1200.0), {}, + crying_obsidian => BlockBehavior::new().requires_correct_tool_for_drops().strength(50.0, 1200.0), {}, + respawn_anchor => BlockBehavior::new().requires_correct_tool_for_drops().strength(50.0, 1200.0), { charges: 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(), { + potted_crimson_fungus => BlockBehavior::new(), {}, + potted_warped_fungus => BlockBehavior::new(), {}, + potted_crimson_roots => BlockBehavior::new(), {}, + potted_warped_roots => BlockBehavior::new(), {}, + lodestone => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 3.5), {}, + blackstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + blackstone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - blackstone_wall => BlockBehavior::default(), { + blackstone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4627,25 +4627,25 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - blackstone_slab => BlockBehavior::default(), { + blackstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: 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(), { + polished_blackstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + polished_blackstone_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + cracked_polished_blackstone_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + chiseled_polished_blackstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + polished_blackstone_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - polished_blackstone_brick_stairs => BlockBehavior::default(), { + polished_blackstone_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - polished_blackstone_brick_wall => BlockBehavior::default(), { + polished_blackstone_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4653,26 +4653,26 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - gilded_blackstone => BlockBehavior::default(), {}, - polished_blackstone_stairs => BlockBehavior::default(), { + gilded_blackstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + polished_blackstone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - polished_blackstone_slab => BlockBehavior::default(), { + polished_blackstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - polished_blackstone_pressure_plate => BlockBehavior::default(), { + polished_blackstone_pressure_plate => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.5, 0.5), { powered: false, }, - polished_blackstone_button => BlockBehavior::default(), { + polished_blackstone_button => BlockBehavior::new().strength(0.5, 0.5), { face: Face::Wall, facing: FacingCardinal::North, powered: false, }, - polished_blackstone_wall => BlockBehavior::default(), { + polished_blackstone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -4680,180 +4680,180 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - chiseled_nether_bricks => BlockBehavior::default(), {}, - cracked_nether_bricks => BlockBehavior::default(), {}, - quartz_bricks => BlockBehavior::default(), {}, - candle => BlockBehavior::default(), { + chiseled_nether_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + cracked_nether_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {}, + quartz_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {}, + candle => BlockBehavior::new().strength(0.1, 0.1), { candles: CandleCandles::_1, lit: false, waterlogged: false, }, - white_candle => BlockBehavior::default(), { + white_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: WhiteCandleCandles::_1, lit: false, waterlogged: false, }, - orange_candle => BlockBehavior::default(), { + orange_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: OrangeCandleCandles::_1, lit: false, waterlogged: false, }, - magenta_candle => BlockBehavior::default(), { + magenta_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: MagentaCandleCandles::_1, lit: false, waterlogged: false, }, - light_blue_candle => BlockBehavior::default(), { + light_blue_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: LightBlueCandleCandles::_1, lit: false, waterlogged: false, }, - yellow_candle => BlockBehavior::default(), { + yellow_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: YellowCandleCandles::_1, lit: false, waterlogged: false, }, - lime_candle => BlockBehavior::default(), { + lime_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: LimeCandleCandles::_1, lit: false, waterlogged: false, }, - pink_candle => BlockBehavior::default(), { + pink_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: PinkCandleCandles::_1, lit: false, waterlogged: false, }, - gray_candle => BlockBehavior::default(), { + gray_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: GrayCandleCandles::_1, lit: false, waterlogged: false, }, - light_gray_candle => BlockBehavior::default(), { + light_gray_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: LightGrayCandleCandles::_1, lit: false, waterlogged: false, }, - cyan_candle => BlockBehavior::default(), { + cyan_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: CyanCandleCandles::_1, lit: false, waterlogged: false, }, - purple_candle => BlockBehavior::default(), { + purple_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: PurpleCandleCandles::_1, lit: false, waterlogged: false, }, - blue_candle => BlockBehavior::default(), { + blue_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: BlueCandleCandles::_1, lit: false, waterlogged: false, }, - brown_candle => BlockBehavior::default(), { + brown_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: BrownCandleCandles::_1, lit: false, waterlogged: false, }, - green_candle => BlockBehavior::default(), { + green_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: GreenCandleCandles::_1, lit: false, waterlogged: false, }, - red_candle => BlockBehavior::default(), { + red_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: RedCandleCandles::_1, lit: false, waterlogged: false, }, - black_candle => BlockBehavior::default(), { + black_candle => BlockBehavior::new().strength(0.1, 0.1), { candles: BlackCandleCandles::_1, lit: false, waterlogged: false, }, - candle_cake => BlockBehavior::default(), { + candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - white_candle_cake => BlockBehavior::default(), { + white_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - orange_candle_cake => BlockBehavior::default(), { + orange_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - magenta_candle_cake => BlockBehavior::default(), { + magenta_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - light_blue_candle_cake => BlockBehavior::default(), { + light_blue_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - yellow_candle_cake => BlockBehavior::default(), { + yellow_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - lime_candle_cake => BlockBehavior::default(), { + lime_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - pink_candle_cake => BlockBehavior::default(), { + pink_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - gray_candle_cake => BlockBehavior::default(), { + gray_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - light_gray_candle_cake => BlockBehavior::default(), { + light_gray_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - cyan_candle_cake => BlockBehavior::default(), { + cyan_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - purple_candle_cake => BlockBehavior::default(), { + purple_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - blue_candle_cake => BlockBehavior::default(), { + blue_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - brown_candle_cake => BlockBehavior::default(), { + brown_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - green_candle_cake => BlockBehavior::default(), { + green_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - red_candle_cake => BlockBehavior::default(), { + red_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - black_candle_cake => BlockBehavior::default(), { + black_candle_cake => BlockBehavior::new().strength(0.5, 0.5), { lit: false, }, - amethyst_block => BlockBehavior::default(), {}, - budding_amethyst => BlockBehavior::default(), {}, - amethyst_cluster => BlockBehavior::default(), { + amethyst_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 1.5), {}, + budding_amethyst => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 1.5), {}, + amethyst_cluster => BlockBehavior::new().strength(1.5, 1.5), { facing: FacingCubic::Up, waterlogged: false, }, - large_amethyst_bud => BlockBehavior::default(), { + large_amethyst_bud => BlockBehavior::new().strength(1.5, 1.5), { facing: FacingCubic::Up, waterlogged: false, }, - medium_amethyst_bud => BlockBehavior::default(), { + medium_amethyst_bud => BlockBehavior::new().strength(1.5, 1.5), { facing: FacingCubic::Up, waterlogged: false, }, - small_amethyst_bud => BlockBehavior::default(), { + small_amethyst_bud => BlockBehavior::new().strength(1.5, 1.5), { facing: FacingCubic::Up, waterlogged: false, }, - tuff => BlockBehavior::default(), {}, - calcite => BlockBehavior::default(), {}, - tinted_glass => BlockBehavior::default(), {}, - powder_snow => BlockBehavior::default(), {}, - sculk_sensor => BlockBehavior::default(), { + tuff => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {}, + calcite => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.75, 0.75), {}, + tinted_glass => BlockBehavior::new().strength(0.3, 0.3), {}, + powder_snow => BlockBehavior::new().strength(0.25, 0.25), {}, + sculk_sensor => BlockBehavior::new().strength(1.5, 1.5), { power: SculkSensorPower::_0, sculk_sensor_phase: Phase::Inactive, waterlogged: false, }, - calibrated_sculk_sensor => BlockBehavior::default(), { + calibrated_sculk_sensor => BlockBehavior::new().strength(1.5, 1.5), { facing: FacingCardinal::North, power: CalibratedSculkSensorPower::_0, sculk_sensor_phase: Phase::Inactive, waterlogged: false, }, - sculk => BlockBehavior::default(), {}, - sculk_vein => BlockBehavior::default(), { + sculk => BlockBehavior::new().strength(0.2, 0.2), {}, + sculk_vein => BlockBehavior::new().strength(0.2, 0.2), { down: false, east: false, north: false, @@ -4862,173 +4862,173 @@ make_block_states! { waterlogged: false, west: false, }, - sculk_catalyst => BlockBehavior::default(), { + sculk_catalyst => BlockBehavior::new().strength(3.0, 3.0), { bloom: false, }, - sculk_shrieker => BlockBehavior::default(), { + sculk_shrieker => BlockBehavior::new().strength(3.0, 3.0), { can_summon: 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(), { + oxidized_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + weathered_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + exposed_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + copper_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + copper_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 3.0), {}, + deepslate_copper_ore => BlockBehavior::new().requires_correct_tool_for_drops().strength(4.5, 3.0), {}, + oxidized_cut_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + weathered_cut_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + exposed_cut_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + cut_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + oxidized_cut_copper_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - weathered_cut_copper_stairs => BlockBehavior::default(), { + weathered_cut_copper_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - exposed_cut_copper_stairs => BlockBehavior::default(), { + exposed_cut_copper_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - cut_copper_stairs => BlockBehavior::default(), { + cut_copper_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - oxidized_cut_copper_slab => BlockBehavior::default(), { + oxidized_cut_copper_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - weathered_cut_copper_slab => BlockBehavior::default(), { + weathered_cut_copper_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - exposed_cut_copper_slab => BlockBehavior::default(), { + exposed_cut_copper_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - cut_copper_slab => BlockBehavior::default(), { + cut_copper_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { kind: 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(), { + waxed_copper_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + waxed_weathered_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + waxed_exposed_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + waxed_oxidized_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + waxed_oxidized_cut_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + waxed_weathered_cut_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + waxed_exposed_cut_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + waxed_cut_copper => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), {}, + waxed_oxidized_cut_copper_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - waxed_weathered_cut_copper_stairs => BlockBehavior::default(), { + waxed_weathered_cut_copper_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - waxed_exposed_cut_copper_stairs => BlockBehavior::default(), { + waxed_exposed_cut_copper_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - waxed_cut_copper_stairs => BlockBehavior::default(), { + waxed_cut_copper_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - waxed_oxidized_cut_copper_slab => BlockBehavior::default(), { + waxed_oxidized_cut_copper_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - waxed_weathered_cut_copper_slab => BlockBehavior::default(), { + waxed_weathered_cut_copper_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - waxed_exposed_cut_copper_slab => BlockBehavior::default(), { + waxed_exposed_cut_copper_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - waxed_cut_copper_slab => BlockBehavior::default(), { + waxed_cut_copper_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { kind: Type::Bottom, waterlogged: false, }, - lightning_rod => BlockBehavior::default(), { + lightning_rod => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { facing: FacingCubic::Up, powered: false, waterlogged: false, }, - pointed_dripstone => BlockBehavior::default(), { + pointed_dripstone => BlockBehavior::new().strength(1.5, 3.0), { thickness: Thickness::Tip, vertical_direction: TipDirection::Up, waterlogged: false, }, - dripstone_block => BlockBehavior::default(), {}, - cave_vines => BlockBehavior::default(), { + dripstone_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 1.0), {}, + cave_vines => BlockBehavior::new(), { age: CaveVinesAge::_0, berries: false, }, - cave_vines_plant => BlockBehavior::default(), { + cave_vines_plant => BlockBehavior::new(), { berries: false, }, - spore_blossom => BlockBehavior::default(), {}, - azalea => BlockBehavior::default(), {}, - flowering_azalea => BlockBehavior::default(), {}, - moss_carpet => BlockBehavior::default(), {}, - pink_petals => BlockBehavior::default(), { + spore_blossom => BlockBehavior::new(), {}, + azalea => BlockBehavior::new(), {}, + flowering_azalea => BlockBehavior::new(), {}, + moss_carpet => BlockBehavior::new().strength(0.1, 0.1), {}, + pink_petals => BlockBehavior::new(), { facing: FacingCardinal::North, flower_amount: PinkPetalsAmount::_1, }, - moss_block => BlockBehavior::default(), {}, - big_dripleaf => BlockBehavior::default(), { + moss_block => BlockBehavior::new().strength(0.1, 0.1), {}, + big_dripleaf => BlockBehavior::new().strength(0.1, 0.1), { facing: FacingCardinal::North, tilt: Tilt::None, waterlogged: false, }, - big_dripleaf_stem => BlockBehavior::default(), { + big_dripleaf_stem => BlockBehavior::new().strength(0.1, 0.1), { facing: FacingCardinal::North, waterlogged: false, }, - small_dripleaf => BlockBehavior::default(), { + small_dripleaf => BlockBehavior::new(), { facing: FacingCardinal::North, half: Half::Lower, waterlogged: false, }, - hanging_roots => BlockBehavior::default(), { + hanging_roots => BlockBehavior::new(), { waterlogged: false, }, - rooted_dirt => BlockBehavior::default(), {}, - mud => BlockBehavior::default(), {}, - deepslate => BlockBehavior::default(), { + rooted_dirt => BlockBehavior::new().strength(0.5, 0.5), {}, + mud => BlockBehavior::new().strength(0.5, 0.5), {}, + deepslate => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 6.0), { axis: Axis::Y, }, - cobbled_deepslate => BlockBehavior::default(), {}, - cobbled_deepslate_stairs => BlockBehavior::default(), { + cobbled_deepslate => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {}, + cobbled_deepslate_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - cobbled_deepslate_slab => BlockBehavior::default(), { + cobbled_deepslate_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - cobbled_deepslate_wall => BlockBehavior::default(), { + cobbled_deepslate_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -5036,18 +5036,18 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - polished_deepslate => BlockBehavior::default(), {}, - polished_deepslate_stairs => BlockBehavior::default(), { + polished_deepslate => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {}, + polished_deepslate_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - polished_deepslate_slab => BlockBehavior::default(), { + polished_deepslate_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - polished_deepslate_wall => BlockBehavior::default(), { + polished_deepslate_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -5055,18 +5055,18 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - deepslate_tiles => BlockBehavior::default(), {}, - deepslate_tile_stairs => BlockBehavior::default(), { + deepslate_tiles => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {}, + deepslate_tile_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - deepslate_tile_slab => BlockBehavior::default(), { + deepslate_tile_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - deepslate_tile_wall => BlockBehavior::default(), { + deepslate_tile_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -5074,18 +5074,18 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - deepslate_bricks => BlockBehavior::default(), {}, - deepslate_brick_stairs => BlockBehavior::default(), { + deepslate_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {}, + deepslate_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { facing: FacingCardinal::North, half: TopBottom::Bottom, shape: StairShape::Straight, waterlogged: false, }, - deepslate_brick_slab => BlockBehavior::default(), { + deepslate_brick_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { kind: Type::Bottom, waterlogged: false, }, - deepslate_brick_wall => BlockBehavior::default(), { + deepslate_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), { east: EastWall::None, north: NorthWall::None, south: SouthWall::None, @@ -5093,30 +5093,30 @@ make_block_states! { waterlogged: false, west: WestWall::None, }, - chiseled_deepslate => BlockBehavior::default(), {}, - cracked_deepslate_bricks => BlockBehavior::default(), {}, - cracked_deepslate_tiles => BlockBehavior::default(), {}, - infested_deepslate => BlockBehavior::default(), { + chiseled_deepslate => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {}, + cracked_deepslate_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {}, + cracked_deepslate_tiles => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {}, + infested_deepslate => BlockBehavior::new().strength(1.5, 0.75), { axis: CacheSize::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(), { + smooth_basalt => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {}, + raw_iron_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {}, + raw_copper_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {}, + raw_gold_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {}, + potted_azalea_bush => BlockBehavior::new(), {}, + potted_flowering_azalea_bush => BlockBehavior::new(), {}, + ochre_froglight => BlockBehavior::new().strength(0.3, 0.3), { axis: Axis::Y, }, - verdant_froglight => BlockBehavior::default(), { + verdant_froglight => BlockBehavior::new().strength(0.3, 0.3), { axis: Axis::Y, }, - pearlescent_froglight => BlockBehavior::default(), { + pearlescent_froglight => BlockBehavior::new().strength(0.3, 0.3), { axis: Axis::Y, }, - frogspawn => BlockBehavior::default(), {}, - reinforced_deepslate => BlockBehavior::default(), {}, - decorated_pot => BlockBehavior::default(), { + frogspawn => BlockBehavior::new(), {}, + reinforced_deepslate => BlockBehavior::new().strength(55.0, 1200.0), {}, + decorated_pot => BlockBehavior::new(), { cracked: false, facing: FacingCardinal::North, waterlogged: false, diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index 43099db5..ef0041f1 100755 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -24,6 +24,9 @@ pub trait Block: Debug + Any { /// Convert the block to a block state. This is lossless, as the block /// contains all the state data. fn as_block_state(&self) -> BlockState; + /// Convert the block to an [`azalea_registry::Block`]. This is lossy, as + /// `azalea_registry::Block` doesn't contain any state data. + fn as_registry_block(&self) -> azalea_registry::Block; } impl dyn Block { pub fn downcast_ref(&self) -> Option<&T> { @@ -45,19 +48,14 @@ pub struct BlockState { impl BlockState { pub const AIR: BlockState = BlockState { id: 0 }; - /// Transmutes a u32 to a block state. - /// - /// # Safety - /// The `state_id` should be a valid block state. - #[inline] - pub unsafe fn from_u32_unchecked(state_id: u32) -> Self { - BlockState { id: state_id } - } - #[inline] pub fn is_valid_state(state_id: u32) -> bool { state_id <= Self::max_state() } + + pub fn is_air(&self) -> bool { + self == &Self::AIR + } } impl TryFrom for BlockState { @@ -66,7 +64,7 @@ impl TryFrom for BlockState { /// 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_unchecked(state_id) }) + Ok(BlockState { id: state_id }) } else { Err(()) } @@ -98,6 +96,68 @@ impl std::fmt::Debug for BlockState { } } +#[derive(Clone, Debug)] +pub struct FluidState { + pub fluid: azalea_registry::Fluid, + pub height: u8, +} + +impl Default for FluidState { + fn default() -> Self { + Self { + fluid: azalea_registry::Fluid::Empty, + height: 0, + } + } +} + +impl From for FluidState { + fn from(state: BlockState) -> Self { + if state.waterlogged() { + Self { + fluid: azalea_registry::Fluid::Water, + height: 15, + } + } else { + let block = Box::::from(state); + if let Some(water) = block.downcast_ref::() { + Self { + fluid: azalea_registry::Fluid::Water, + height: water.level as u8, + } + } else if let Some(lava) = block.downcast_ref::() { + Self { + fluid: azalea_registry::Fluid::Lava, + height: lava.level as u8, + } + } else { + Self { + fluid: azalea_registry::Fluid::Empty, + height: 0, + } + } + } + } +} + +impl From for BlockState { + fn from(state: FluidState) -> Self { + match state.fluid { + azalea_registry::Fluid::Empty => BlockState::AIR, + azalea_registry::Fluid::Water | azalea_registry::Fluid::FlowingWater => { + BlockState::from(crate::blocks::Water { + level: crate::properties::WaterLevel::from(state.height as u32), + }) + } + azalea_registry::Fluid::Lava | azalea_registry::Fluid::FlowingLava => { + BlockState::from(crate::blocks::Lava { + level: crate::properties::LavaLevel::from(state.height as u32), + }) + } + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/azalea-buf/src/read.rs b/azalea-buf/src/read.rs index 00693384..7c996f20 100755 --- a/azalea-buf/src/read.rs +++ b/azalea-buf/src/read.rs @@ -96,17 +96,10 @@ fn read_utf_with_len(buf: &mut Cursor<&[u8]>, max_length: u32) -> Result Result { -// let mut buffer = [0]; -// let mut ans = 0; -// for i in 0..5 { -// reader.read_exact(&mut buffer).await?; -// ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); -// if buffer[0] & 0b1000_0000 == 0 { -// break; -// } -// } -// Ok(ans) +// ) -> Result { let mut buffer = [0]; let mut ans = 0; for i +// in 0..5 { reader.read_exact(&mut buffer).await?; ans |= ((buffer[0] & +// 0b0111_1111) as i32) << (7 * i); if buffer[0] & 0b1000_0000 == 0 { break; } +// } Ok(ans) // } pub trait McBufReadable diff --git a/azalea-client/Cargo.toml b/azalea-client/Cargo.toml index fb96fccb..9c4bcac6 100644 --- a/azalea-client/Cargo.toml +++ b/azalea-client/Cargo.toml @@ -38,6 +38,7 @@ regex = "1.9.1" thiserror = "^1.0.43" tokio = { version = "^1.29.1", features = ["sync"] } uuid = "^1.4.0" +azalea-entity = { version = "0.1.0", path = "../azalea-entity" } [features] default = ["log"] diff --git a/azalea-client/src/account.rs b/azalea-client/src/account.rs index 2d1b766c..0e67a79a 100755 --- a/azalea-client/src/account.rs +++ b/azalea-client/src/account.rs @@ -187,7 +187,10 @@ impl Account { *access_token_mutex.lock() = new_access_token; let AccountOpts::MicrosoftWithAccessToken { msa: new_msa } = - new_account.account_opts else { unreachable!() }; + new_account.account_opts + else { + unreachable!() + }; *msa.lock() = new_msa.lock().clone(); Ok(()) diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 725cd9f3..0b1fccc1 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -8,6 +8,7 @@ use crate::{ death_event, handle_send_packet_event, update_in_loaded_chunk, GameProfileComponent, LocalPlayer, PhysicsState, SendPacketEvent, }, + mining::{self, MinePlugin}, movement::{LastSentLookDirection, PlayerMovePlugin}, packet_handling::{self, PacketHandlerPlugin, PacketReceiver}, player::retroactively_add_game_profile_component, @@ -19,6 +20,7 @@ use crate::{ use azalea_auth::{game_profile::GameProfile, sessionserver::ClientSessionServerError}; use azalea_chat::FormattedText; use azalea_core::Vec3; +use azalea_entity::{EntityPlugin, EntityUpdateSet, Local, Position}; use azalea_physics::{PhysicsPlugin, PhysicsSet}; use azalea_protocol::{ connect::{Connection, ConnectionError}, @@ -41,10 +43,7 @@ use azalea_protocol::{ }, resolver, ServerAddress, }; -use azalea_world::{ - entity::{EntityPlugin, EntityUpdateSet, Local, Position, WorldName}, - Instance, InstanceContainer, PartialInstance, -}; +use azalea_world::{Instance, InstanceContainer, InstanceName, PartialInstance}; use bevy_app::{App, FixedUpdate, Main, Plugin, PluginGroup, PluginGroupBuilder, Update}; use bevy_ecs::{ bundle::Bundle, @@ -132,6 +131,10 @@ impl From for PlayerAbilities { } } +/// Level must be 0..=4 +#[derive(Component, Clone, Default, Deref, DerefMut)] +pub struct PermissionLevel(pub u8); + /// A component that contains a map of player UUIDs to their information in the /// tab list. /// @@ -301,6 +304,8 @@ impl Client { current_sequence_number: CurrentSequenceNumber::default(), last_sent_direction: LastSentLookDirection::default(), abilities: PlayerAbilities::default(), + permission_level: PermissionLevel::default(), + mining: mining::MineBundle::default(), _local: Local, }); @@ -466,9 +471,9 @@ impl Client { /// # Examples /// /// ``` - /// # use azalea_world::entity::WorldName; + /// # use azalea_world::InstanceName; /// # fn example(client: &azalea_client::Client) { - /// let world_name = client.component::(); + /// let world_name = client.component::(); /// # } pub fn component(&self) -> T { self.query::<&T>(&mut self.ecs.lock()).clone() @@ -486,7 +491,7 @@ impl Client { /// If the client using a shared world, then the shared world will be a /// superset of the client's world. pub fn world(&self) -> Arc> { - let world_name = self.component::(); + let world_name = self.component::(); let ecs = self.ecs.lock(); let instance_container = ecs.resource::(); instance_container.get(&world_name).unwrap() @@ -495,7 +500,7 @@ impl Client { /// Returns whether we have a received the login packet yet. pub fn logged_in(&self) -> bool { // the login packet tells us the world name - self.query::>(&mut self.ecs.lock()) + self.query::>(&mut self.ecs.lock()) .is_some() } @@ -560,6 +565,10 @@ pub struct JoinedClientBundle { pub current_sequence_number: CurrentSequenceNumber, pub last_sent_direction: LastSentLookDirection, pub abilities: PlayerAbilities, + pub permission_level: PermissionLevel, + + pub mining: mining::MineBundle, + pub _local: Local, } @@ -660,7 +669,7 @@ pub async fn tick_run_schedule_loop(run_schedule_sender: mpsc::UnboundedSender<( #[derive(Resource, Deref)] pub struct TickBroadcast(broadcast::Sender<()>); -fn send_tick_broadcast(tick_broadcast: ResMut) { +pub fn send_tick_broadcast(tick_broadcast: ResMut) { let _ = tick_broadcast.0.send(()); } /// A plugin that makes the [`RanScheduleBroadcast`] resource available. @@ -706,6 +715,7 @@ impl PluginGroup for DefaultPlugins { .add(PlayerMovePlugin) .add(InteractPlugin) .add(RespawnPlugin) + .add(MinePlugin) .add(TickBroadcastPlugin); #[cfg(feature = "log")] { diff --git a/azalea-client/src/entity_query.rs b/azalea-client/src/entity_query.rs index 8fe94659..0320457f 100644 --- a/azalea-client/src/entity_query.rs +++ b/azalea-client/src/entity_query.rs @@ -15,10 +15,10 @@ impl Client { /// /// # Examples /// ``` - /// # use azalea_world::entity::WorldName; + /// # use azalea_world::InstanceName; /// # fn example(mut client: azalea_client::Client) { /// let is_logged_in = client - /// .query::>(&mut client.ecs.lock()) + /// .query::>(&mut client.ecs.lock()) /// .is_some(); /// # } /// ``` @@ -39,7 +39,7 @@ impl Client { /// ``` /// use azalea_client::{Client, GameProfileComponent}; /// use bevy_ecs::query::With; - /// use azalea_world::entity::{Position, metadata::Player}; + /// use azalea_entity::{Position, metadata::Player}; /// /// # fn example(mut bot: Client, sender_name: String) { /// let entity = bot.entity_by::, (&GameProfileComponent,)>( diff --git a/azalea-client/src/events.rs b/azalea-client/src/events.rs index e97f3477..900f559f 100644 --- a/azalea-client/src/events.rs +++ b/azalea-client/src/events.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use azalea_protocol::packets::game::{ clientbound_player_combat_kill_packet::ClientboundPlayerCombatKillPacket, ClientboundGamePacket, }; -use azalea_world::entity::MinecraftEntityId; +use azalea_world::MinecraftEntityId; use bevy_app::{App, FixedUpdate, Plugin, Update}; use bevy_ecs::{component::Component, event::EventReader, query::Added, system::Query}; use derive_more::{Deref, DerefMut}; diff --git a/azalea-client/src/interact.rs b/azalea-client/src/interact.rs index 45b845f9..dc0213b0 100644 --- a/azalea-client/src/interact.rs +++ b/azalea-client/src/interact.rs @@ -1,22 +1,22 @@ +use std::ops::AddAssign; + use azalea_block::BlockState; use azalea_core::{BlockHitResult, BlockPos, Direction, GameMode, Vec3}; +use azalea_entity::{clamp_look_direction, view_vector, EyeHeight, LookDirection, Position}; use azalea_inventory::{ItemSlot, ItemSlotData}; use azalea_nbt::NbtList; use azalea_physics::clip::{BlockShapeType, ClipContext, FluidPickType}; use azalea_protocol::packets::game::{ serverbound_interact_packet::InteractionHand, + serverbound_swing_packet::ServerboundSwingPacket, serverbound_use_item_on_packet::{BlockHit, ServerboundUseItemOnPacket}, }; -use azalea_world::{ - entity::{clamp_look_direction, view_vector, EyeHeight, LookDirection, Position, WorldName}, - Instance, InstanceContainer, -}; +use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_app::{App, Plugin, Update}; use bevy_ecs::{ component::Component, entity::Entity, - event::EventReader, - prelude::Event, + event::{Event, EventReader, EventWriter}, schedule::IntoSystemConfigs, system::{Commands, Query, Res}, }; @@ -24,8 +24,9 @@ use derive_more::{Deref, DerefMut}; use log::warn; use crate::{ + client::{PermissionLevel, PlayerAbilities}, inventory::InventoryComponent, - local_player::{handle_send_packet_event, LocalGameMode}, + local_player::{handle_send_packet_event, LocalGameMode, SendPacketEvent}, Client, LocalPlayer, }; @@ -33,15 +34,18 @@ use crate::{ pub struct InteractPlugin; impl Plugin for InteractPlugin { fn build(&self, app: &mut App) { - app.add_event::().add_systems( - Update, - ( - update_hit_result_component.after(clamp_look_direction), - handle_block_interact_event, - ) - .before(handle_send_packet_event) - .chain(), - ); + app.add_event::() + .add_event::() + .add_systems( + Update, + ( + update_hit_result_component.after(clamp_look_direction), + handle_block_interact_event, + handle_swing_arm_event, + ) + .before(handle_send_packet_event) + .chain(), + ); } } @@ -73,9 +77,15 @@ pub struct BlockInteractEvent { /// A component that contains the number of changes this client has made to /// blocks. -#[derive(Component, Copy, Clone, Debug, Default, Deref, DerefMut)] +#[derive(Component, Copy, Clone, Debug, Default, Deref)] pub struct CurrentSequenceNumber(u32); +impl AddAssign for CurrentSequenceNumber { + fn add_assign(&mut self, rhs: u32) { + self.0 += rhs; + } +} + /// A component that contains the block that the player is currently looking at. #[derive(Component, Clone, Debug, Deref, DerefMut)] pub struct HitResultComponent(BlockHitResult); @@ -89,14 +99,15 @@ pub fn handle_block_interact_event( )>, ) { for event in events.iter() { - let Ok((local_player, mut sequence_number, hit_result)) = query.get_mut(event.entity) else { + let Ok((local_player, mut sequence_number, hit_result)) = query.get_mut(event.entity) + else { warn!("Sent BlockInteractEvent for entity that isn't LocalPlayer"); continue; }; // TODO: check to make sure we're within the world border - **sequence_number += 1; + *sequence_number += 1; // minecraft also does the interaction client-side (so it looks like clicking a // button is instant) but we don't really need that @@ -143,7 +154,7 @@ fn update_hit_result_component( &Position, &EyeHeight, &LookDirection, - &WorldName, + &InstanceName, )>, instance_container: Res, ) { @@ -246,10 +257,11 @@ pub fn check_block_can_be_broken_by_item_in_adventure_mode( .nbt .as_compound() .and_then(|nbt| nbt.get("tag").and_then(|nbt| nbt.as_compound())) - .and_then(|nbt| nbt.get("CanDestroy").and_then(|nbt| nbt.as_list())) else { - // no CanDestroy tag - return false; - }; + .and_then(|nbt| nbt.get("CanDestroy").and_then(|nbt| nbt.as_list())) + else { + // no CanDestroy tag + return false; + }; let NbtList::String(_can_destroy) = can_destroy else { // CanDestroy tag must be a list of strings @@ -265,3 +277,31 @@ pub fn check_block_can_be_broken_by_item_in_adventure_mode( // true } + +pub fn can_use_game_master_blocks( + abilities: &PlayerAbilities, + permission_level: &PermissionLevel, +) -> bool { + abilities.instant_break && **permission_level >= 2 +} + +/// Swing your arm. This is purely a visual effect and won't interact with +/// anything in the world. +#[derive(Event)] +pub struct SwingArmEvent { + pub entity: Entity, +} +fn handle_swing_arm_event( + mut events: EventReader, + mut send_packet_events: EventWriter, +) { + for event in events.iter() { + send_packet_events.send(SendPacketEvent { + entity: event.entity, + packet: ServerboundSwingPacket { + hand: InteractionHand::MainHand, + } + .get(), + }); + } +} diff --git a/azalea-client/src/inventory.rs b/azalea-client/src/inventory.rs index 25ce157e..6f7829de 100644 --- a/azalea-client/src/inventory.rs +++ b/azalea-client/src/inventory.rs @@ -101,6 +101,7 @@ pub struct InventoryComponent { /// the scroll wheel. pub selected_hotbar_slot: u8, } + impl InventoryComponent { /// Returns a reference to the currently active menu. If a container is open /// it'll return [`Self::container_menu`], otherwise @@ -220,10 +221,10 @@ impl InventoryComponent { loop { let Some(&next_slot) = quick_craft_slots_iter.next() else { - carried.count = carried_count; - self.carried = ItemSlot::Present(carried); - return self.reset_quick_craft(); - }; + carried.count = carried_count; + self.carried = ItemSlot::Present(carried); + return self.reset_quick_craft(); + }; slot = self.menu().slot(next_slot as usize).unwrap(); slot_index = next_slot; @@ -244,8 +245,8 @@ impl InventoryComponent { // get the ItemSlotData for the slot let ItemSlot::Present(slot) = slot else { - unreachable!("the loop above requires the slot to be present to break") - }; + unreachable!("the loop above requires the slot to be present to break") + }; // if self.can_drag_to(slot) { let mut new_carried = carried.clone(); @@ -480,8 +481,8 @@ impl InventoryComponent { // now extend the carried item let target_slot = &mut self.carried; let ItemSlot::Present(target_slot_item) = target_slot else { - unreachable!("target slot is not empty but is not present"); - }; + unreachable!("target slot is not empty but is not present"); + }; target_slot_item.count += taken_item.count(); } } @@ -512,13 +513,13 @@ fn can_item_quick_replace( ignore_item_count: bool, ) -> bool { let ItemSlot::Present(target_slot) = target_slot else { - return false; - }; + return false; + }; let ItemSlot::Present(item) = item else { // i *think* this is what vanilla does // not 100% sure lol probably doesn't matter though - return false; - }; + return false; + }; if !item.is_same_item_and_nbt(target_slot) { return false; diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs index c47c5e29..e36cb846 100644 --- a/azalea-client/src/lib.rs +++ b/azalea-client/src/lib.rs @@ -21,7 +21,7 @@ mod get_mc_dir; pub mod interact; pub mod inventory; mod local_player; -mod mining; +pub mod mining; mod movement; pub mod packet_handling; pub mod ping; diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs index 4368c47c..594513db 100644 --- a/azalea-client/src/local_player.rs +++ b/azalea-client/src/local_player.rs @@ -2,11 +2,9 @@ use std::{io, sync::Arc}; use azalea_auth::game_profile::GameProfile; use azalea_core::{ChunkPos, GameMode}; +use azalea_entity::{Dead, Position}; use azalea_protocol::packets::game::ServerboundGamePacket; -use azalea_world::{ - entity::{self, Dead, WorldName}, - Instance, InstanceContainer, PartialInstance, -}; +use azalea_world::{Instance, InstanceContainer, InstanceName, PartialInstance}; use bevy_ecs::{ component::Component, entity::Entity, @@ -32,7 +30,7 @@ use crate::{ /// You can also use the [`Local`] marker component for queries if you're only /// checking for a local player and don't need the contents of this component. /// -/// [`Local`]: azalea_world::entity::Local +/// [`Local`]: azalea_entity::Local /// [`Client`]: crate::Client #[derive(Component)] pub struct LocalPlayer { @@ -135,7 +133,7 @@ impl Drop for LocalPlayer { /// Update the [`LocalPlayerInLoadedChunk`] component for all [`LocalPlayer`]s. pub fn update_in_loaded_chunk( mut commands: bevy_ecs::system::Commands, - query: Query<(Entity, &WorldName, &entity::Position)>, + query: Query<(Entity, &InstanceName, &Position)>, instance_container: Res, ) { for (entity, local_player, position) in &query { diff --git a/azalea-client/src/mining.rs b/azalea-client/src/mining.rs index 241c4fde..049bc859 100644 --- a/azalea-client/src/mining.rs +++ b/azalea-client/src/mining.rs @@ -1,36 +1,543 @@ -use azalea_core::BlockPos; -use bevy_app::{App, Plugin, Update}; +use azalea_block::{Block, BlockState, FluidState}; +use azalea_core::{BlockPos, Direction, GameMode}; +use azalea_entity::{mining::get_mine_progress, FluidOnEyes, Physics}; +use azalea_inventory::ItemSlot; +use azalea_protocol::packets::game::serverbound_player_action_packet::{ + self, ServerboundPlayerActionPacket, +}; +use azalea_world::{InstanceContainer, InstanceName}; +use bevy_app::{App, FixedUpdate, Plugin, Update}; use bevy_ecs::prelude::*; +use derive_more::{Deref, DerefMut}; -use crate::Client; +use crate::{ + client::{PermissionLevel, PlayerAbilities}, + interact::{ + can_use_game_master_blocks, check_is_interaction_restricted, CurrentSequenceNumber, + HitResultComponent, SwingArmEvent, + }, + inventory::InventoryComponent, + local_player::{LocalGameMode, SendPacketEvent}, +}; /// A plugin that allows clients to break blocks in the world. pub struct MinePlugin; impl Plugin for MinePlugin { fn build(&self, app: &mut App) { app.add_event::() - .add_systems(Update, handle_start_mining_block_event); + .add_event::() + .add_event::() + .add_event::() + .add_event::() + .add_event::() + .add_systems(FixedUpdate, continue_mining_block) + .add_systems( + Update, + ( + handle_start_mining_block_event, + handle_start_mining_block_with_direction_event, + handle_finish_mining_block_event, + handle_stop_mining_block_event, + ) + .chain(), + ); } } -impl Client { - /// Start mining a block. - pub fn start_mining_block(&self, position: BlockPos) { - self.ecs.lock().send_event(StartMiningBlockEvent { - entity: self.entity, - position, - }); - } +/// Information about the block we're currently mining. This is only present if +/// we're currently mining a block. +#[derive(Component)] +pub struct Mining { + pub pos: BlockPos, + pub dir: Direction, } +/// Start mining the block at the given position. +/// +/// If we're looking at the block then the correct direction will be used, +/// otherwise it'll be [`Direction::Down`]. #[derive(Event)] pub struct StartMiningBlockEvent { pub entity: Entity, pub position: BlockPos, } - -fn handle_start_mining_block_event(mut _events: EventReader) { - // for event in events.iter() { - // // - // } +fn handle_start_mining_block_event( + mut events: EventReader, + mut start_mining_events: EventWriter, + mut query: Query<&HitResultComponent>, +) { + for event in events.iter() { + let hit_result = query.get_mut(event.entity).unwrap(); + let direction = if hit_result.block_pos == event.position { + // we're looking at the block + hit_result.direction + } else { + // we're not looking at the block, arbitrary direction + Direction::Down + }; + start_mining_events.send(StartMiningBlockWithDirectionEvent { + entity: event.entity, + position: event.position, + direction, + }); + } +} + +#[derive(Event)] +pub struct StartMiningBlockWithDirectionEvent { + pub entity: Entity, + pub position: BlockPos, + pub direction: Direction, +} +#[allow(clippy::too_many_arguments, clippy::type_complexity)] +fn handle_start_mining_block_with_direction_event( + mut events: EventReader, + mut finish_mining_events: EventWriter, + mut send_packet_events: EventWriter, + mut attack_block_events: EventWriter, + mut mine_block_progress_events: EventWriter, + mut query: Query<( + &InstanceName, + &LocalGameMode, + &InventoryComponent, + &FluidOnEyes, + &Physics, + Option<&Mining>, + &mut CurrentSequenceNumber, + &mut MineDelay, + &mut MineProgress, + &mut MineTicks, + &mut MineItem, + &mut MineBlockPos, + )>, + instances: Res, + mut commands: Commands, +) { + for event in events.iter() { + let ( + instance_name, + game_mode, + inventory, + fluid_on_eyes, + physics, + mining, + mut sequence_number, + mut mine_delay, + mut mine_progress, + mut mine_ticks, + mut current_mining_item, + mut current_mining_pos, + ) = query.get_mut(event.entity).unwrap(); + + let instance_lock = instances.get(instance_name).unwrap(); + let instance = instance_lock.read(); + if check_is_interaction_restricted( + &instance, + &event.position, + &game_mode.current, + inventory, + ) { + continue; + } + // TODO (when world border is implemented): vanilla ignores if the block + // is outside of the worldborder + + if game_mode.current == GameMode::Creative { + *sequence_number += 1; + finish_mining_events.send(FinishMiningBlockEvent { + entity: event.entity, + position: event.position, + }); + **mine_delay = 5; + } else if mining.is_none() + || !is_same_mining_target( + event.position, + inventory, + ¤t_mining_pos, + ¤t_mining_item, + ) + { + if mining.is_some() { + // send a packet to stop mining since we just changed target + send_packet_events.send(SendPacketEvent { + entity: event.entity, + packet: ServerboundPlayerActionPacket { + action: serverbound_player_action_packet::Action::AbortDestroyBlock, + pos: current_mining_pos + .expect("IsMining is true so MineBlockPos must be present"), + direction: event.direction, + sequence: 0, + } + .get(), + }); + } + + let target_block_state = instance + .get_block_state(&event.position) + .unwrap_or_default(); + *sequence_number += 1; + let block_is_solid = !target_block_state.is_air(); + if block_is_solid && **mine_progress == 0. { + // interact with the block (like note block left click) here + attack_block_events.send(AttackBlockEvent { + entity: event.entity, + position: event.position, + }); + } + + let block = Box::::from(target_block_state); + + let held_item = inventory.held_item(); + + if block_is_solid + && get_mine_progress( + block.as_ref(), + held_item.kind(), + &inventory.inventory_menu, + fluid_on_eyes, + physics, + ) >= 1. + { + // block was broken instantly + finish_mining_events.send(FinishMiningBlockEvent { + entity: event.entity, + position: event.position, + }); + } else { + commands.entity(event.entity).insert(Mining { + pos: event.position, + dir: event.direction, + }); + **current_mining_pos = Some(event.position); + **current_mining_item = held_item; + **mine_progress = 0.; + **mine_ticks = 0.; + mine_block_progress_events.send(MineBlockProgressEvent { + entity: event.entity, + position: event.position, + destroy_stage: mine_progress.destroy_stage(), + }) + } + + send_packet_events.send(SendPacketEvent { + entity: event.entity, + packet: ServerboundPlayerActionPacket { + action: serverbound_player_action_packet::Action::StartDestroyBlock, + pos: event.position, + direction: event.direction, + sequence: **sequence_number, + } + .get(), + }); + } + } +} + +#[derive(Event)] +pub struct MineBlockProgressEvent { + pub entity: Entity, + pub position: BlockPos, + pub destroy_stage: Option, +} + +/// A player left clicked on a block, used for stuff like interacting with note +/// blocks. +#[derive(Event)] +pub struct AttackBlockEvent { + pub entity: Entity, + pub position: BlockPos, +} + +/// Returns whether the block and item are still the same as when we started +/// mining. +fn is_same_mining_target( + target_block: BlockPos, + inventory: &InventoryComponent, + current_mining_pos: &MineBlockPos, + current_mining_item: &MineItem, +) -> bool { + let held_item = inventory.held_item(); + Some(target_block) == current_mining_pos.0 && held_item == current_mining_item.0 +} + +/// A component bundle for players that can mine blocks. +#[derive(Bundle, Default)] +pub struct MineBundle { + pub delay: MineDelay, + pub progress: MineProgress, + pub ticks: MineTicks, + pub mining_pos: MineBlockPos, + pub mine_item: MineItem, +} + +/// A component that counts down until we start mining the next block. +#[derive(Component, Debug, Default, Deref, DerefMut)] +pub struct MineDelay(pub u32); + +/// A component that stores the progress of the current mining operation. This +/// is a value between 0 and 1. +#[derive(Component, Debug, Default, Deref, DerefMut)] +pub struct MineProgress(pub f32); + +impl MineProgress { + pub fn destroy_stage(&self) -> Option { + if self.0 > 0. { + Some((self.0 * 10.) as u32) + } else { + None + } + } +} + +/// A component that stores the number of ticks that we've been mining the same +/// block for. This is a float even though it should only ever be a round +/// number. +#[derive(Component, Debug, Default, Deref, DerefMut)] +pub struct MineTicks(pub f32); + +/// A component that stores the position of the block we're currently mining. +#[derive(Component, Debug, Default, Deref, DerefMut)] +pub struct MineBlockPos(pub Option); + +/// A component that contains the item we're currently using to mine. If we're +/// not mining anything, it'll be [`ItemSlot::Empty`]. +#[derive(Component, Debug, Default, Deref, DerefMut)] +pub struct MineItem(pub ItemSlot); + +/// Sent when we completed mining a block. +#[derive(Event)] +pub struct FinishMiningBlockEvent { + pub entity: Entity, + pub position: BlockPos, +} + +fn handle_finish_mining_block_event( + mut events: EventReader, + mut query: Query<( + &InstanceName, + &LocalGameMode, + &InventoryComponent, + &PlayerAbilities, + &PermissionLevel, + &mut CurrentSequenceNumber, + )>, + instances: Res, +) { + for event in events.iter() { + let (instance_name, game_mode, inventory, abilities, permission_level, _sequence_number) = + query.get_mut(event.entity).unwrap(); + let instance_lock = instances.get(instance_name).unwrap(); + let instance = instance_lock.read(); + if check_is_interaction_restricted( + &instance, + &event.position, + &game_mode.current, + inventory, + ) { + continue; + } + + if game_mode.current == GameMode::Creative { + let held_item = inventory.held_item().kind(); + if matches!( + held_item, + azalea_registry::Item::Trident | azalea_registry::Item::DebugStick + ) || azalea_registry::tags::items::SWORDS.contains(&held_item) + { + continue; + } + } + + let Some(block_state) = instance.get_block_state(&event.position) else { + continue; + }; + + let registry_block = Box::::from(block_state).as_registry_block(); + if !can_use_game_master_blocks(abilities, permission_level) + && matches!( + registry_block, + azalea_registry::Block::CommandBlock | azalea_registry::Block::StructureBlock + ) + { + continue; + } + if block_state == BlockState::AIR { + continue; + } + + // when we break a waterlogged block we want to keep the water there + let fluid_state = FluidState::from(block_state); + let block_state_for_fluid = BlockState::from(fluid_state); + instance.set_block_state(&event.position, block_state_for_fluid); + } +} + +/// Abort mining a block. +#[derive(Event)] +pub struct StopMiningBlockEvent { + pub entity: Entity, +} +fn handle_stop_mining_block_event( + mut events: EventReader, + mut send_packet_events: EventWriter, + mut mine_block_progress_events: EventWriter, + mut query: Query<(&mut Mining, &MineBlockPos, &mut MineProgress)>, + mut commands: Commands, +) { + for event in events.iter() { + let (mut _mining, mine_block_pos, mut mine_progress) = query.get_mut(event.entity).unwrap(); + + let mine_block_pos = + mine_block_pos.expect("IsMining is true so MineBlockPos must be present"); + send_packet_events.send(SendPacketEvent { + entity: event.entity, + packet: ServerboundPlayerActionPacket { + action: serverbound_player_action_packet::Action::AbortDestroyBlock, + pos: mine_block_pos, + direction: Direction::Down, + sequence: 0, + } + .get(), + }); + commands.entity(event.entity).remove::(); + **mine_progress = 0.; + mine_block_progress_events.send(MineBlockProgressEvent { + entity: event.entity, + position: mine_block_pos, + destroy_stage: None, + }); + } +} + +#[allow(clippy::too_many_arguments, clippy::type_complexity)] +fn continue_mining_block( + mut query: Query<( + Entity, + &InstanceName, + &LocalGameMode, + &InventoryComponent, + &MineBlockPos, + &MineItem, + &FluidOnEyes, + &Physics, + &Mining, + &mut MineDelay, + &mut MineProgress, + &mut MineTicks, + &mut CurrentSequenceNumber, + )>, + mut send_packet_events: EventWriter, + mut mine_block_progress_events: EventWriter, + mut finish_mining_events: EventWriter, + mut start_mining_events: EventWriter, + mut swing_arm_events: EventWriter, + instances: Res, + mut commands: Commands, +) { + for ( + entity, + instance_name, + game_mode, + inventory, + current_mining_pos, + current_mining_item, + fluid_on_eyes, + physics, + mining, + mut mine_delay, + mut mine_progress, + mut mine_ticks, + mut sequence_number, + ) in query.iter_mut() + { + if **mine_delay > 0 { + **mine_delay -= 1; + continue; + } + + if game_mode.current == GameMode::Creative { + // TODO: worldborder check + **mine_delay = 5; + finish_mining_events.send(FinishMiningBlockEvent { + entity, + position: mining.pos, + }); + *sequence_number += 1; + send_packet_events.send(SendPacketEvent { + entity, + packet: ServerboundPlayerActionPacket { + action: serverbound_player_action_packet::Action::StartDestroyBlock, + pos: mining.pos, + direction: mining.dir, + sequence: **sequence_number, + } + .get(), + }); + swing_arm_events.send(SwingArmEvent { entity }); + } else if is_same_mining_target( + mining.pos, + inventory, + current_mining_pos, + current_mining_item, + ) { + let instance_lock = instances.get(instance_name).unwrap(); + let instance = instance_lock.read(); + let target_block_state = instance.get_block_state(&mining.pos).unwrap_or_default(); + + if target_block_state.is_air() { + commands.entity(entity).remove::(); + continue; + } + let block = Box::::from(target_block_state); + **mine_progress += get_mine_progress( + block.as_ref(), + current_mining_item.kind(), + &inventory.inventory_menu, + fluid_on_eyes, + physics, + ); + + if **mine_ticks % 4. == 0. { + // vanilla makes a mining sound here + } + **mine_ticks += 1.; + + if **mine_progress >= 1. { + commands.entity(entity).remove::(); + *sequence_number += 1; + finish_mining_events.send(FinishMiningBlockEvent { + entity, + position: mining.pos, + }); + send_packet_events.send(SendPacketEvent { + entity, + packet: ServerboundPlayerActionPacket { + action: serverbound_player_action_packet::Action::StopDestroyBlock, + pos: mining.pos, + direction: mining.dir, + sequence: **sequence_number, + } + .get(), + }); + **mine_progress = 0.; + **mine_ticks = 0.; + **mine_delay = 0; + } + + mine_block_progress_events.send(MineBlockProgressEvent { + entity, + position: mining.pos, + destroy_stage: mine_progress.destroy_stage(), + }); + swing_arm_events.send(SwingArmEvent { entity }); + } else { + start_mining_events.send(StartMiningBlockWithDirectionEvent { + entity, + position: mining.pos, + direction: mining.dir, + }) + } + + swing_arm_events.send(SwingArmEvent { entity }); + } } diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs index 2db392b4..0bda9b15 100644 --- a/azalea-client/src/movement.rs +++ b/azalea-client/src/movement.rs @@ -2,6 +2,8 @@ use crate::client::Client; use crate::local_player::{ update_in_loaded_chunk, LocalPlayer, LocalPlayerInLoadedChunk, PhysicsState, }; +use azalea_entity::{metadata::Sprinting, Attributes, Jumping}; +use azalea_entity::{LastSentPosition, LookDirection, Physics, Position}; use azalea_physics::{force_jump_listener, PhysicsSet}; use azalea_protocol::packets::game::serverbound_player_command_packet::ServerboundPlayerCommandPacket; use azalea_protocol::packets::game::{ @@ -10,10 +12,7 @@ use azalea_protocol::packets::game::{ serverbound_move_player_rot_packet::ServerboundMovePlayerRotPacket, serverbound_move_player_status_only_packet::ServerboundMovePlayerStatusOnlyPacket, }; -use azalea_world::{ - entity::{self, metadata::Sprinting, Attributes, Jumping, MinecraftEntityId}, - MoveEntityError, -}; +use azalea_world::{MinecraftEntityId, MoveEntityError}; use bevy_app::{App, FixedUpdate, Plugin, Update}; use bevy_ecs::prelude::Event; use bevy_ecs::{ @@ -89,7 +88,7 @@ impl Client { /// `y_rot` goes from -180 to 180, and `x_rot` goes from -90 to 90. pub fn set_direction(&mut self, y_rot: f32, x_rot: f32) { let mut ecs = self.ecs.lock(); - let mut look_direction = self.query::<&mut entity::LookDirection>(&mut ecs); + let mut look_direction = self.query::<&mut LookDirection>(&mut ecs); (look_direction.y_rot, look_direction.x_rot) = (y_rot, x_rot); } @@ -110,12 +109,12 @@ pub(crate) fn send_position( &MinecraftEntityId, &mut LocalPlayer, &mut PhysicsState, - &entity::Position, - &mut entity::LastSentPosition, - &mut entity::Physics, - &entity::LookDirection, + &Position, + &mut LastSentPosition, + &mut Physics, + &LookDirection, &mut LastSentLookDirection, - &entity::metadata::Sprinting, + &Sprinting, ), &LocalPlayerInLoadedChunk, >, @@ -223,7 +222,7 @@ impl LocalPlayer { fn send_sprinting_if_needed( &mut self, id: &MinecraftEntityId, - sprinting: &entity::metadata::Sprinting, + sprinting: &Sprinting, physics_state: &mut PhysicsState, ) { let was_sprinting = physics_state.was_sprinting; @@ -287,9 +286,9 @@ pub fn local_player_ai_step( mut query: Query< ( &mut PhysicsState, - &mut entity::Physics, - &mut entity::metadata::Sprinting, - &mut entity::Attributes, + &mut Physics, + &mut Sprinting, + &mut Attributes, ), With, >, @@ -431,12 +430,12 @@ fn set_sprinting( if sprinting { attributes .speed - .insert(entity::attributes::sprinting_modifier()) + .insert(azalea_entity::attributes::sprinting_modifier()) .is_ok() } else { attributes .speed - .remove(&entity::attributes::sprinting_modifier().uuid) + .remove(&azalea_entity::attributes::sprinting_modifier().uuid) .is_none() } } diff --git a/azalea-client/src/packet_handling.rs b/azalea-client/src/packet_handling.rs index 2371d834..fd8d77e5 100644 --- a/azalea-client/src/packet_handling.rs +++ b/azalea-client/src/packet_handling.rs @@ -1,6 +1,11 @@ use std::{collections::HashSet, io::Cursor, sync::Arc}; use azalea_core::{ChunkPos, GameMode, ResourceLocation, Vec3}; +use azalea_entity::{ + metadata::{apply_metadata, Health, PlayerMetadataBundle}, + Dead, EntityBundle, EntityKind, EntityUpdateSet, LastSentPosition, LoadedBy, LookDirection, + Physics, PlayerBundle, Position, RelativeEntityUpdate, +}; use azalea_protocol::{ connect::{ReadConnection, WriteConnection}, packets::game::{ @@ -15,15 +20,7 @@ use azalea_protocol::{ }, read::ReadPacketError, }; -use azalea_world::{ - entity::{ - metadata::{apply_metadata, Health, PlayerMetadataBundle}, - Dead, EntityBundle, EntityKind, EntityUpdateSet, LastSentPosition, LookDirection, - MinecraftEntityId, Physics, PlayerBundle, Position, WorldName, - }, - entity::{LoadedBy, RelativeEntityUpdate}, - InstanceContainer, PartialInstance, -}; +use azalea_world::{InstanceContainer, InstanceName, MinecraftEntityId, PartialInstance}; use bevy_app::{App, First, Plugin, PreUpdate}; use bevy_ecs::{ component::Component, @@ -195,7 +192,7 @@ fn process_packet_events(ecs: &mut World) { Commands, Query<( &mut LocalPlayer, - Option<&mut WorldName>, + Option<&mut InstanceName>, &GameProfileComponent, &ClientInformation, )>, @@ -225,7 +222,7 @@ fn process_packet_events(ecs: &mut World) { } else { commands .entity(player_entity) - .insert(WorldName(new_world_name.clone())); + .insert(InstanceName(new_world_name.clone())); } // add this world to the instance_container (or don't if it's already // there) @@ -348,10 +345,16 @@ fn process_packet_events(ecs: &mut World) { )>, > = SystemState::new(ecs); let mut query = system_state.get_mut(ecs); - let Ok((local_player, mut physics, mut direction, mut position, mut last_sent_position)) = - query.get_mut(player_entity) else { - continue; - }; + let Ok(( + local_player, + mut physics, + mut direction, + mut position, + mut last_sent_position, + )) = query.get_mut(player_entity) + else { + continue; + }; let delta_movement = physics.delta; @@ -555,12 +558,12 @@ fn process_packet_events(ecs: &mut World) { ClientboundGamePacket::AddEntity(p) => { debug!("Got add entity packet {:?}", p); - let mut system_state: SystemState<(Commands, Query>)> = + let mut system_state: SystemState<(Commands, Query>)> = SystemState::new(ecs); let (mut commands, mut query) = system_state.get_mut(ecs); let world_name = query.get_mut(player_entity).unwrap(); - if let Some(WorldName(world_name)) = world_name { + if let Some(InstanceName(world_name)) = world_name { let bundle = p.as_entity_bundle(world_name.clone()); let mut entity_commands = commands.spawn(( MinecraftEntityId(p.id), @@ -622,12 +625,12 @@ fn process_packet_events(ecs: &mut World) { #[allow(clippy::type_complexity)] let mut system_state: SystemState<( Commands, - Query<(&TabList, Option<&WorldName>)>, + Query<(&TabList, Option<&InstanceName>)>, )> = SystemState::new(ecs); let (mut commands, mut query) = system_state.get_mut(ecs); let (tab_list, world_name) = query.get_mut(player_entity).unwrap(); - if let Some(WorldName(world_name)) = world_name { + if let Some(InstanceName(world_name)) = world_name { let bundle = p.as_player_bundle(world_name.clone()); let mut spawned = commands.spawn(( MinecraftEntityId(p.id), diff --git a/azalea-client/src/player.rs b/azalea-client/src/player.rs index 999f2490..25ba0d8c 100755 --- a/azalea-client/src/player.rs +++ b/azalea-client/src/player.rs @@ -1,7 +1,7 @@ use azalea_auth::game_profile::GameProfile; use azalea_chat::FormattedText; use azalea_core::GameMode; -use azalea_world::entity::EntityInfos; +use azalea_entity::EntityInfos; use bevy_ecs::{ event::EventReader, system::{Commands, Res}, diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs index 7bf4a12c..8ed62b06 100755 --- a/azalea-core/src/lib.rs +++ b/azalea-core/src/lib.rs @@ -22,8 +22,7 @@ pub use direction::*; mod delta; pub use delta::*; -mod particle; -pub use particle::*; +pub mod particle; mod cursor3d; pub use cursor3d::*; @@ -37,61 +36,5 @@ pub use aabb::*; mod block_hit_result; pub use block_hit_result::*; -// some random math things used in minecraft are defined down here - -// TODO: make this generic -pub fn binary_search(mut min: i32, max: i32, predicate: &dyn Fn(i32) -> bool) -> i32 { - let mut diff = max - min; - while diff > 0 { - let diff_mid = diff / 2; - let mid = min + diff_mid; - if predicate(mid) { - diff = diff_mid; - } else { - min = mid + 1; - diff -= diff_mid + 1; - } - } - - min -} - -pub fn lcm(a: u32, b: u32) -> u64 { - let gcd = gcd(a, b); - (a as u64) * (b / gcd) as u64 -} -pub fn gcd(mut a: u32, mut b: u32) -> u32 { - while b != 0 { - let t = b; - b = a % b; - a = t; - } - a -} - -pub fn lerp(amount: T, a: T, b: T) -> T { - a + amount * (b - a) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_gcd() { - assert_eq!(gcd(0, 0), 0); - assert_eq!(gcd(1, 1), 1); - - assert_eq!(gcd(0, 1), 1); - assert_eq!(gcd(1, 0), 1); - - assert_eq!(gcd(12, 8), 4); - assert_eq!(gcd(8, 12), 4); - - assert_eq!(gcd(12, 9), 3); - assert_eq!(gcd(9, 12), 3); - - assert_eq!(gcd(12, 7), 1); - assert_eq!(gcd(7, 12), 1); - } -} +pub mod math; +pub mod tier; diff --git a/azalea-core/src/math.rs b/azalea-core/src/math.rs new file mode 100644 index 00000000..2e5e78f6 --- /dev/null +++ b/azalea-core/src/math.rs @@ -0,0 +1,56 @@ +// TODO: make this generic +pub fn binary_search(mut min: i32, max: i32, predicate: &dyn Fn(i32) -> bool) -> i32 { + let mut diff = max - min; + while diff > 0 { + let diff_mid = diff / 2; + let mid = min + diff_mid; + if predicate(mid) { + diff = diff_mid; + } else { + min = mid + 1; + diff -= diff_mid + 1; + } + } + + min +} + +pub fn lcm(a: u32, b: u32) -> u64 { + let gcd = gcd(a, b); + (a as u64) * (b / gcd) as u64 +} +pub fn gcd(mut a: u32, mut b: u32) -> u32 { + while b != 0 { + let t = b; + b = a % b; + a = t; + } + a +} + +pub fn lerp(amount: T, a: T, b: T) -> T { + a + amount * (b - a) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_gcd() { + assert_eq!(gcd(0, 0), 0); + assert_eq!(gcd(1, 1), 1); + + assert_eq!(gcd(0, 1), 1); + assert_eq!(gcd(1, 0), 1); + + assert_eq!(gcd(12, 8), 4); + assert_eq!(gcd(8, 12), 4); + + assert_eq!(gcd(12, 9), 3); + assert_eq!(gcd(9, 12), 3); + + assert_eq!(gcd(12, 7), 1); + assert_eq!(gcd(7, 12), 1); + } +} diff --git a/azalea-core/src/particle/mod.rs b/azalea-core/src/particle.rs similarity index 100% rename from azalea-core/src/particle/mod.rs rename to azalea-core/src/particle.rs diff --git a/azalea-core/src/tier.rs b/azalea-core/src/tier.rs new file mode 100644 index 00000000..e921899f --- /dev/null +++ b/azalea-core/src/tier.rs @@ -0,0 +1,46 @@ +pub fn get_item_tier(item: azalea_registry::Item) -> Option { + use azalea_registry::Item::*; + Some(match item { + WoodenPickaxe | WoodenShovel | WoodenAxe | WoodenHoe | WoodenSword => Tier::Wood, + StonePickaxe | StoneShovel | StoneAxe | StoneHoe | StoneSword => Tier::Stone, + IronPickaxe | IronShovel | IronAxe | IronHoe | IronSword => Tier::Iron, + DiamondPickaxe | DiamondShovel | DiamondAxe | DiamondHoe | DiamondSword => Tier::Diamond, + GoldenPickaxe | GoldenShovel | GoldenAxe | GoldenHoe | GoldenSword => Tier::Gold, + NetheritePickaxe | NetheriteShovel | NetheriteAxe | NetheriteHoe | NetheriteSword => { + Tier::Netherite + } + _ => return None, + }) +} + +pub enum Tier { + Wood, + Stone, + Iron, + Diamond, + Gold, + Netherite, +} + +impl Tier { + pub fn level(&self) -> u8 { + match self { + Tier::Wood => 0, + Tier::Stone => 1, + Tier::Iron => 2, + Tier::Diamond => 3, + Tier::Gold => 0, // gold is the same tier as wood + Tier::Netherite => 4, + } + } + pub fn speed(&self) -> f32 { + match self { + Tier::Wood => 2., + Tier::Stone => 4., + Tier::Iron => 6., + Tier::Diamond => 8., + Tier::Gold => 12., + Tier::Netherite => 9., + } + } +} diff --git a/azalea-entity/Cargo.toml b/azalea-entity/Cargo.toml new file mode 100644 index 00000000..c2a405fe --- /dev/null +++ b/azalea-entity/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "azalea-entity" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +azalea-block = { version = "0.7.0", path = "../azalea-block" } +azalea-buf = { version = "0.7.0", path = "../azalea-buf" } +azalea-chat = { version = "0.7.0", path = "../azalea-chat" } +azalea-core = { version = "0.7.0", path = "../azalea-core" } +azalea-inventory = { version = "0.7.0", path = "../azalea-inventory" } +azalea-nbt = { version = "0.7.0", path = "../azalea-nbt" } +azalea-registry = { version = "0.7.0", path = "../azalea-registry" } +azalea-world = { version = "0.7.0", path = "../azalea-world" } +bevy_app = "0.11.0" +bevy_ecs = "0.11.0" +derive_more = "0.99.17" +enum-as-inner = "0.6.0" +log = "0.4.19" +nohash-hasher = "0.2.0" +parking_lot = "0.12.1" +thiserror = "1.0.43" +uuid = "1.4.0" diff --git a/azalea-world/src/entity/attributes.rs b/azalea-entity/src/attributes.rs similarity index 100% rename from azalea-world/src/entity/attributes.rs rename to azalea-entity/src/attributes.rs diff --git a/azalea-world/src/entity/data.rs b/azalea-entity/src/data.rs similarity index 98% rename from azalea-world/src/entity/data.rs rename to azalea-entity/src/data.rs index 31d4ca2f..4f6d8492 100755 --- a/azalea-world/src/entity/data.rs +++ b/azalea-entity/src/data.rs @@ -4,7 +4,7 @@ use azalea_buf::{ BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable, }; use azalea_chat::FormattedText; -use azalea_core::{BlockPos, Direction, GlobalPos, Particle, Vec3}; +use azalea_core::{particle::Particle, BlockPos, Direction, GlobalPos, Vec3}; use azalea_inventory::ItemSlot; use bevy_ecs::component::Component; use derive_more::Deref; diff --git a/azalea-world/src/entity/dimensions.rs b/azalea-entity/src/dimensions.rs similarity index 100% rename from azalea-world/src/entity/dimensions.rs rename to azalea-entity/src/dimensions.rs diff --git a/azalea-entity/src/effects.rs b/azalea-entity/src/effects.rs new file mode 100644 index 00000000..9cc750e5 --- /dev/null +++ b/azalea-entity/src/effects.rs @@ -0,0 +1,26 @@ +// TODO + +// pub struct ActiveEffects(HashMap); + +/// Returns the level of the given effect, or `None` if the effect is not +/// active. The lowest level is 0. +pub fn get_effect(_effect: azalea_registry::MobEffect) -> Option { + // TODO + None +} + +pub fn get_dig_speed_amplifier() -> Option { + let effect_plus_one = u32::max( + get_effect(azalea_registry::MobEffect::Haste) + .map(|x| x + 1) + .unwrap_or_default(), + get_effect(azalea_registry::MobEffect::ConduitPower) + .map(|x| x + 1) + .unwrap_or_default(), + ); + if effect_plus_one > 0 { + Some(effect_plus_one - 1) + } else { + None + } +} diff --git a/azalea-entity/src/enchantments.rs b/azalea-entity/src/enchantments.rs new file mode 100644 index 00000000..fd238bf2 --- /dev/null +++ b/azalea-entity/src/enchantments.rs @@ -0,0 +1,8 @@ +pub fn get_enchant_level( + _enchantment: azalea_registry::Enchantment, + _player_inventory: &azalea_inventory::Menu, +) -> u32 { + // TODO + + 0 +} diff --git a/azalea-world/src/entity/info.rs b/azalea-entity/src/info.rs similarity index 87% rename from azalea-world/src/entity/info.rs rename to azalea-entity/src/info.rs index 03b72f94..18021d36 100644 --- a/azalea-world/src/entity/info.rs +++ b/azalea-entity/src/info.rs @@ -1,14 +1,8 @@ //! Implement things relating to entity datas, like an index of uuids to //! entities. -use crate::{ - deduplicate_entities, deduplicate_local_entities, - entity::{ - self, add_dead, update_bounding_box, EntityUuid, MinecraftEntityId, Position, WorldName, - }, - update_entity_by_id_index, update_uuid_index, InstanceContainer, PartialInstance, -}; use azalea_core::ChunkPos; +use azalea_world::{InstanceContainer, InstanceName, MinecraftEntityId, PartialInstance}; use bevy_app::{App, Plugin, PostUpdate, PreUpdate, Update}; use bevy_ecs::{ component::Component, @@ -20,7 +14,6 @@ use bevy_ecs::{ }; use derive_more::{Deref, DerefMut}; use log::{debug, warn}; -use nohash_hasher::IntMap; use parking_lot::RwLock; use std::{ collections::{HashMap, HashSet}, @@ -29,6 +22,15 @@ use std::{ }; use uuid::Uuid; +use crate::{ + add_dead, + systems::{ + deduplicate_entities, deduplicate_local_entities, update_entity_by_id_index, + update_fluid_on_eyes, update_uuid_index, + }, + update_bounding_box, EntityUuid, LastSentPosition, Position, +}; + use super::{Local, LookDirection}; /// A Bevy [`SystemSet`] for various types of entity updates. @@ -75,6 +77,7 @@ impl Plugin for EntityPlugin { add_dead, update_bounding_box, clamp_look_direction, + update_fluid_on_eyes, ), ), ) @@ -109,33 +112,6 @@ fn debug_new_entity(query: Query<(Entity, Option<&Local>), Added, - /// A counter for each entity that tracks how many updates we've observed - /// for it. - /// - /// This is used for shared worlds (i.e. swarms), to make sure we don't - /// update entities twice on accident. - pub updates_received: IntMap, -} - -impl PartialEntityInfos { - pub fn new(owner_entity: Option) -> Self { - Self { - owner_entity, - updates_received: IntMap::default(), - } - } -} - /// An [`EntityCommand`] that applies a "relative update" to an entity, which /// means this update won't be run multiple times by different clients in the /// same world. @@ -211,15 +187,7 @@ impl EntityInfos { /// Update the chunk position indexes in [`EntityInfos`]. fn update_entity_chunk_positions( - mut query: Query< - ( - Entity, - &entity::Position, - &mut entity::LastSentPosition, - &entity::WorldName, - ), - Changed, - >, + mut query: Query<(Entity, &Position, &mut LastSentPosition, &InstanceName), Changed>, instance_container: Res, ) { for (entity, pos, last_pos, world_name) in query.iter_mut() { @@ -288,7 +256,7 @@ fn remove_despawned_entities_from_indexes( mut commands: Commands, mut entity_infos: ResMut, instance_container: Res, - query: Query<(Entity, &EntityUuid, &Position, &WorldName, &LoadedBy), Changed>, + query: Query<(Entity, &EntityUuid, &Position, &InstanceName, &LoadedBy), Changed>, ) { for (entity, uuid, position, world_name, loaded_by) in &query { let world_lock = instance_container.get(world_name).unwrap(); diff --git a/azalea-world/src/entity/mod.rs b/azalea-entity/src/lib.rs similarity index 93% rename from azalea-world/src/entity/mod.rs rename to azalea-entity/src/lib.rs index d1d29a5a..53e8bfdb 100644 --- a/azalea-world/src/entity/mod.rs +++ b/azalea-entity/src/lib.rs @@ -3,15 +3,18 @@ pub mod attributes; mod data; mod dimensions; +mod effects; +mod enchantments; mod info; pub mod metadata; - -use crate::ChunkStorage; +pub mod mining; +mod systems; use self::{attributes::AttributeInstance, metadata::Health}; pub use attributes::Attributes; use azalea_block::BlockState; use azalea_core::{BlockPos, ChunkPos, ResourceLocation, Vec3, AABB}; +use azalea_world::{ChunkStorage, InstanceName}; use bevy_ecs::{ bundle::Bundle, component::Component, @@ -23,23 +26,12 @@ pub use data::*; use derive_more::{Deref, DerefMut}; pub use dimensions::{update_bounding_box, EntityDimensions}; pub use info::{ - clamp_look_direction, EntityInfos, EntityPlugin, EntityUpdateSet, LoadedBy, PartialEntityInfos, + clamp_look_direction, EntityInfos, EntityPlugin, EntityUpdateSet, LoadedBy, RelativeEntityUpdate, }; use std::fmt::Debug; use uuid::Uuid; -/// An entity ID used by Minecraft. These are not guaranteed to be unique in -/// shared worlds, that's what [`Entity`] is for. -#[derive(Component, Copy, Clone, Debug, PartialEq, Eq, Deref, DerefMut)] -pub struct MinecraftEntityId(pub u32); -impl std::hash::Hash for MinecraftEntityId { - fn hash(&self, hasher: &mut H) { - hasher.write_u32(self.0); - } -} -impl nohash_hasher::IsEnabled for MinecraftEntityId {} - pub fn move_relative( physics: &mut Physics, direction: &LookDirection, @@ -197,11 +189,6 @@ impl From<&LastSentPosition> for BlockPos { } } -/// The name of the world the entity is in. If two entities share the same world -/// name, we assume they're in the same world. -#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)] -pub struct WorldName(pub ResourceLocation); - /// A component for entities that can jump. /// /// If this is true, the entity will try to jump every tick. (It's equivalent to @@ -303,7 +290,7 @@ pub struct EntityKind(pub azalea_registry::EntityKind); pub struct EntityBundle { pub kind: EntityKind, pub uuid: EntityUuid, - pub world_name: WorldName, + pub world_name: InstanceName, pub position: Position, pub last_sent_position: LastSentPosition, pub physics: Physics, @@ -311,6 +298,7 @@ pub struct EntityBundle { pub eye_height: EyeHeight, pub attributes: Attributes, pub jumping: Jumping, + pub fluid_on_eyes: FluidOnEyes, } impl EntityBundle { @@ -330,7 +318,7 @@ impl EntityBundle { Self { kind: EntityKind(kind), uuid: EntityUuid(uuid), - world_name: WorldName(world_name), + world_name: InstanceName(world_name), position: Position(pos), last_sent_position: LastSentPosition(pos), physics: Physics { @@ -359,6 +347,7 @@ impl EntityBundle { }, jumping: Jumping(false), + fluid_on_eyes: FluidOnEyes(azalea_registry::Fluid::Empty), } } } @@ -375,6 +364,9 @@ pub struct PlayerBundle { #[derive(Component)] pub struct Local; +#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)] +pub struct FluidOnEyes(azalea_registry::Fluid); + // #[cfg(test)] // mod tests { // use super::*; diff --git a/azalea-world/src/entity/metadata.rs b/azalea-entity/src/metadata.rs similarity index 99% rename from azalea-world/src/entity/metadata.rs rename to azalea-entity/src/metadata.rs index ed7aa40c..2f6a4870 100644 --- a/azalea-world/src/entity/metadata.rs +++ b/azalea-entity/src/metadata.rs @@ -8,7 +8,7 @@ use super::{ SnifferState, VillagerData, }; use azalea_chat::FormattedText; -use azalea_core::{BlockPos, Direction, Particle, Vec3}; +use azalea_core::{particle::Particle, BlockPos, Direction, Vec3}; use azalea_inventory::ItemSlot; use bevy_ecs::{bundle::Bundle, component::Component}; use derive_more::{Deref, DerefMut}; diff --git a/azalea-entity/src/mining.rs b/azalea-entity/src/mining.rs new file mode 100644 index 00000000..a2f869cf --- /dev/null +++ b/azalea-entity/src/mining.rs @@ -0,0 +1,170 @@ +use azalea_block::{Block, BlockBehavior}; +use azalea_core::tier::get_item_tier; +use azalea_registry as registry; + +use crate::{effects, enchantments, FluidOnEyes, Physics}; + +pub fn get_mine_progress( + block: &dyn Block, + held_item: registry::Item, + player_inventory: &azalea_inventory::Menu, + fluid_on_eyes: &FluidOnEyes, + physics: &Physics, +) -> f32 { + // public float getDestroyProgress(BlockState blockState, Player player, + // BlockGetter world, BlockPos blockPos) { float destroySpeed = + // blockState.getDestroySpeed(world, blockPos); if (destroySpeed == + // -1.0F) { return 0.0F; + // } else { + // int divider = player.hasCorrectToolForDrops(blockState) ? 30 : 100; + // return player.getDestroySpeed(blockState) / destroySpeed / + // (float)divider; } + // } + + let block_behavior: BlockBehavior = block.behavior(); + + let destroy_time = block_behavior.destroy_time; + if destroy_time == -1. { + return 0.; + } + let divider = if has_correct_tool_for_drops(block, held_item) { + 30 + } else { + 100 + }; + + (destroy_speed( + block.as_registry_block(), + held_item, + player_inventory, + fluid_on_eyes, + physics, + ) / destroy_time) + / divider as f32 +} + +fn has_correct_tool_for_drops(block: &dyn Block, tool: registry::Item) -> bool { + if !block.behavior().requires_correct_tool_for_drops { + return true; + } + let registry_block = block.as_registry_block(); + if tool == registry::Item::Shears { + matches!( + registry_block, + registry::Block::Cobweb | registry::Block::RedstoneWire | registry::Block::Tripwire + ) + } else if registry::tags::items::SWORDS.contains(&tool) { + registry_block == registry::Block::Cobweb + } else if registry::tags::items::PICKAXES.contains(&tool) + || registry::tags::items::SHOVELS.contains(&tool) + || registry::tags::items::HOES.contains(&tool) + || registry::tags::items::AXES.contains(&tool) + { + let tier = get_item_tier(tool).expect("all pickaxes and shovels should be matched"); + let tier_level = tier.level(); + !((tier_level < 3 && registry::tags::blocks::NEEDS_DIAMOND_TOOL.contains(®istry_block)) + || (tier_level < 2 + && registry::tags::blocks::NEEDS_IRON_TOOL.contains(®istry_block)) + || (tier_level < 1 + && registry::tags::blocks::NEEDS_STONE_TOOL.contains(®istry_block))) + } else { + false + } +} + +/// Returns the destroy speed of the given block with the given tool, taking +/// into account enchantments and effects. If the player is not holding anything +/// then `tool` should be `Item::Air`. +fn destroy_speed( + block: registry::Block, + tool: registry::Item, + player_inventory: &azalea_inventory::Menu, + fluid_on_eyes: &FluidOnEyes, + physics: &Physics, +) -> f32 { + let mut base_destroy_speed = base_destroy_speed(block, tool); + + // add efficiency enchantment + if base_destroy_speed > 1. { + let efficiency_level = + enchantments::get_enchant_level(registry::Enchantment::Efficiency, player_inventory); + if efficiency_level > 0 && tool != registry::Item::Air { + base_destroy_speed += (efficiency_level * efficiency_level + 1) as f32; + } + } + + if let Some(dig_speed_amplifier) = effects::get_dig_speed_amplifier() { + base_destroy_speed *= 1. + (dig_speed_amplifier + 1) as f32 * 0.2; + } + + if let Some(dig_slowdown) = effects::get_effect(registry::MobEffect::MiningFatigue) { + let multiplier = match dig_slowdown { + 0 => 0.3, + 1 => 0.09, + 2 => 0.0027, + _ => 8.1E-4, + }; + base_destroy_speed *= multiplier; + } + + if registry::tags::fluids::WATER.contains(fluid_on_eyes) + && enchantments::get_enchant_level(registry::Enchantment::AquaAffinity, player_inventory) + == 0 + { + base_destroy_speed /= 5.; + } + + if !physics.on_ground { + base_destroy_speed /= 5.; + } + + base_destroy_speed +} + +fn base_destroy_speed(block: registry::Block, tool: registry::Item) -> f32 { + if tool == registry::Item::Shears { + if block == registry::Block::Cobweb || registry::tags::blocks::LEAVES.contains(&block) { + 15. + } else if registry::tags::blocks::WOOL.contains(&block) { + 5. + } else if matches!(block, registry::Block::Vine | registry::Block::GlowLichen) { + 2. + } else { + 1. + } + } else if registry::tags::items::SWORDS.contains(&tool) { + if block == registry::Block::Cobweb { + 15. + } else if registry::tags::blocks::SWORD_EFFICIENT.contains(&block) { + 1.5 + } else { + 1. + } + } else if registry::tags::items::PICKAXES.contains(&tool) { + if registry::tags::blocks::MINEABLE_PICKAXE.contains(&block) { + get_item_tier(tool).unwrap().speed() + } else { + 1. + } + } else if registry::tags::items::SHOVELS.contains(&tool) { + if registry::tags::blocks::MINEABLE_SHOVEL.contains(&block) { + get_item_tier(tool).unwrap().speed() + } else { + 1. + } + } else if registry::tags::items::HOES.contains(&tool) { + if registry::tags::blocks::MINEABLE_HOE.contains(&block) { + get_item_tier(tool).unwrap().speed() + } else { + 1. + } + } else if registry::tags::items::AXES.contains(&tool) { + if registry::tags::blocks::MINEABLE_AXE.contains(&block) { + get_item_tier(tool).unwrap().speed() + } else { + 1. + } + } else { + 1. + } +} diff --git a/azalea-entity/src/systems.rs b/azalea-entity/src/systems.rs new file mode 100644 index 00000000..3fa8c4d5 --- /dev/null +++ b/azalea-entity/src/systems.rs @@ -0,0 +1,181 @@ +use azalea_core::{BlockPos, Vec3}; +use azalea_world::{InstanceContainer, InstanceName, MinecraftEntityId}; +use bevy_ecs::prelude::*; +use log::{debug, error, info}; + +use crate::{EntityInfos, EntityUuid, EyeHeight, FluidOnEyes, LoadedBy, Local, Position}; + +/// Remove new entities that have the same id as an existing entity, and +/// increase the reference counts. +/// +/// This is the reason why spawning entities into the ECS when you get a spawn +/// entity packet is okay. This system will make sure the new entity gets +/// combined into the old one. +#[allow(clippy::type_complexity)] +pub fn deduplicate_entities( + mut commands: Commands, + mut query: Query< + (Entity, &MinecraftEntityId, &InstanceName), + (Changed, Without), + >, + mut loaded_by_query: Query<&mut LoadedBy>, + instance_container: Res, +) { + // if this entity already exists, remove it + for (new_entity, id, world_name) in query.iter_mut() { + if let Some(world_lock) = instance_container.get(world_name) { + let world = world_lock.write(); + if let Some(old_entity) = world.entity_by_id.get(id) { + if old_entity == &new_entity { + continue; + } + + // this entity already exists!!! remove the one we just added but increase + // the reference count + let new_loaded_by = loaded_by_query + .get(new_entity) + .unwrap_or_else(|_| panic!( + "Entities should always have the LoadedBy component ({new_entity:?} did not)" + )) + .clone(); + let old_loaded_by = loaded_by_query.get_mut(*old_entity); + // merge them if possible + if let Ok(mut old_loaded_by) = old_loaded_by { + old_loaded_by.extend(new_loaded_by.iter()); + } + commands.entity(new_entity).despawn(); + info!( + "Entity with id {id:?} / {new_entity:?} already existed in the world, merging it with {old_entity:?}" + ); + break; + } + } else { + error!("Entity was inserted into a world that doesn't exist."); + } + } +} + +// when a local entity is added, if there was already an entity with the same id +// then delete the old entity +#[allow(clippy::type_complexity)] +pub fn deduplicate_local_entities( + mut commands: Commands, + mut query: Query< + (Entity, &MinecraftEntityId, &InstanceName), + (Changed, With), + >, + instance_container: Res, +) { + // if this entity already exists, remove the old one + for (new_entity, id, world_name) in query.iter_mut() { + if let Some(world_lock) = instance_container.get(world_name) { + let world = world_lock.write(); + if let Some(old_entity) = world.entity_by_id.get(id) { + if old_entity == &new_entity { + // lol + continue; + } + + commands.entity(*old_entity).despawn(); + debug!( + "Added local entity {id:?} / {new_entity:?} but already existed in world as {old_entity:?}, despawning {old_entity:?}" + ); + break; + } + } else { + error!("Entity was inserted into a world that doesn't exist."); + } + } +} + +pub fn update_uuid_index( + mut entity_infos: ResMut, + query: Query<(Entity, &EntityUuid, Option<&Local>), Changed>, +) { + for (entity, &uuid, local) in query.iter() { + // only add it if it doesn't already exist in + // entity_infos.entity_by_uuid + if local.is_none() { + if let Some(old_entity) = entity_infos.entity_by_uuid.get(&uuid) { + debug!( + "Entity with UUID {uuid:?} already existed in the world, not adding to + index (old ecs id: {old_entity:?} / new ecs id: {entity:?})" + ); + continue; + } + } + entity_infos.entity_by_uuid.insert(*uuid, entity); + } +} + +// /// Clear all entities in a chunk. This will not clear them from the +// /// shared storage unless there are no other references to them. +// pub fn clear_entities_in_chunk( +// mut commands: Commands, +// partial_entity_infos: &mut PartialEntityInfos, +// chunk: &ChunkPos, +// instance_container: &WorldContainer, +// world_name: &InstanceName, +// mut query: Query<(&MinecraftEntityId, &mut ReferenceCount)>, +// ) { let world_lock = instance_container.get(world_name).unwrap(); let world = +// world_lock.read(); + +// if let Some(entities) = world.entities_by_chunk.get(chunk).cloned() { +// for &entity in &entities { +// let (id, mut reference_count) = query.get_mut(entity).unwrap(); +// if partial_entity_infos.loaded_entity_ids.remove(id) { +// // decrease the reference count +// **reference_count -= 1; +// } +// } +// } +// } + +/// System to keep the entity_by_id index up-to-date. +pub fn update_entity_by_id_index( + mut query: Query< + (Entity, &MinecraftEntityId, &InstanceName, Option<&Local>), + Changed, + >, + instance_container: Res, +) { + for (entity, id, world_name, local) in query.iter_mut() { + let world_lock = instance_container.get(world_name).unwrap(); + let mut world = world_lock.write(); + if local.is_none() { + if let Some(old_entity) = world.entity_by_id.get(id) { + debug!( + "Entity with ID {id:?} already existed in the world, not adding to + index (old ecs id: {old_entity:?} / new ecs id: {entity:?})" + ); + continue; + } + } + world.entity_by_id.insert(*id, entity); + debug!("Added {entity:?} to {world_name:?} with {id:?}."); + } +} + +pub fn update_fluid_on_eyes( + mut query: Query<(&mut FluidOnEyes, &Position, &EyeHeight, &InstanceName)>, + instance_container: Res, +) { + for (mut fluid_on_eyes, position, eye_height, instance_name) in query.iter_mut() { + let Some(instance) = instance_container.get(instance_name) else { + continue; + }; + + let adjusted_eye_y = position.y + (**eye_height as f64) - 0.1111111119389534; + let eye_block_pos = BlockPos::from(Vec3::new(position.x, adjusted_eye_y, position.z)); + let fluid_at_eye = instance + .read() + .get_fluid_state(&eye_block_pos) + .unwrap_or_default(); + let fluid_cutoff_y = eye_block_pos.y as f64 + (fluid_at_eye.height as f64 / 16f64); + if fluid_cutoff_y > adjusted_eye_y { + **fluid_on_eyes = fluid_at_eye.fluid; + } else { + **fluid_on_eyes = azalea_registry::Fluid::Empty; + } + } +} diff --git a/azalea-inventory/src/lib.rs b/azalea-inventory/src/lib.rs index 29d06fd9..dbbf1f5c 100644 --- a/azalea-inventory/src/lib.rs +++ b/azalea-inventory/src/lib.rs @@ -10,8 +10,8 @@ use azalea_inventory_macros::declare_menus; pub use slot::{ItemSlot, ItemSlotData}; // TODO: remove this here and in azalea-inventory-macros when rust makes -// Default be implemented for all array sizes (since right now it's only up to -// 32) +// Default be implemented for all array sizes +// https://github.com/rust-lang/rust/issues/61415 /// A fixed-size list of [`ItemSlot`]s. #[derive(Debug, Clone)] diff --git a/azalea-physics/Cargo.toml b/azalea-physics/Cargo.toml index 7209420c..135681cc 100644 --- a/azalea-physics/Cargo.toml +++ b/azalea-physics/Cargo.toml @@ -11,6 +11,7 @@ version = "0.7.0" [dependencies] azalea-block = { path = "../azalea-block", version = "^0.7.0" } azalea-core = { path = "../azalea-core", version = "^0.7.0" } +azalea-entity = { version = "0.1.0", path = "../azalea-entity" } azalea-inventory = { version = "0.7.0", path = "../azalea-inventory" } azalea-registry = { path = "../azalea-registry", version = "^0.7.0" } azalea-world = { path = "../azalea-world", version = "^0.7.0" } diff --git a/azalea-physics/src/clip.rs b/azalea-physics/src/clip.rs index ca85c32a..d6e0f6bb 100644 --- a/azalea-physics/src/clip.rs +++ b/azalea-physics/src/clip.rs @@ -1,5 +1,5 @@ use azalea_block::BlockState; -use azalea_core::{lerp, BlockHitResult, BlockPos, Direction, Vec3, EPSILON}; +use azalea_core::{math::lerp, BlockHitResult, BlockPos, Direction, Vec3, EPSILON}; use azalea_inventory::ItemSlot; use azalea_world::ChunkStorage; use bevy_ecs::entity::Entity; diff --git a/azalea-physics/src/collision/mergers.rs b/azalea-physics/src/collision/mergers.rs index 483cb55f..e2381c49 100755 --- a/azalea-physics/src/collision/mergers.rs +++ b/azalea-physics/src/collision/mergers.rs @@ -1,7 +1,10 @@ use std::{cmp::Ordering, convert::TryInto}; use super::CubePointRange; -use azalea_core::{gcd, lcm, EPSILON}; +use azalea_core::{ + math::{gcd, lcm}, + EPSILON, +}; #[derive(Debug)] pub enum IndexMerger { diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index a99b5710..e24df378 100644 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -5,7 +5,7 @@ mod shape; mod world_collisions; use azalea_core::{Axis, Vec3, AABB, EPSILON}; -use azalea_world::{entity, Instance, MoveEntityError}; +use azalea_world::{Instance, MoveEntityError}; pub use blocks::BlockWithShape; pub use discrete_voxel_shape::*; pub use shape::*; @@ -49,7 +49,7 @@ pub enum MoverType { // return var4; // } -fn collide(movement: &Vec3, world: &Instance, physics: &entity::Physics) -> Vec3 { +fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics) -> Vec3 { let entity_bounding_box = physics.bounding_box; // TODO: get_entity_collisions // let entity_collisions = world.get_entity_collisions(self, @@ -71,8 +71,8 @@ pub fn move_colliding( _mover_type: &MoverType, movement: &Vec3, world: &Instance, - position: &mut entity::Position, - physics: &mut entity::Physics, + position: &mut azalea_entity::Position, + physics: &mut azalea_entity::Physics, ) -> Result<(), MoveEntityError> { // TODO: do all these @@ -122,7 +122,7 @@ pub fn move_colliding( // TODO: minecraft checks for a "minor" horizontal collision here - let _block_pos_below = entity::on_pos_legacy(&world.chunks, position); + let _block_pos_below = azalea_entity::on_pos_legacy(&world.chunks, position); // let _block_state_below = self // .world // .get_block_state(&block_pos_below) diff --git a/azalea-physics/src/collision/shape.rs b/azalea-physics/src/collision/shape.rs index 29c1b440..a39a86cf 100755 --- a/azalea-physics/src/collision/shape.rs +++ b/azalea-physics/src/collision/shape.rs @@ -1,7 +1,7 @@ use super::mergers::IndexMerger; use crate::collision::{BitSetDiscreteVoxelShape, DiscreteVoxelShape, AABB}; use azalea_core::{ - binary_search, Axis, AxisCycle, BlockHitResult, BlockPos, Direction, Vec3, EPSILON, + math::binary_search, Axis, AxisCycle, BlockHitResult, BlockPos, Direction, Vec3, EPSILON, }; use std::{cmp, num::NonZeroU32}; diff --git a/azalea-physics/src/collision/world_collisions.rs b/azalea-physics/src/collision/world_collisions.rs index aa55150e..e640f0ce 100644 --- a/azalea-physics/src/collision/world_collisions.rs +++ b/azalea-physics/src/collision/world_collisions.rs @@ -71,9 +71,7 @@ impl<'a> Iterator for BlockCollisions<'a> { } let chunk = self.get_chunk(item.pos.x, item.pos.z); - let Some(chunk) = chunk else { - continue - }; + let Some(chunk) = chunk else { continue }; let pos = item.pos; let block_state: BlockState = chunk diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 0d9f3be4..6b451dd6 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -6,13 +6,12 @@ pub mod collision; use azalea_block::{Block, BlockState}; use azalea_core::{BlockPos, Vec3}; -use azalea_world::{ - entity::{ - clamp_look_direction, metadata::Sprinting, move_relative, Attributes, Jumping, Local, - LookDirection, Physics, Position, WorldName, - }, - Instance, InstanceContainer, +use azalea_entity::update_bounding_box; +use azalea_entity::{ + clamp_look_direction, metadata::Sprinting, move_relative, Attributes, Jumping, Local, + LookDirection, Physics, Position, }; +use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_app::{App, FixedUpdate, Plugin, Update}; use bevy_ecs::{ entity::Entity, @@ -35,7 +34,7 @@ impl Plugin for PhysicsPlugin { .add_systems( Update, force_jump_listener - .before(azalea_world::entity::update_bounding_box) + .before(update_bounding_box) .after(clamp_look_direction), ) .add_systems(FixedUpdate, (ai_step, travel).chain().in_set(PhysicsSet)); @@ -51,7 +50,7 @@ fn travel( &mut LookDirection, &mut Position, &Attributes, - &WorldName, + &InstanceName, ), With, >, @@ -176,7 +175,7 @@ pub fn force_jump_listener( &Position, &LookDirection, &Sprinting, - &WorldName, + &InstanceName, )>, instance_container: Res, mut events: EventReader, @@ -327,10 +326,8 @@ mod tests { use super::*; use azalea_core::{ChunkPos, ResourceLocation}; - use azalea_world::{ - entity::{EntityBundle, EntityPlugin, MinecraftEntityId}, - Chunk, PartialInstance, - }; + use azalea_entity::{EntityBundle, EntityPlugin}; + use azalea_world::{Chunk, MinecraftEntityId, PartialInstance}; use bevy_app::App; use bevy_time::fixed_timestep::FixedTime; use uuid::Uuid; diff --git a/azalea-protocol/Cargo.toml b/azalea-protocol/Cargo.toml index ebe49e64..50e6bbae 100644 --- a/azalea-protocol/Cargo.toml +++ b/azalea-protocol/Cargo.toml @@ -25,6 +25,7 @@ azalea-core = { path = "../azalea-core", optional = true, version = "^0.7.0", fe "serde", ] } azalea-crypto = { path = "../azalea-crypto", version = "^0.7.0" } +azalea-entity = { version = "0.1.0", path = "../azalea-entity" } azalea-inventory = { version = "0.7.0", path = "../azalea-inventory" } azalea-nbt = { path = "../azalea-nbt", version = "^0.7.0", features = [ "serde", 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 75f3f4dc..0f2686e6 100755 --- a/azalea-protocol/src/packets/game/clientbound_add_entity_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_add_entity_packet.rs @@ -1,7 +1,7 @@ use azalea_buf::McBuf; use azalea_core::{ResourceLocation, Vec3}; +use azalea_entity::{metadata::apply_default_metadata, EntityBundle}; use azalea_protocol_macros::ClientboundGamePacket; -use azalea_world::entity::{metadata::apply_default_metadata, EntityBundle}; use uuid::Uuid; #[derive(Clone, Debug, McBuf, ClientboundGamePacket)] diff --git a/azalea-protocol/src/packets/game/clientbound_add_player_packet.rs b/azalea-protocol/src/packets/game/clientbound_add_player_packet.rs index 4cbeb1b9..45ab4584 100755 --- a/azalea-protocol/src/packets/game/clientbound_add_player_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_add_player_packet.rs @@ -1,8 +1,8 @@ use azalea_buf::McBuf; use azalea_core::{ResourceLocation, Vec3}; +use azalea_entity::{metadata::PlayerMetadataBundle, EntityBundle, PlayerBundle}; use azalea_protocol_macros::ClientboundGamePacket; use azalea_registry::EntityKind; -use azalea_world::entity::{metadata::PlayerMetadataBundle, EntityBundle, PlayerBundle}; use uuid::Uuid; /// This packet is sent by the server when a player comes into visible range, diff --git a/azalea-protocol/src/packets/game/clientbound_level_particles_packet.rs b/azalea-protocol/src/packets/game/clientbound_level_particles_packet.rs index 6efe1f97..7cae607e 100755 --- a/azalea-protocol/src/packets/game/clientbound_level_particles_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_level_particles_packet.rs @@ -1,5 +1,5 @@ use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable}; -use azalea_core::ParticleData; +use azalea_core::particle::ParticleData; use azalea_protocol_macros::ClientboundGamePacket; use std::io::{Cursor, Write}; diff --git a/azalea-protocol/src/packets/game/clientbound_set_entity_data_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_entity_data_packet.rs index d133eeea..7d869650 100755 --- a/azalea-protocol/src/packets/game/clientbound_set_entity_data_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_set_entity_data_packet.rs @@ -1,6 +1,6 @@ use azalea_buf::McBuf; +use azalea_entity::EntityMetadataItems; use azalea_protocol_macros::ClientboundGamePacket; -use azalea_world::entity::EntityMetadataItems; #[derive(Clone, Debug, McBuf, ClientboundGamePacket)] pub struct ClientboundSetEntityDataPacket { diff --git a/azalea-protocol/src/packets/game/clientbound_update_attributes_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_attributes_packet.rs index 4c24ba64..1468a77f 100755 --- a/azalea-protocol/src/packets/game/clientbound_update_attributes_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_attributes_packet.rs @@ -1,7 +1,7 @@ use azalea_buf::McBuf; use azalea_core::ResourceLocation; +use azalea_entity::attributes::AttributeModifier; use azalea_protocol_macros::ClientboundGamePacket; -use azalea_world::entity::attributes::AttributeModifier; #[derive(Clone, Debug, McBuf, ClientboundGamePacket)] pub struct ClientboundUpdateAttributesPacket { diff --git a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs index 8c24bdbe..7acffb7a 100755 --- a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs @@ -221,10 +221,12 @@ impl McBufWritable for Recipe { impl McBufReadable for Recipe { fn read_from(buf: &mut Cursor<&[u8]>) -> Result { let recipe_serializer_name = ResourceLocation::read_from(buf)?; - let Ok(recipe_serializer) = - RecipeSerializer::from_str(&recipe_serializer_name.to_string()) else { - return Err(BufReadError::UnexpectedStringEnumVariant { id: recipe_serializer_name.to_string() }); - }; + let Ok(recipe_serializer) = RecipeSerializer::from_str(&recipe_serializer_name.to_string()) + else { + return Err(BufReadError::UnexpectedStringEnumVariant { + id: recipe_serializer_name.to_string(), + }); + }; let identifier = ResourceLocation::read_from(buf)?; // rust doesn't let us match ResourceLocation so we have to do a big diff --git a/azalea-registry/Cargo.toml b/azalea-registry/Cargo.toml index af36946f..8046894b 100644 --- a/azalea-registry/Cargo.toml +++ b/azalea-registry/Cargo.toml @@ -11,6 +11,7 @@ version = "0.7.0" [dependencies] azalea-buf = { path = "../azalea-buf", version = "^0.7.0" } azalea-registry-macros = { path = "./azalea-registry-macros", version = "^0.7.0" } +once_cell = "1.18.0" serde = { version = "^1.0", optional = true } [features] diff --git a/azalea-registry/src/lib.rs b/azalea-registry/src/lib.rs index 081b3c3e..c1edcd3f 100755 --- a/azalea-registry/src/lib.rs +++ b/azalea-registry/src/lib.rs @@ -5,6 +5,8 @@ // auto-generated (so you can add doc comments to the registry enums if you // want) +pub mod tags; + use std::io::{Cursor, Write}; use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable}; diff --git a/azalea-registry/src/tags/blocks.rs b/azalea-registry/src/tags/blocks.rs new file mode 100644 index 00000000..aae39c07 --- /dev/null +++ b/azalea-registry/src/tags/blocks.rs @@ -0,0 +1,3374 @@ +// This file was generated by codegen/lib/code/tags.py, don't edit it manually! + +use std::collections::HashSet; + +use once_cell::sync::Lazy; + +use crate::Block; + +pub static MINEABLE_SHOVEL: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Clay, + Block::Dirt, + Block::CoarseDirt, + Block::Podzol, + Block::Farmland, + Block::GrassBlock, + Block::Gravel, + Block::Mycelium, + Block::Sand, + Block::RedSand, + Block::SnowBlock, + Block::Snow, + Block::SoulSand, + Block::DirtPath, + Block::WhiteConcretePowder, + Block::OrangeConcretePowder, + Block::MagentaConcretePowder, + Block::LightBlueConcretePowder, + Block::YellowConcretePowder, + Block::LimeConcretePowder, + Block::PinkConcretePowder, + Block::GrayConcretePowder, + Block::LightGrayConcretePowder, + Block::CyanConcretePowder, + Block::PurpleConcretePowder, + Block::BlueConcretePowder, + Block::BrownConcretePowder, + Block::GreenConcretePowder, + Block::RedConcretePowder, + Block::BlackConcretePowder, + Block::SoulSoil, + Block::RootedDirt, + Block::MuddyMangroveRoots, + Block::Mud, + Block::SuspiciousSand, + Block::SuspiciousGravel, + ]) +}); +pub static MINEABLE_AXE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::NoteBlock, + Block::AttachedMelonStem, + Block::AttachedPumpkinStem, + Block::Azalea, + Block::Bamboo, + Block::Barrel, + Block::BeeNest, + Block::Beehive, + Block::Beetroots, + Block::BigDripleafStem, + Block::BigDripleaf, + Block::Bookshelf, + Block::BrownMushroomBlock, + Block::BrownMushroom, + Block::Campfire, + Block::Carrots, + Block::CartographyTable, + Block::CarvedPumpkin, + Block::CaveVinesPlant, + Block::CaveVines, + Block::Chest, + Block::ChorusFlower, + Block::ChorusPlant, + Block::Cocoa, + Block::Composter, + Block::CraftingTable, + Block::CrimsonFungus, + Block::DaylightDetector, + Block::DeadBush, + Block::Fern, + Block::FletchingTable, + Block::GlowLichen, + Block::Grass, + Block::HangingRoots, + Block::JackOLantern, + Block::Jukebox, + Block::Ladder, + Block::LargeFern, + Block::Lectern, + Block::LilyPad, + Block::Loom, + Block::MelonStem, + Block::Melon, + Block::MushroomStem, + Block::NetherWart, + Block::Potatoes, + Block::PumpkinStem, + Block::Pumpkin, + Block::RedMushroomBlock, + Block::RedMushroom, + Block::Scaffolding, + Block::SmallDripleaf, + Block::SmithingTable, + Block::SoulCampfire, + Block::SporeBlossom, + Block::SugarCane, + Block::SweetBerryBush, + Block::TallGrass, + Block::TrappedChest, + Block::TwistingVinesPlant, + Block::TwistingVines, + Block::Vine, + Block::WarpedFungus, + Block::WeepingVinesPlant, + Block::WeepingVines, + Block::Wheat, + Block::MangroveRoots, + Block::BambooMosaic, + Block::BambooMosaicSlab, + Block::BambooMosaicStairs, + Block::ChiseledBookshelf, + Block::WhiteBanner, + Block::OrangeBanner, + Block::MagentaBanner, + Block::LightBlueBanner, + Block::YellowBanner, + Block::LimeBanner, + Block::PinkBanner, + Block::GrayBanner, + Block::LightGrayBanner, + Block::CyanBanner, + Block::PurpleBanner, + Block::BlueBanner, + Block::BrownBanner, + Block::GreenBanner, + Block::RedBanner, + Block::BlackBanner, + Block::WhiteWallBanner, + Block::OrangeWallBanner, + Block::MagentaWallBanner, + Block::LightBlueWallBanner, + Block::YellowWallBanner, + Block::LimeWallBanner, + Block::PinkWallBanner, + Block::GrayWallBanner, + Block::LightGrayWallBanner, + Block::CyanWallBanner, + Block::PurpleWallBanner, + Block::BlueWallBanner, + Block::BrownWallBanner, + Block::GreenWallBanner, + Block::RedWallBanner, + Block::BlackWallBanner, + Block::AcaciaFenceGate, + Block::BirchFenceGate, + Block::DarkOakFenceGate, + Block::JungleFenceGate, + Block::OakFenceGate, + Block::SpruceFenceGate, + Block::CrimsonFenceGate, + Block::WarpedFenceGate, + Block::MangroveFenceGate, + Block::BambooFenceGate, + Block::CherryFenceGate, + Block::OakPlanks, + Block::SprucePlanks, + Block::BirchPlanks, + Block::JunglePlanks, + Block::AcaciaPlanks, + Block::DarkOakPlanks, + Block::CrimsonPlanks, + Block::WarpedPlanks, + Block::MangrovePlanks, + Block::BambooPlanks, + Block::CherryPlanks, + Block::OakSapling, + Block::SpruceSapling, + Block::BirchSapling, + Block::JungleSapling, + Block::AcaciaSapling, + Block::DarkOakSapling, + Block::Azalea, + Block::FloweringAzalea, + Block::MangrovePropagule, + Block::CherrySapling, + Block::OakButton, + Block::SpruceButton, + Block::BirchButton, + Block::JungleButton, + Block::AcaciaButton, + Block::DarkOakButton, + Block::CrimsonButton, + Block::WarpedButton, + Block::MangroveButton, + Block::BambooButton, + Block::CherryButton, + Block::OakDoor, + Block::SpruceDoor, + Block::BirchDoor, + Block::JungleDoor, + Block::AcaciaDoor, + Block::DarkOakDoor, + Block::CrimsonDoor, + Block::WarpedDoor, + Block::MangroveDoor, + Block::BambooDoor, + Block::CherryDoor, + Block::OakFence, + Block::AcaciaFence, + Block::DarkOakFence, + Block::SpruceFence, + Block::BirchFence, + Block::JungleFence, + Block::CrimsonFence, + Block::WarpedFence, + Block::MangroveFence, + Block::BambooFence, + Block::CherryFence, + Block::OakPressurePlate, + Block::SprucePressurePlate, + Block::BirchPressurePlate, + Block::JunglePressurePlate, + Block::AcaciaPressurePlate, + Block::DarkOakPressurePlate, + Block::CrimsonPressurePlate, + Block::WarpedPressurePlate, + Block::MangrovePressurePlate, + Block::BambooPressurePlate, + Block::CherryPressurePlate, + Block::OakSlab, + Block::SpruceSlab, + Block::BirchSlab, + Block::JungleSlab, + Block::AcaciaSlab, + Block::DarkOakSlab, + Block::CrimsonSlab, + Block::WarpedSlab, + Block::MangroveSlab, + Block::BambooSlab, + Block::CherrySlab, + Block::OakStairs, + Block::SpruceStairs, + Block::BirchStairs, + Block::JungleStairs, + Block::AcaciaStairs, + Block::DarkOakStairs, + Block::CrimsonStairs, + Block::WarpedStairs, + Block::MangroveStairs, + Block::BambooStairs, + Block::CherryStairs, + Block::AcaciaTrapdoor, + Block::BirchTrapdoor, + Block::DarkOakTrapdoor, + Block::JungleTrapdoor, + Block::OakTrapdoor, + Block::SpruceTrapdoor, + Block::CrimsonTrapdoor, + Block::WarpedTrapdoor, + Block::MangroveTrapdoor, + Block::BambooTrapdoor, + Block::CherryTrapdoor, + Block::BambooBlock, + Block::StrippedBambooBlock, + Block::CrimsonStem, + Block::StrippedCrimsonStem, + Block::CrimsonHyphae, + Block::StrippedCrimsonHyphae, + Block::WarpedStem, + Block::StrippedWarpedStem, + Block::WarpedHyphae, + Block::StrippedWarpedHyphae, + Block::OakSign, + Block::SpruceSign, + Block::BirchSign, + Block::AcaciaSign, + Block::JungleSign, + Block::DarkOakSign, + Block::CrimsonSign, + Block::WarpedSign, + Block::MangroveSign, + Block::BambooSign, + Block::CherrySign, + Block::OakWallSign, + Block::SpruceWallSign, + Block::BirchWallSign, + Block::AcaciaWallSign, + Block::JungleWallSign, + Block::DarkOakWallSign, + Block::CrimsonWallSign, + Block::WarpedWallSign, + Block::MangroveWallSign, + Block::BambooWallSign, + Block::CherryWallSign, + Block::OakHangingSign, + Block::SpruceHangingSign, + Block::BirchHangingSign, + Block::AcaciaHangingSign, + Block::CherryHangingSign, + Block::JungleHangingSign, + Block::DarkOakHangingSign, + Block::CrimsonHangingSign, + Block::WarpedHangingSign, + Block::MangroveHangingSign, + Block::BambooHangingSign, + Block::OakWallHangingSign, + Block::SpruceWallHangingSign, + Block::BirchWallHangingSign, + Block::AcaciaWallHangingSign, + Block::CherryWallHangingSign, + Block::JungleWallHangingSign, + Block::DarkOakWallHangingSign, + Block::CrimsonWallHangingSign, + Block::WarpedWallHangingSign, + Block::MangroveWallHangingSign, + Block::BambooWallHangingSign, + Block::DarkOakLog, + Block::DarkOakWood, + Block::StrippedDarkOakLog, + Block::StrippedDarkOakWood, + Block::OakLog, + Block::OakWood, + Block::StrippedOakLog, + Block::StrippedOakWood, + Block::AcaciaLog, + Block::AcaciaWood, + Block::StrippedAcaciaLog, + Block::StrippedAcaciaWood, + Block::BirchLog, + Block::BirchWood, + Block::StrippedBirchLog, + Block::StrippedBirchWood, + Block::JungleLog, + Block::JungleWood, + Block::StrippedJungleLog, + Block::StrippedJungleWood, + Block::SpruceLog, + Block::SpruceWood, + Block::StrippedSpruceLog, + Block::StrippedSpruceWood, + Block::MangroveLog, + Block::MangroveWood, + Block::StrippedMangroveLog, + Block::StrippedMangroveWood, + Block::CherryLog, + Block::CherryWood, + Block::StrippedCherryLog, + Block::StrippedCherryWood, + ]) +}); +pub static MINEABLE_HOE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::NetherWartBlock, + Block::WarpedWartBlock, + Block::HayBlock, + Block::DriedKelpBlock, + Block::Target, + Block::Shroomlight, + Block::Sponge, + Block::WetSponge, + Block::JungleLeaves, + Block::OakLeaves, + Block::SpruceLeaves, + Block::DarkOakLeaves, + Block::AcaciaLeaves, + Block::BirchLeaves, + Block::AzaleaLeaves, + Block::FloweringAzaleaLeaves, + Block::MangroveLeaves, + Block::SculkSensor, + Block::CalibratedSculkSensor, + Block::MossBlock, + Block::MossCarpet, + Block::Sculk, + Block::SculkCatalyst, + Block::SculkVein, + Block::SculkShrieker, + Block::PinkPetals, + Block::CherryLeaves, + ]) +}); +pub static MINEABLE_PICKAXE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Stone, + Block::Granite, + Block::PolishedGranite, + Block::Diorite, + Block::PolishedDiorite, + Block::Andesite, + Block::PolishedAndesite, + Block::Cobblestone, + Block::GoldOre, + Block::DeepslateGoldOre, + Block::IronOre, + Block::DeepslateIronOre, + Block::CoalOre, + Block::DeepslateCoalOre, + Block::NetherGoldOre, + Block::LapisOre, + Block::DeepslateLapisOre, + Block::LapisBlock, + Block::Dispenser, + Block::Sandstone, + Block::ChiseledSandstone, + Block::CutSandstone, + Block::GoldBlock, + Block::IronBlock, + Block::Bricks, + Block::MossyCobblestone, + Block::Obsidian, + Block::Spawner, + Block::DiamondOre, + Block::DeepslateDiamondOre, + Block::DiamondBlock, + Block::Furnace, + Block::CobblestoneStairs, + Block::StonePressurePlate, + Block::IronDoor, + Block::RedstoneOre, + Block::DeepslateRedstoneOre, + Block::Netherrack, + Block::Basalt, + Block::PolishedBasalt, + Block::StoneBricks, + Block::MossyStoneBricks, + Block::CrackedStoneBricks, + Block::ChiseledStoneBricks, + Block::IronBars, + Block::Chain, + Block::BrickStairs, + Block::StoneBrickStairs, + Block::NetherBricks, + Block::NetherBrickFence, + Block::NetherBrickStairs, + Block::EnchantingTable, + Block::BrewingStand, + Block::EndStone, + Block::SandstoneStairs, + Block::EmeraldOre, + Block::DeepslateEmeraldOre, + Block::EnderChest, + Block::EmeraldBlock, + Block::LightWeightedPressurePlate, + Block::HeavyWeightedPressurePlate, + Block::RedstoneBlock, + Block::NetherQuartzOre, + Block::Hopper, + Block::QuartzBlock, + Block::ChiseledQuartzBlock, + Block::QuartzPillar, + Block::QuartzStairs, + Block::Dropper, + Block::WhiteTerracotta, + Block::OrangeTerracotta, + Block::MagentaTerracotta, + Block::LightBlueTerracotta, + Block::YellowTerracotta, + Block::LimeTerracotta, + Block::PinkTerracotta, + Block::GrayTerracotta, + Block::LightGrayTerracotta, + Block::CyanTerracotta, + Block::PurpleTerracotta, + Block::BlueTerracotta, + Block::BrownTerracotta, + Block::GreenTerracotta, + Block::RedTerracotta, + Block::BlackTerracotta, + Block::IronTrapdoor, + Block::Prismarine, + Block::PrismarineBricks, + Block::DarkPrismarine, + Block::PrismarineStairs, + Block::PrismarineBrickStairs, + Block::DarkPrismarineStairs, + Block::PrismarineSlab, + Block::PrismarineBrickSlab, + Block::DarkPrismarineSlab, + Block::Terracotta, + Block::CoalBlock, + Block::RedSandstone, + Block::ChiseledRedSandstone, + Block::CutRedSandstone, + Block::RedSandstoneStairs, + Block::StoneSlab, + Block::SmoothStoneSlab, + Block::SandstoneSlab, + Block::CutSandstoneSlab, + Block::PetrifiedOakSlab, + Block::CobblestoneSlab, + Block::BrickSlab, + Block::StoneBrickSlab, + Block::NetherBrickSlab, + Block::QuartzSlab, + Block::RedSandstoneSlab, + Block::CutRedSandstoneSlab, + Block::PurpurSlab, + Block::SmoothStone, + Block::SmoothSandstone, + Block::SmoothQuartz, + Block::SmoothRedSandstone, + Block::PurpurBlock, + Block::PurpurPillar, + Block::PurpurStairs, + Block::EndStoneBricks, + Block::MagmaBlock, + Block::RedNetherBricks, + Block::BoneBlock, + Block::Observer, + Block::WhiteGlazedTerracotta, + Block::OrangeGlazedTerracotta, + Block::MagentaGlazedTerracotta, + Block::LightBlueGlazedTerracotta, + Block::YellowGlazedTerracotta, + Block::LimeGlazedTerracotta, + Block::PinkGlazedTerracotta, + Block::GrayGlazedTerracotta, + Block::LightGrayGlazedTerracotta, + Block::CyanGlazedTerracotta, + Block::PurpleGlazedTerracotta, + Block::BlueGlazedTerracotta, + Block::BrownGlazedTerracotta, + Block::GreenGlazedTerracotta, + Block::RedGlazedTerracotta, + Block::BlackGlazedTerracotta, + Block::WhiteConcrete, + Block::OrangeConcrete, + Block::MagentaConcrete, + Block::LightBlueConcrete, + Block::YellowConcrete, + Block::LimeConcrete, + Block::PinkConcrete, + Block::GrayConcrete, + Block::LightGrayConcrete, + Block::CyanConcrete, + Block::PurpleConcrete, + Block::BlueConcrete, + Block::BrownConcrete, + Block::GreenConcrete, + Block::RedConcrete, + Block::BlackConcrete, + Block::DeadTubeCoralBlock, + Block::DeadBrainCoralBlock, + Block::DeadBubbleCoralBlock, + Block::DeadFireCoralBlock, + Block::DeadHornCoralBlock, + Block::TubeCoralBlock, + Block::BrainCoralBlock, + Block::BubbleCoralBlock, + Block::FireCoralBlock, + Block::HornCoralBlock, + Block::DeadTubeCoral, + Block::DeadBrainCoral, + Block::DeadBubbleCoral, + Block::DeadFireCoral, + Block::DeadHornCoral, + Block::DeadTubeCoralFan, + Block::DeadBrainCoralFan, + Block::DeadBubbleCoralFan, + Block::DeadFireCoralFan, + Block::DeadHornCoralFan, + Block::DeadTubeCoralWallFan, + Block::DeadBrainCoralWallFan, + Block::DeadBubbleCoralWallFan, + Block::DeadFireCoralWallFan, + Block::DeadHornCoralWallFan, + Block::PolishedGraniteStairs, + Block::SmoothRedSandstoneStairs, + Block::MossyStoneBrickStairs, + Block::PolishedDioriteStairs, + Block::MossyCobblestoneStairs, + Block::EndStoneBrickStairs, + Block::StoneStairs, + Block::SmoothSandstoneStairs, + Block::SmoothQuartzStairs, + Block::GraniteStairs, + Block::AndesiteStairs, + Block::RedNetherBrickStairs, + Block::PolishedAndesiteStairs, + Block::DioriteStairs, + Block::PolishedGraniteSlab, + Block::SmoothRedSandstoneSlab, + Block::MossyStoneBrickSlab, + Block::PolishedDioriteSlab, + Block::MossyCobblestoneSlab, + Block::EndStoneBrickSlab, + Block::SmoothSandstoneSlab, + Block::SmoothQuartzSlab, + Block::GraniteSlab, + Block::AndesiteSlab, + Block::RedNetherBrickSlab, + Block::PolishedAndesiteSlab, + Block::DioriteSlab, + Block::Smoker, + Block::BlastFurnace, + Block::Grindstone, + Block::Stonecutter, + Block::Bell, + Block::Lantern, + Block::SoulLantern, + Block::WarpedNylium, + Block::CrimsonNylium, + Block::NetheriteBlock, + Block::AncientDebris, + Block::CryingObsidian, + Block::RespawnAnchor, + Block::Lodestone, + Block::Blackstone, + Block::BlackstoneStairs, + Block::BlackstoneSlab, + Block::PolishedBlackstone, + Block::PolishedBlackstoneBricks, + Block::CrackedPolishedBlackstoneBricks, + Block::ChiseledPolishedBlackstone, + Block::PolishedBlackstoneBrickSlab, + Block::PolishedBlackstoneBrickStairs, + Block::GildedBlackstone, + Block::PolishedBlackstoneStairs, + Block::PolishedBlackstoneSlab, + Block::PolishedBlackstonePressurePlate, + Block::ChiseledNetherBricks, + Block::CrackedNetherBricks, + Block::QuartzBricks, + Block::Tuff, + Block::Calcite, + Block::OxidizedCopper, + Block::WeatheredCopper, + Block::ExposedCopper, + Block::CopperBlock, + Block::CopperOre, + Block::DeepslateCopperOre, + Block::OxidizedCutCopper, + Block::WeatheredCutCopper, + Block::ExposedCutCopper, + Block::CutCopper, + Block::OxidizedCutCopperStairs, + Block::WeatheredCutCopperStairs, + Block::ExposedCutCopperStairs, + Block::CutCopperStairs, + Block::OxidizedCutCopperSlab, + Block::WeatheredCutCopperSlab, + Block::ExposedCutCopperSlab, + Block::CutCopperSlab, + Block::WaxedCopperBlock, + Block::WaxedWeatheredCopper, + Block::WaxedExposedCopper, + Block::WaxedOxidizedCopper, + Block::WaxedOxidizedCutCopper, + Block::WaxedWeatheredCutCopper, + Block::WaxedExposedCutCopper, + Block::WaxedCutCopper, + Block::WaxedOxidizedCutCopperStairs, + Block::WaxedWeatheredCutCopperStairs, + Block::WaxedExposedCutCopperStairs, + Block::WaxedCutCopperStairs, + Block::WaxedOxidizedCutCopperSlab, + Block::WaxedWeatheredCutCopperSlab, + Block::WaxedExposedCutCopperSlab, + Block::WaxedCutCopperSlab, + Block::LightningRod, + Block::PointedDripstone, + Block::DripstoneBlock, + Block::Deepslate, + Block::CobbledDeepslate, + Block::CobbledDeepslateStairs, + Block::CobbledDeepslateSlab, + Block::PolishedDeepslate, + Block::PolishedDeepslateStairs, + Block::PolishedDeepslateSlab, + Block::DeepslateTiles, + Block::DeepslateTileStairs, + Block::DeepslateTileSlab, + Block::DeepslateBricks, + Block::DeepslateBrickStairs, + Block::DeepslateBrickSlab, + Block::ChiseledDeepslate, + Block::CrackedDeepslateBricks, + Block::CrackedDeepslateTiles, + Block::SmoothBasalt, + Block::RawIronBlock, + Block::RawCopperBlock, + Block::RawGoldBlock, + Block::Ice, + Block::PackedIce, + Block::BlueIce, + Block::Piston, + Block::StickyPiston, + Block::PistonHead, + Block::AmethystCluster, + Block::SmallAmethystBud, + Block::MediumAmethystBud, + Block::LargeAmethystBud, + Block::AmethystBlock, + Block::BuddingAmethyst, + Block::InfestedCobblestone, + Block::InfestedChiseledStoneBricks, + Block::InfestedCrackedStoneBricks, + Block::InfestedDeepslate, + Block::InfestedStone, + Block::InfestedMossyStoneBricks, + Block::InfestedStoneBricks, + Block::Conduit, + Block::MudBricks, + Block::MudBrickStairs, + Block::MudBrickSlab, + Block::PackedMud, + Block::StoneButton, + Block::PolishedBlackstoneButton, + Block::CobblestoneWall, + Block::MossyCobblestoneWall, + Block::BrickWall, + Block::PrismarineWall, + Block::RedSandstoneWall, + Block::MossyStoneBrickWall, + Block::GraniteWall, + Block::StoneBrickWall, + Block::NetherBrickWall, + Block::AndesiteWall, + Block::RedNetherBrickWall, + Block::SandstoneWall, + Block::EndStoneBrickWall, + Block::DioriteWall, + Block::BlackstoneWall, + Block::PolishedBlackstoneBrickWall, + Block::PolishedBlackstoneWall, + Block::CobbledDeepslateWall, + Block::PolishedDeepslateWall, + Block::DeepslateTileWall, + Block::DeepslateBrickWall, + Block::MudBrickWall, + Block::ShulkerBox, + Block::BlackShulkerBox, + Block::BlueShulkerBox, + Block::BrownShulkerBox, + Block::CyanShulkerBox, + Block::GrayShulkerBox, + Block::GreenShulkerBox, + Block::LightBlueShulkerBox, + Block::LightGrayShulkerBox, + Block::LimeShulkerBox, + Block::MagentaShulkerBox, + Block::OrangeShulkerBox, + Block::PinkShulkerBox, + Block::PurpleShulkerBox, + Block::RedShulkerBox, + Block::WhiteShulkerBox, + Block::YellowShulkerBox, + Block::Anvil, + Block::ChippedAnvil, + Block::DamagedAnvil, + Block::Cauldron, + Block::WaterCauldron, + Block::LavaCauldron, + Block::PowderSnowCauldron, + Block::Rail, + Block::PoweredRail, + Block::DetectorRail, + Block::ActivatorRail, + ]) +}); +pub static WOODEN_FENCES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakFence, + Block::AcaciaFence, + Block::DarkOakFence, + Block::SpruceFence, + Block::BirchFence, + Block::JungleFence, + Block::CrimsonFence, + Block::WarpedFence, + Block::MangroveFence, + Block::BambooFence, + Block::CherryFence, + ]) +}); +pub static UNDERWATER_BONEMEALS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Seagrass, + Block::TubeCoralFan, + Block::BrainCoralFan, + Block::BubbleCoralFan, + Block::FireCoralFan, + Block::HornCoralFan, + Block::TubeCoralWallFan, + Block::BrainCoralWallFan, + Block::BubbleCoralWallFan, + Block::FireCoralWallFan, + Block::HornCoralWallFan, + Block::TubeCoral, + Block::BrainCoral, + Block::BubbleCoral, + Block::FireCoral, + Block::HornCoral, + ]) +}); +pub static INSIDE_STEP_SOUND_BLOCKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::PowderSnow, + Block::SculkVein, + Block::GlowLichen, + Block::LilyPad, + Block::SmallAmethystBud, + Block::PinkPetals, + ]) +}); +pub static ACACIA_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::AcaciaLog, + Block::AcaciaWood, + Block::StrippedAcaciaLog, + Block::StrippedAcaciaWood, + ]) +}); +pub static SMALL_DRIPLEAF_PLACEABLE: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Clay, Block::MossBlock])); +pub static WALL_CORALS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::TubeCoralWallFan, + Block::BrainCoralWallFan, + Block::BubbleCoralWallFan, + Block::FireCoralWallFan, + Block::HornCoralWallFan, + ]) +}); +pub static BAMBOO_PLANTABLE_ON: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Bamboo, + Block::BambooSapling, + Block::Gravel, + Block::SuspiciousGravel, + Block::Sand, + Block::RedSand, + Block::SuspiciousSand, + Block::SuspiciousSand, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + ]) +}); +pub static SWORD_EFFICIENT: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Grass, + Block::Fern, + Block::DeadBush, + Block::Vine, + Block::GlowLichen, + Block::Sunflower, + Block::Lilac, + Block::RoseBush, + Block::Peony, + Block::TallGrass, + Block::LargeFern, + Block::HangingRoots, + Block::PitcherPlant, + Block::BrownMushroom, + Block::RedMushroom, + Block::SugarCane, + Block::Pumpkin, + Block::CarvedPumpkin, + Block::JackOLantern, + Block::Melon, + Block::AttachedPumpkinStem, + Block::AttachedMelonStem, + Block::LilyPad, + Block::Cocoa, + Block::PitcherCrop, + Block::SweetBerryBush, + Block::CaveVines, + Block::CaveVinesPlant, + Block::SporeBlossom, + Block::MossCarpet, + Block::PinkPetals, + Block::BigDripleaf, + Block::BigDripleafStem, + Block::SmallDripleaf, + Block::NetherWart, + Block::WarpedFungus, + Block::WarpedRoots, + Block::NetherSprouts, + Block::CrimsonFungus, + Block::WeepingVines, + Block::WeepingVinesPlant, + Block::TwistingVines, + Block::TwistingVinesPlant, + Block::CrimsonRoots, + Block::ChorusPlant, + Block::ChorusFlower, + Block::JungleLeaves, + Block::OakLeaves, + Block::SpruceLeaves, + Block::DarkOakLeaves, + Block::AcaciaLeaves, + Block::BirchLeaves, + Block::AzaleaLeaves, + Block::FloweringAzaleaLeaves, + Block::MangroveLeaves, + Block::CherryLeaves, + Block::OakSapling, + Block::SpruceSapling, + Block::BirchSapling, + Block::JungleSapling, + Block::AcaciaSapling, + Block::DarkOakSapling, + Block::Azalea, + Block::FloweringAzalea, + Block::MangrovePropagule, + Block::CherrySapling, + Block::Dandelion, + Block::Poppy, + Block::BlueOrchid, + Block::Allium, + Block::AzureBluet, + Block::RedTulip, + Block::OrangeTulip, + Block::WhiteTulip, + Block::PinkTulip, + Block::OxeyeDaisy, + Block::Cornflower, + Block::LilyOfTheValley, + Block::WitherRose, + Block::Torchflower, + Block::Beetroots, + Block::Carrots, + Block::Potatoes, + Block::Wheat, + Block::MelonStem, + Block::PumpkinStem, + Block::TorchflowerCrop, + Block::PitcherCrop, + ]) +}); +pub static SNOW_LAYER_CANNOT_SURVIVE_ON: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Ice, Block::PackedIce, Block::Barrier])); +pub static MUSHROOM_GROW_BLOCK: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Mycelium, + Block::Podzol, + Block::CrimsonNylium, + Block::WarpedNylium, + ]) +}); +pub static DEAD_BUSH_MAY_PLACE_ON: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Sand, + Block::RedSand, + Block::SuspiciousSand, + Block::SuspiciousSand, + Block::Terracotta, + Block::WhiteTerracotta, + Block::OrangeTerracotta, + Block::MagentaTerracotta, + Block::LightBlueTerracotta, + Block::YellowTerracotta, + Block::LimeTerracotta, + Block::PinkTerracotta, + Block::GrayTerracotta, + Block::LightGrayTerracotta, + Block::CyanTerracotta, + Block::PurpleTerracotta, + Block::BlueTerracotta, + Block::BrownTerracotta, + Block::GreenTerracotta, + Block::RedTerracotta, + Block::BlackTerracotta, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + ]) +}); +pub static WOLVES_SPAWNABLE_ON: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::GrassBlock, Block::Snow, Block::SnowBlock])); +pub static LUSH_GROUND_REPLACEABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Clay, + Block::Gravel, + Block::Sand, + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + Block::CaveVinesPlant, + Block::CaveVines, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + ]) +}); +pub static PARROTS_SPAWNABLE_ON: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::GrassBlock, + Block::Air, + Block::JungleLeaves, + Block::OakLeaves, + Block::SpruceLeaves, + Block::DarkOakLeaves, + Block::AcaciaLeaves, + Block::BirchLeaves, + Block::AzaleaLeaves, + Block::FloweringAzaleaLeaves, + Block::MangroveLeaves, + Block::CherryLeaves, + Block::CrimsonStem, + Block::StrippedCrimsonStem, + Block::CrimsonHyphae, + Block::StrippedCrimsonHyphae, + Block::WarpedStem, + Block::StrippedWarpedStem, + Block::WarpedHyphae, + Block::StrippedWarpedHyphae, + Block::DarkOakLog, + Block::DarkOakWood, + Block::StrippedDarkOakLog, + Block::StrippedDarkOakWood, + Block::OakLog, + Block::OakWood, + Block::StrippedOakLog, + Block::StrippedOakWood, + Block::AcaciaLog, + Block::AcaciaWood, + Block::StrippedAcaciaLog, + Block::StrippedAcaciaWood, + Block::BirchLog, + Block::BirchWood, + Block::StrippedBirchLog, + Block::StrippedBirchWood, + Block::JungleLog, + Block::JungleWood, + Block::StrippedJungleLog, + Block::StrippedJungleWood, + Block::SpruceLog, + Block::SpruceWood, + Block::StrippedSpruceLog, + Block::StrippedSpruceWood, + Block::MangroveLog, + Block::MangroveWood, + Block::StrippedMangroveLog, + Block::StrippedMangroveWood, + Block::CherryLog, + Block::CherryWood, + Block::StrippedCherryLog, + Block::StrippedCherryWood, + ]) +}); +pub static WOODEN_SLABS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakSlab, + Block::SpruceSlab, + Block::BirchSlab, + Block::JungleSlab, + Block::AcaciaSlab, + Block::DarkOakSlab, + Block::CrimsonSlab, + Block::WarpedSlab, + Block::MangroveSlab, + Block::BambooSlab, + Block::CherrySlab, + ]) +}); +pub static WOODEN_STAIRS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakStairs, + Block::SpruceStairs, + Block::BirchStairs, + Block::JungleStairs, + Block::AcaciaStairs, + Block::DarkOakStairs, + Block::CrimsonStairs, + Block::WarpedStairs, + Block::MangroveStairs, + Block::BambooStairs, + Block::CherryStairs, + ]) +}); +pub static WALL_SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakWallSign, + Block::SpruceWallSign, + Block::BirchWallSign, + Block::AcaciaWallSign, + Block::JungleWallSign, + Block::DarkOakWallSign, + Block::CrimsonWallSign, + Block::WarpedWallSign, + Block::MangroveWallSign, + Block::BambooWallSign, + Block::CherryWallSign, + ]) +}); +pub static MANGROVE_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::MangroveLog, + Block::MangroveWood, + Block::StrippedMangroveLog, + Block::StrippedMangroveWood, + ]) +}); +pub static WITHER_IMMUNE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Barrier, + Block::Bedrock, + Block::EndPortal, + Block::EndPortalFrame, + Block::EndGateway, + Block::CommandBlock, + Block::RepeatingCommandBlock, + Block::ChainCommandBlock, + Block::StructureBlock, + Block::Jigsaw, + Block::MovingPiston, + Block::Light, + Block::ReinforcedDeepslate, + ]) +}); +pub static DARK_OAK_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::DarkOakLog, + Block::DarkOakWood, + Block::StrippedDarkOakLog, + Block::StrippedDarkOakWood, + ]) +}); +pub static STONE_ORE_REPLACEABLES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + ]) +}); +pub static EMERALD_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::EmeraldOre, Block::DeepslateEmeraldOre])); +pub static TALL_FLOWERS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Sunflower, + Block::Lilac, + Block::Peony, + Block::RoseBush, + Block::PitcherPlant, + ]) +}); +pub static BEE_GROWABLES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::SweetBerryBush, + Block::CaveVines, + Block::CaveVinesPlant, + Block::Beetroots, + Block::Carrots, + Block::Potatoes, + Block::Wheat, + Block::MelonStem, + Block::PumpkinStem, + Block::TorchflowerCrop, + Block::PitcherCrop, + ]) +}); +pub static DOORS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::IronDoor, + Block::OakDoor, + Block::SpruceDoor, + Block::BirchDoor, + Block::JungleDoor, + Block::AcaciaDoor, + Block::DarkOakDoor, + Block::CrimsonDoor, + Block::WarpedDoor, + Block::MangroveDoor, + Block::BambooDoor, + Block::CherryDoor, + ]) +}); +pub static BEDS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::RedBed, + Block::BlackBed, + Block::BlueBed, + Block::BrownBed, + Block::CyanBed, + Block::GrayBed, + Block::GreenBed, + Block::LightBlueBed, + Block::LightGrayBed, + Block::LimeBed, + Block::MagentaBed, + Block::OrangeBed, + Block::PinkBed, + Block::PurpleBed, + Block::WhiteBed, + Block::YellowBed, + ]) +}); +pub static BASE_STONE_OVERWORLD: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + ]) +}); +pub static SNIFFER_EGG_HATCH_BOOST: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::MossBlock])); +pub static VALID_SPAWN: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::GrassBlock, Block::Podzol])); +pub static NEEDS_STONE_TOOL: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::IronBlock, + Block::RawIronBlock, + Block::IronOre, + Block::DeepslateIronOre, + Block::LapisBlock, + Block::LapisOre, + Block::DeepslateLapisOre, + Block::CopperBlock, + Block::RawCopperBlock, + Block::CopperOre, + Block::DeepslateCopperOre, + Block::CutCopperSlab, + Block::CutCopperStairs, + Block::CutCopper, + Block::WeatheredCopper, + Block::WeatheredCutCopperSlab, + Block::WeatheredCutCopperStairs, + Block::WeatheredCutCopper, + Block::OxidizedCopper, + Block::OxidizedCutCopperSlab, + Block::OxidizedCutCopperStairs, + Block::OxidizedCutCopper, + Block::ExposedCopper, + Block::ExposedCutCopperSlab, + Block::ExposedCutCopperStairs, + Block::ExposedCutCopper, + Block::WaxedCopperBlock, + Block::WaxedCutCopperSlab, + Block::WaxedCutCopperStairs, + Block::WaxedCutCopper, + Block::WaxedWeatheredCopper, + Block::WaxedWeatheredCutCopperSlab, + Block::WaxedWeatheredCutCopperStairs, + Block::WaxedWeatheredCutCopper, + Block::WaxedExposedCopper, + Block::WaxedExposedCutCopperSlab, + Block::WaxedExposedCutCopperStairs, + Block::WaxedExposedCutCopper, + Block::WaxedOxidizedCopper, + Block::WaxedOxidizedCutCopperSlab, + Block::WaxedOxidizedCutCopperStairs, + Block::WaxedOxidizedCutCopper, + Block::LightningRod, + ]) +}); +pub static SNIFFER_DIGGABLE_BLOCK: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + ]) +}); +pub static ANCIENT_CITY_REPLACEABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Deepslate, + Block::DeepslateBricks, + Block::DeepslateTiles, + Block::DeepslateBrickSlab, + Block::DeepslateTileSlab, + Block::DeepslateBrickStairs, + Block::DeepslateTileWall, + Block::DeepslateBrickWall, + Block::CobbledDeepslate, + Block::CrackedDeepslateBricks, + Block::CrackedDeepslateTiles, + Block::GrayWool, + ]) +}); +pub static COPPER_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::CopperOre, Block::DeepslateCopperOre])); +pub static WOODEN_PRESSURE_PLATES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakPressurePlate, + Block::SprucePressurePlate, + Block::BirchPressurePlate, + Block::JunglePressurePlate, + Block::AcaciaPressurePlate, + Block::DarkOakPressurePlate, + Block::CrimsonPressurePlate, + Block::WarpedPressurePlate, + Block::MangrovePressurePlate, + Block::BambooPressurePlate, + Block::CherryPressurePlate, + ]) +}); +pub static NYLIUM: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::CrimsonNylium, Block::WarpedNylium])); +pub static FEATURES_CANNOT_REPLACE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Bedrock, + Block::Spawner, + Block::Chest, + Block::EndPortalFrame, + Block::ReinforcedDeepslate, + ]) +}); +pub static SAND: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Sand, + Block::RedSand, + Block::SuspiciousSand, + Block::SuspiciousSand, + ]) +}); +pub static LOGS_THAT_BURN: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::DarkOakLog, + Block::DarkOakWood, + Block::StrippedDarkOakLog, + Block::StrippedDarkOakWood, + Block::OakLog, + Block::OakWood, + Block::StrippedOakLog, + Block::StrippedOakWood, + Block::AcaciaLog, + Block::AcaciaWood, + Block::StrippedAcaciaLog, + Block::StrippedAcaciaWood, + Block::BirchLog, + Block::BirchWood, + Block::StrippedBirchLog, + Block::StrippedBirchWood, + Block::JungleLog, + Block::JungleWood, + Block::StrippedJungleLog, + Block::StrippedJungleWood, + Block::SpruceLog, + Block::SpruceWood, + Block::StrippedSpruceLog, + Block::StrippedSpruceWood, + Block::MangroveLog, + Block::MangroveWood, + Block::StrippedMangroveLog, + Block::StrippedMangroveWood, + Block::CherryLog, + Block::CherryWood, + Block::StrippedCherryLog, + Block::StrippedCherryWood, + ]) +}); +pub static CHERRY_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::CherryLog, + Block::CherryWood, + Block::StrippedCherryLog, + Block::StrippedCherryWood, + ]) +}); +pub static DAMPENS_VIBRATIONS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::WhiteWool, + Block::OrangeWool, + Block::MagentaWool, + Block::LightBlueWool, + Block::YellowWool, + Block::LimeWool, + Block::PinkWool, + Block::GrayWool, + Block::LightGrayWool, + Block::CyanWool, + Block::PurpleWool, + Block::BlueWool, + Block::BrownWool, + Block::GreenWool, + Block::RedWool, + Block::BlackWool, + Block::WhiteCarpet, + Block::OrangeCarpet, + Block::MagentaCarpet, + Block::LightBlueCarpet, + Block::YellowCarpet, + Block::LimeCarpet, + Block::PinkCarpet, + Block::GrayCarpet, + Block::LightGrayCarpet, + Block::CyanCarpet, + Block::PurpleCarpet, + Block::BlueCarpet, + Block::BrownCarpet, + Block::GreenCarpet, + Block::RedCarpet, + Block::BlackCarpet, + ]) +}); +pub static DIAMOND_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::DiamondOre, Block::DeepslateDiamondOre])); +pub static WOOL: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::WhiteWool, + Block::OrangeWool, + Block::MagentaWool, + Block::LightBlueWool, + Block::YellowWool, + Block::LimeWool, + Block::PinkWool, + Block::GrayWool, + Block::LightGrayWool, + Block::CyanWool, + Block::PurpleWool, + Block::BlueWool, + Block::BrownWool, + Block::GreenWool, + Block::RedWool, + Block::BlackWool, + ]) +}); +pub static FOXES_SPAWNABLE_ON: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::GrassBlock, + Block::Snow, + Block::SnowBlock, + Block::Podzol, + Block::CoarseDirt, + ]) +}); +pub static ALL_HANGING_SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakHangingSign, + Block::SpruceHangingSign, + Block::BirchHangingSign, + Block::AcaciaHangingSign, + Block::CherryHangingSign, + Block::JungleHangingSign, + Block::DarkOakHangingSign, + Block::CrimsonHangingSign, + Block::WarpedHangingSign, + Block::MangroveHangingSign, + Block::BambooHangingSign, + Block::OakWallHangingSign, + Block::SpruceWallHangingSign, + Block::BirchWallHangingSign, + Block::AcaciaWallHangingSign, + Block::CherryWallHangingSign, + Block::JungleWallHangingSign, + Block::DarkOakWallHangingSign, + Block::CrimsonWallHangingSign, + Block::WarpedWallHangingSign, + Block::MangroveWallHangingSign, + Block::BambooWallHangingSign, + ]) +}); +pub static WOODEN_TRAPDOORS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::AcaciaTrapdoor, + Block::BirchTrapdoor, + Block::DarkOakTrapdoor, + Block::JungleTrapdoor, + Block::OakTrapdoor, + Block::SpruceTrapdoor, + Block::CrimsonTrapdoor, + Block::WarpedTrapdoor, + Block::MangroveTrapdoor, + Block::BambooTrapdoor, + Block::CherryTrapdoor, + ]) +}); +pub static DRAGON_TRANSPARENT: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Light, Block::Fire, Block::SoulFire])); +pub static REPLACEABLE_BY_TREES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Grass, + Block::Fern, + Block::DeadBush, + Block::Vine, + Block::GlowLichen, + Block::Sunflower, + Block::Lilac, + Block::RoseBush, + Block::Peony, + Block::TallGrass, + Block::LargeFern, + Block::HangingRoots, + Block::PitcherPlant, + Block::Water, + Block::Seagrass, + Block::TallSeagrass, + Block::WarpedRoots, + Block::NetherSprouts, + Block::CrimsonRoots, + Block::JungleLeaves, + Block::OakLeaves, + Block::SpruceLeaves, + Block::DarkOakLeaves, + Block::AcaciaLeaves, + Block::BirchLeaves, + Block::AzaleaLeaves, + Block::FloweringAzaleaLeaves, + Block::MangroveLeaves, + Block::CherryLeaves, + ]) +}); +pub static FLOWERS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::FloweringAzaleaLeaves, + Block::FloweringAzalea, + Block::MangrovePropagule, + Block::CherryLeaves, + Block::PinkPetals, + Block::Dandelion, + Block::Poppy, + Block::BlueOrchid, + Block::Allium, + Block::AzureBluet, + Block::RedTulip, + Block::OrangeTulip, + Block::WhiteTulip, + Block::PinkTulip, + Block::OxeyeDaisy, + Block::Cornflower, + Block::LilyOfTheValley, + Block::WitherRose, + Block::Torchflower, + Block::Sunflower, + Block::Lilac, + Block::Peony, + Block::RoseBush, + Block::PitcherPlant, + ]) +}); +pub static FIRE: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Fire, Block::SoulFire])); +pub static CANDLE_CAKES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::CandleCake, + Block::WhiteCandleCake, + Block::OrangeCandleCake, + Block::MagentaCandleCake, + Block::LightBlueCandleCake, + Block::YellowCandleCake, + Block::LimeCandleCake, + Block::PinkCandleCake, + Block::GrayCandleCake, + Block::LightGrayCandleCake, + Block::CyanCandleCake, + Block::PurpleCandleCake, + Block::BlueCandleCake, + Block::BrownCandleCake, + Block::GreenCandleCake, + Block::RedCandleCake, + Block::BlackCandleCake, + ]) +}); +pub static BANNERS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::WhiteBanner, + Block::OrangeBanner, + Block::MagentaBanner, + Block::LightBlueBanner, + Block::YellowBanner, + Block::LimeBanner, + Block::PinkBanner, + Block::GrayBanner, + Block::LightGrayBanner, + Block::CyanBanner, + Block::PurpleBanner, + Block::BlueBanner, + Block::BrownBanner, + Block::GreenBanner, + Block::RedBanner, + Block::BlackBanner, + Block::WhiteWallBanner, + Block::OrangeWallBanner, + Block::MagentaWallBanner, + Block::LightBlueWallBanner, + Block::YellowWallBanner, + Block::LimeWallBanner, + Block::PinkWallBanner, + Block::GrayWallBanner, + Block::LightGrayWallBanner, + Block::CyanWallBanner, + Block::PurpleWallBanner, + Block::BlueWallBanner, + Block::BrownWallBanner, + Block::GreenWallBanner, + Block::RedWallBanner, + Block::BlackWallBanner, + ]) +}); +pub static TERRACOTTA: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Terracotta, + Block::WhiteTerracotta, + Block::OrangeTerracotta, + Block::MagentaTerracotta, + Block::LightBlueTerracotta, + Block::YellowTerracotta, + Block::LimeTerracotta, + Block::PinkTerracotta, + Block::GrayTerracotta, + Block::LightGrayTerracotta, + Block::CyanTerracotta, + Block::PurpleTerracotta, + Block::BlueTerracotta, + Block::BrownTerracotta, + Block::GreenTerracotta, + Block::RedTerracotta, + Block::BlackTerracotta, + ]) +}); +pub static BIRCH_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::BirchLog, + Block::BirchWood, + Block::StrippedBirchLog, + Block::StrippedBirchWood, + ]) +}); +pub static PIGLIN_REPELLENTS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::SoulFire, + Block::SoulTorch, + Block::SoulLantern, + Block::SoulWallTorch, + Block::SoulCampfire, + ]) +}); +pub static MANGROVE_LOGS_CAN_GROW_THROUGH: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Mud, + Block::MuddyMangroveRoots, + Block::MangroveRoots, + Block::MangroveLeaves, + Block::MangroveLog, + Block::MangrovePropagule, + Block::MossCarpet, + Block::Vine, + ]) +}); +pub static BEACON_BASE_BLOCKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::NetheriteBlock, + Block::EmeraldBlock, + Block::DiamondBlock, + Block::GoldBlock, + Block::IronBlock, + ]) +}); +pub static LAVA_POOL_STONE_CANNOT_REPLACE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Bedrock, + Block::Spawner, + Block::Chest, + Block::EndPortalFrame, + Block::ReinforcedDeepslate, + Block::JungleLeaves, + Block::OakLeaves, + Block::SpruceLeaves, + Block::DarkOakLeaves, + Block::AcaciaLeaves, + Block::BirchLeaves, + Block::AzaleaLeaves, + Block::FloweringAzaleaLeaves, + Block::MangroveLeaves, + Block::CherryLeaves, + Block::CrimsonStem, + Block::StrippedCrimsonStem, + Block::CrimsonHyphae, + Block::StrippedCrimsonHyphae, + Block::WarpedStem, + Block::StrippedWarpedStem, + Block::WarpedHyphae, + Block::StrippedWarpedHyphae, + Block::DarkOakLog, + Block::DarkOakWood, + Block::StrippedDarkOakLog, + Block::StrippedDarkOakWood, + Block::OakLog, + Block::OakWood, + Block::StrippedOakLog, + Block::StrippedOakWood, + Block::AcaciaLog, + Block::AcaciaWood, + Block::StrippedAcaciaLog, + Block::StrippedAcaciaWood, + Block::BirchLog, + Block::BirchWood, + Block::StrippedBirchLog, + Block::StrippedBirchWood, + Block::JungleLog, + Block::JungleWood, + Block::StrippedJungleLog, + Block::StrippedJungleWood, + Block::SpruceLog, + Block::SpruceWood, + Block::StrippedSpruceLog, + Block::StrippedSpruceWood, + Block::MangroveLog, + Block::MangroveWood, + Block::StrippedMangroveLog, + Block::StrippedMangroveWood, + Block::CherryLog, + Block::CherryWood, + Block::StrippedCherryLog, + Block::StrippedCherryWood, + ]) +}); +pub static OVERWORLD_CARVER_REPLACEABLES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Water, + Block::Gravel, + Block::SuspiciousGravel, + Block::Sandstone, + Block::RedSandstone, + Block::Calcite, + Block::Snow, + Block::PackedIce, + Block::RawIronBlock, + Block::RawCopperBlock, + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + Block::Sand, + Block::RedSand, + Block::SuspiciousSand, + Block::SuspiciousSand, + Block::Terracotta, + Block::WhiteTerracotta, + Block::OrangeTerracotta, + Block::MagentaTerracotta, + Block::LightBlueTerracotta, + Block::YellowTerracotta, + Block::LimeTerracotta, + Block::PinkTerracotta, + Block::GrayTerracotta, + Block::LightGrayTerracotta, + Block::CyanTerracotta, + Block::PurpleTerracotta, + Block::BlueTerracotta, + Block::BrownTerracotta, + Block::GreenTerracotta, + Block::RedTerracotta, + Block::BlackTerracotta, + Block::IronOre, + Block::DeepslateIronOre, + Block::CopperOre, + Block::DeepslateCopperOre, + ]) +}); +pub static STANDING_SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakSign, + Block::SpruceSign, + Block::BirchSign, + Block::AcaciaSign, + Block::JungleSign, + Block::DarkOakSign, + Block::CrimsonSign, + Block::WarpedSign, + Block::MangroveSign, + Block::BambooSign, + Block::CherrySign, + ]) +}); +pub static SLABS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::BambooMosaicSlab, + Block::StoneSlab, + Block::SmoothStoneSlab, + Block::StoneBrickSlab, + Block::SandstoneSlab, + Block::PurpurSlab, + Block::QuartzSlab, + Block::RedSandstoneSlab, + Block::BrickSlab, + Block::CobblestoneSlab, + Block::NetherBrickSlab, + Block::PetrifiedOakSlab, + Block::PrismarineSlab, + Block::PrismarineBrickSlab, + Block::DarkPrismarineSlab, + Block::PolishedGraniteSlab, + Block::SmoothRedSandstoneSlab, + Block::MossyStoneBrickSlab, + Block::PolishedDioriteSlab, + Block::MossyCobblestoneSlab, + Block::EndStoneBrickSlab, + Block::SmoothSandstoneSlab, + Block::SmoothQuartzSlab, + Block::GraniteSlab, + Block::AndesiteSlab, + Block::RedNetherBrickSlab, + Block::PolishedAndesiteSlab, + Block::DioriteSlab, + Block::CutSandstoneSlab, + Block::CutRedSandstoneSlab, + Block::BlackstoneSlab, + Block::PolishedBlackstoneBrickSlab, + Block::PolishedBlackstoneSlab, + Block::CobbledDeepslateSlab, + Block::PolishedDeepslateSlab, + Block::DeepslateTileSlab, + Block::DeepslateBrickSlab, + Block::WaxedWeatheredCutCopperSlab, + Block::WaxedExposedCutCopperSlab, + Block::WaxedCutCopperSlab, + Block::OxidizedCutCopperSlab, + Block::WeatheredCutCopperSlab, + Block::ExposedCutCopperSlab, + Block::CutCopperSlab, + Block::WaxedOxidizedCutCopperSlab, + Block::MudBrickSlab, + Block::OakSlab, + Block::SpruceSlab, + Block::BirchSlab, + Block::JungleSlab, + Block::AcaciaSlab, + Block::DarkOakSlab, + Block::CrimsonSlab, + Block::WarpedSlab, + Block::MangroveSlab, + Block::BambooSlab, + Block::CherrySlab, + ]) +}); +pub static ANVIL: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Anvil, Block::ChippedAnvil, Block::DamagedAnvil])); +pub static DRAGON_IMMUNE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Barrier, + Block::Bedrock, + Block::EndPortal, + Block::EndPortalFrame, + Block::EndGateway, + Block::CommandBlock, + Block::RepeatingCommandBlock, + Block::ChainCommandBlock, + Block::StructureBlock, + Block::Jigsaw, + Block::MovingPiston, + Block::Obsidian, + Block::CryingObsidian, + Block::EndStone, + Block::IronBars, + Block::RespawnAnchor, + Block::ReinforcedDeepslate, + ]) +}); +pub static STAIRS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::BambooMosaicStairs, + Block::CobblestoneStairs, + Block::SandstoneStairs, + Block::NetherBrickStairs, + Block::StoneBrickStairs, + Block::BrickStairs, + Block::PurpurStairs, + Block::QuartzStairs, + Block::RedSandstoneStairs, + Block::PrismarineBrickStairs, + Block::PrismarineStairs, + Block::DarkPrismarineStairs, + Block::PolishedGraniteStairs, + Block::SmoothRedSandstoneStairs, + Block::MossyStoneBrickStairs, + Block::PolishedDioriteStairs, + Block::MossyCobblestoneStairs, + Block::EndStoneBrickStairs, + Block::StoneStairs, + Block::SmoothSandstoneStairs, + Block::SmoothQuartzStairs, + Block::GraniteStairs, + Block::AndesiteStairs, + Block::RedNetherBrickStairs, + Block::PolishedAndesiteStairs, + Block::DioriteStairs, + Block::BlackstoneStairs, + Block::PolishedBlackstoneBrickStairs, + Block::PolishedBlackstoneStairs, + Block::CobbledDeepslateStairs, + Block::PolishedDeepslateStairs, + Block::DeepslateTileStairs, + Block::DeepslateBrickStairs, + Block::OxidizedCutCopperStairs, + Block::WeatheredCutCopperStairs, + Block::ExposedCutCopperStairs, + Block::CutCopperStairs, + Block::WaxedWeatheredCutCopperStairs, + Block::WaxedExposedCutCopperStairs, + Block::WaxedCutCopperStairs, + Block::WaxedOxidizedCutCopperStairs, + Block::MudBrickStairs, + Block::OakStairs, + Block::SpruceStairs, + Block::BirchStairs, + Block::JungleStairs, + Block::AcaciaStairs, + Block::DarkOakStairs, + Block::CrimsonStairs, + Block::WarpedStairs, + Block::MangroveStairs, + Block::BambooStairs, + Block::CherryStairs, + ]) +}); +pub static CAVE_VINES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::CaveVinesPlant, Block::CaveVines])); +pub static NEEDS_DIAMOND_TOOL: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Obsidian, + Block::CryingObsidian, + Block::NetheriteBlock, + Block::RespawnAnchor, + Block::AncientDebris, + ]) +}); +pub static ENDERMAN_HOLDABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Sand, + Block::RedSand, + Block::Gravel, + Block::BrownMushroom, + Block::RedMushroom, + Block::Tnt, + Block::Cactus, + Block::Clay, + Block::Pumpkin, + Block::CarvedPumpkin, + Block::Melon, + Block::CrimsonFungus, + Block::CrimsonNylium, + Block::CrimsonRoots, + Block::WarpedFungus, + Block::WarpedNylium, + Block::WarpedRoots, + Block::Dandelion, + Block::Poppy, + Block::BlueOrchid, + Block::Allium, + Block::AzureBluet, + Block::RedTulip, + Block::OrangeTulip, + Block::WhiteTulip, + Block::PinkTulip, + Block::OxeyeDaisy, + Block::Cornflower, + Block::LilyOfTheValley, + Block::WitherRose, + Block::Torchflower, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + ]) +}); +pub static ENCHANTMENT_POWER_TRANSMITTER: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Air, + Block::Water, + Block::Lava, + Block::Grass, + Block::Fern, + Block::DeadBush, + Block::Seagrass, + Block::TallSeagrass, + Block::Fire, + Block::SoulFire, + Block::Snow, + Block::Vine, + Block::GlowLichen, + Block::Light, + Block::TallGrass, + Block::LargeFern, + Block::StructureVoid, + Block::VoidAir, + Block::CaveAir, + Block::BubbleColumn, + Block::WarpedRoots, + Block::NetherSprouts, + Block::CrimsonRoots, + Block::HangingRoots, + ]) +}); +pub static INFINIBURN_END: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Bedrock, Block::Netherrack, Block::MagmaBlock])); +pub static SOUL_FIRE_BASE_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::SoulSand, Block::SoulSoil])); +pub static WOOL_CARPETS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::WhiteCarpet, + Block::OrangeCarpet, + Block::MagentaCarpet, + Block::LightBlueCarpet, + Block::YellowCarpet, + Block::LimeCarpet, + Block::PinkCarpet, + Block::GrayCarpet, + Block::LightGrayCarpet, + Block::CyanCarpet, + Block::PurpleCarpet, + Block::BlueCarpet, + Block::BrownCarpet, + Block::GreenCarpet, + Block::RedCarpet, + Block::BlackCarpet, + ]) +}); +pub static GOATS_SPAWNABLE_ON: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Stone, + Block::Snow, + Block::SnowBlock, + Block::PackedIce, + Block::Gravel, + Block::GrassBlock, + ]) +}); +pub static CORAL_BLOCKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::TubeCoralBlock, + Block::BrainCoralBlock, + Block::BubbleCoralBlock, + Block::FireCoralBlock, + Block::HornCoralBlock, + ]) +}); +pub static WOODEN_DOORS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakDoor, + Block::SpruceDoor, + Block::BirchDoor, + Block::JungleDoor, + Block::AcaciaDoor, + Block::DarkOakDoor, + Block::CrimsonDoor, + Block::WarpedDoor, + Block::MangroveDoor, + Block::BambooDoor, + Block::CherryDoor, + ]) +}); +pub static COAL_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::CoalOre, Block::DeepslateCoalOre])); +pub static BIG_DRIPLEAF_PLACEABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Farmland, + Block::Clay, + Block::MossBlock, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + ]) +}); +pub static BUTTONS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakButton, + Block::SpruceButton, + Block::BirchButton, + Block::JungleButton, + Block::AcaciaButton, + Block::DarkOakButton, + Block::CrimsonButton, + Block::WarpedButton, + Block::MangroveButton, + Block::BambooButton, + Block::CherryButton, + Block::StoneButton, + Block::PolishedBlackstoneButton, + ]) +}); +pub static GOLD_ORES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::GoldOre, + Block::NetherGoldOre, + Block::DeepslateGoldOre, + ]) +}); +pub static NEEDS_IRON_TOOL: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::DiamondBlock, + Block::DiamondOre, + Block::DeepslateDiamondOre, + Block::EmeraldOre, + Block::DeepslateEmeraldOre, + Block::EmeraldBlock, + Block::GoldBlock, + Block::RawGoldBlock, + Block::GoldOre, + Block::DeepslateGoldOre, + Block::RedstoneOre, + Block::DeepslateRedstoneOre, + ]) +}); +pub static UNSTABLE_BOTTOM_CENTER: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::AcaciaFenceGate, + Block::BirchFenceGate, + Block::DarkOakFenceGate, + Block::JungleFenceGate, + Block::OakFenceGate, + Block::SpruceFenceGate, + Block::CrimsonFenceGate, + Block::WarpedFenceGate, + Block::MangroveFenceGate, + Block::BambooFenceGate, + Block::CherryFenceGate, + ]) +}); +pub static CORALS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::TubeCoralFan, + Block::BrainCoralFan, + Block::BubbleCoralFan, + Block::FireCoralFan, + Block::HornCoralFan, + Block::TubeCoral, + Block::BrainCoral, + Block::BubbleCoral, + Block::FireCoral, + Block::HornCoral, + ]) +}); +pub static WART_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::NetherWartBlock, Block::WarpedWartBlock])); +pub static BEEHIVES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::BeeNest, Block::Beehive])); +pub static POLAR_BEARS_SPAWNABLE_ON_ALTERNATE: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Ice])); +pub static DEEPSLATE_ORE_REPLACEABLES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Deepslate, Block::Tuff])); +pub static SNAPS_GOAT_HORN: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Stone, + Block::PackedIce, + Block::IronOre, + Block::CoalOre, + Block::CopperOre, + Block::EmeraldOre, + Block::AcaciaLog, + Block::BirchLog, + Block::OakLog, + Block::JungleLog, + Block::SpruceLog, + Block::DarkOakLog, + Block::MangroveLog, + Block::CherryLog, + ]) +}); +pub static PREVENT_MOB_SPAWNING_INSIDE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Rail, + Block::PoweredRail, + Block::DetectorRail, + Block::ActivatorRail, + ]) +}); +pub static CONVERTABLE_TO_MUD: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Dirt, Block::CoarseDirt, Block::RootedDirt])); +pub static SOUL_SPEED_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::SoulSand, Block::SoulSoil])); +pub static OVERWORLD_NATURAL_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::AcaciaLog, + Block::BirchLog, + Block::OakLog, + Block::JungleLog, + Block::SpruceLog, + Block::DarkOakLog, + Block::MangroveLog, + Block::CherryLog, + ]) +}); +pub static CORAL_PLANTS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::TubeCoral, + Block::BrainCoral, + Block::BubbleCoral, + Block::FireCoral, + Block::HornCoral, + ]) +}); +pub static PORTALS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::NetherPortal, + Block::EndPortal, + Block::EndGateway, + ]) +}); +pub static SCULK_REPLACEABLE_WORLD_GEN: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::DeepslateBricks, + Block::DeepslateTiles, + Block::CobbledDeepslate, + Block::CrackedDeepslateBricks, + Block::CrackedDeepslateTiles, + Block::PolishedDeepslate, + Block::Sand, + Block::RedSand, + Block::Gravel, + Block::SoulSand, + Block::SoulSoil, + Block::Calcite, + Block::SmoothBasalt, + Block::Clay, + Block::DripstoneBlock, + Block::EndStone, + Block::RedSandstone, + Block::Sandstone, + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + Block::Terracotta, + Block::WhiteTerracotta, + Block::OrangeTerracotta, + Block::MagentaTerracotta, + Block::LightBlueTerracotta, + Block::YellowTerracotta, + Block::LimeTerracotta, + Block::PinkTerracotta, + Block::GrayTerracotta, + Block::LightGrayTerracotta, + Block::CyanTerracotta, + Block::PurpleTerracotta, + Block::BlueTerracotta, + Block::BrownTerracotta, + Block::GreenTerracotta, + Block::RedTerracotta, + Block::BlackTerracotta, + Block::CrimsonNylium, + Block::WarpedNylium, + Block::Netherrack, + Block::Basalt, + Block::Blackstone, + ]) +}); +pub static SHULKER_BOXES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::ShulkerBox, + Block::BlackShulkerBox, + Block::BlueShulkerBox, + Block::BrownShulkerBox, + Block::CyanShulkerBox, + Block::GrayShulkerBox, + Block::GreenShulkerBox, + Block::LightBlueShulkerBox, + Block::LightGrayShulkerBox, + Block::LimeShulkerBox, + Block::MagentaShulkerBox, + Block::OrangeShulkerBox, + Block::PinkShulkerBox, + Block::PurpleShulkerBox, + Block::RedShulkerBox, + Block::WhiteShulkerBox, + Block::YellowShulkerBox, + ]) +}); +pub static FENCES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::NetherBrickFence, + Block::OakFence, + Block::AcaciaFence, + Block::DarkOakFence, + Block::SpruceFence, + Block::BirchFence, + Block::JungleFence, + Block::CrimsonFence, + Block::WarpedFence, + Block::MangroveFence, + Block::BambooFence, + Block::CherryFence, + ]) +}); +pub static GEODE_INVALID_BLOCKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Bedrock, + Block::Water, + Block::Lava, + Block::Ice, + Block::PackedIce, + Block::BlueIce, + ]) +}); +pub static COMPLETES_FIND_TREE_TUTORIAL: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::JungleLeaves, + Block::OakLeaves, + Block::SpruceLeaves, + Block::DarkOakLeaves, + Block::AcaciaLeaves, + Block::BirchLeaves, + Block::AzaleaLeaves, + Block::FloweringAzaleaLeaves, + Block::MangroveLeaves, + Block::CherryLeaves, + Block::NetherWartBlock, + Block::WarpedWartBlock, + Block::CrimsonStem, + Block::StrippedCrimsonStem, + Block::CrimsonHyphae, + Block::StrippedCrimsonHyphae, + Block::WarpedStem, + Block::StrippedWarpedStem, + Block::WarpedHyphae, + Block::StrippedWarpedHyphae, + Block::DarkOakLog, + Block::DarkOakWood, + Block::StrippedDarkOakLog, + Block::StrippedDarkOakWood, + Block::OakLog, + Block::OakWood, + Block::StrippedOakLog, + Block::StrippedOakWood, + Block::AcaciaLog, + Block::AcaciaWood, + Block::StrippedAcaciaLog, + Block::StrippedAcaciaWood, + Block::BirchLog, + Block::BirchWood, + Block::StrippedBirchLog, + Block::StrippedBirchWood, + Block::JungleLog, + Block::JungleWood, + Block::StrippedJungleLog, + Block::StrippedJungleWood, + Block::SpruceLog, + Block::SpruceWood, + Block::StrippedSpruceLog, + Block::StrippedSpruceWood, + Block::MangroveLog, + Block::MangroveWood, + Block::StrippedMangroveLog, + Block::StrippedMangroveWood, + Block::CherryLog, + Block::CherryWood, + Block::StrippedCherryLog, + Block::StrippedCherryWood, + ]) +}); +pub static FROG_PREFER_JUMP_TO: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::LilyPad, Block::BigDripleaf])); +pub static INFINIBURN_OVERWORLD: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Netherrack, Block::MagmaBlock])); +pub static WITHER_SUMMON_BASE_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::SoulSand, Block::SoulSoil])); +pub static FALL_DAMAGE_RESETTING: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::SweetBerryBush, + Block::Cobweb, + Block::Ladder, + Block::Vine, + Block::Scaffolding, + Block::WeepingVines, + Block::WeepingVinesPlant, + Block::TwistingVines, + Block::TwistingVinesPlant, + Block::CaveVines, + Block::CaveVinesPlant, + ]) +}); +pub static SMALL_FLOWERS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Dandelion, + Block::Poppy, + Block::BlueOrchid, + Block::Allium, + Block::AzureBluet, + Block::RedTulip, + Block::OrangeTulip, + Block::WhiteTulip, + Block::PinkTulip, + Block::OxeyeDaisy, + Block::Cornflower, + Block::LilyOfTheValley, + Block::WitherRose, + Block::Torchflower, + ]) +}); +pub static CEILING_HANGING_SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakHangingSign, + Block::SpruceHangingSign, + Block::BirchHangingSign, + Block::AcaciaHangingSign, + Block::CherryHangingSign, + Block::JungleHangingSign, + Block::DarkOakHangingSign, + Block::CrimsonHangingSign, + Block::WarpedHangingSign, + Block::MangroveHangingSign, + Block::BambooHangingSign, + ]) +}); +pub static REPLACEABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Air, + Block::Water, + Block::Lava, + Block::Grass, + Block::Fern, + Block::DeadBush, + Block::Seagrass, + Block::TallSeagrass, + Block::Fire, + Block::SoulFire, + Block::Snow, + Block::Vine, + Block::GlowLichen, + Block::Light, + Block::TallGrass, + Block::LargeFern, + Block::StructureVoid, + Block::VoidAir, + Block::CaveAir, + Block::BubbleColumn, + Block::WarpedRoots, + Block::NetherSprouts, + Block::CrimsonRoots, + Block::HangingRoots, + ]) +}); +pub static STRIDER_WARM_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Lava])); +pub static ANIMALS_SPAWNABLE_ON: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::GrassBlock])); +pub static INVALID_SPAWN_INSIDE: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::EndPortal, Block::EndGateway])); +pub static FENCE_GATES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::AcaciaFenceGate, + Block::BirchFenceGate, + Block::DarkOakFenceGate, + Block::JungleFenceGate, + Block::OakFenceGate, + Block::SpruceFenceGate, + Block::CrimsonFenceGate, + Block::WarpedFenceGate, + Block::MangroveFenceGate, + Block::BambooFenceGate, + Block::CherryFenceGate, + ]) +}); +pub static GUARDED_BY_PIGLINS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::GoldBlock, + Block::Barrel, + Block::Chest, + Block::EnderChest, + Block::GildedBlackstone, + Block::TrappedChest, + Block::RawGoldBlock, + Block::ShulkerBox, + Block::BlackShulkerBox, + Block::BlueShulkerBox, + Block::BrownShulkerBox, + Block::CyanShulkerBox, + Block::GrayShulkerBox, + Block::GreenShulkerBox, + Block::LightBlueShulkerBox, + Block::LightGrayShulkerBox, + Block::LimeShulkerBox, + Block::MagentaShulkerBox, + Block::OrangeShulkerBox, + Block::PinkShulkerBox, + Block::PurpleShulkerBox, + Block::RedShulkerBox, + Block::WhiteShulkerBox, + Block::YellowShulkerBox, + Block::GoldOre, + Block::NetherGoldOre, + Block::DeepslateGoldOre, + ]) +}); +pub static AZALEA_GROWS_ON: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::SnowBlock, + Block::PowderSnow, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + Block::Sand, + Block::RedSand, + Block::SuspiciousSand, + Block::SuspiciousSand, + Block::Terracotta, + Block::WhiteTerracotta, + Block::OrangeTerracotta, + Block::MagentaTerracotta, + Block::LightBlueTerracotta, + Block::YellowTerracotta, + Block::LimeTerracotta, + Block::PinkTerracotta, + Block::GrayTerracotta, + Block::LightGrayTerracotta, + Block::CyanTerracotta, + Block::PurpleTerracotta, + Block::BlueTerracotta, + Block::BrownTerracotta, + Block::GreenTerracotta, + Block::RedTerracotta, + Block::BlackTerracotta, + ]) +}); +pub static OAK_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakLog, + Block::OakWood, + Block::StrippedOakLog, + Block::StrippedOakWood, + ]) +}); +pub static STONE_BRICKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::StoneBricks, + Block::MossyStoneBricks, + Block::CrackedStoneBricks, + Block::ChiseledStoneBricks, + ]) +}); +pub static LAPIS_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::LapisOre, Block::DeepslateLapisOre])); +pub static IMPERMEABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Glass, + Block::WhiteStainedGlass, + Block::OrangeStainedGlass, + Block::MagentaStainedGlass, + Block::LightBlueStainedGlass, + Block::YellowStainedGlass, + Block::LimeStainedGlass, + Block::PinkStainedGlass, + Block::GrayStainedGlass, + Block::LightGrayStainedGlass, + Block::CyanStainedGlass, + Block::PurpleStainedGlass, + Block::BlueStainedGlass, + Block::BrownStainedGlass, + Block::GreenStainedGlass, + Block::RedStainedGlass, + Block::BlackStainedGlass, + Block::TintedGlass, + ]) +}); +pub static ICE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Ice, + Block::PackedIce, + Block::BlueIce, + Block::FrostedIce, + ]) +}); +pub static ALL_SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakSign, + Block::SpruceSign, + Block::BirchSign, + Block::AcaciaSign, + Block::JungleSign, + Block::DarkOakSign, + Block::CrimsonSign, + Block::WarpedSign, + Block::MangroveSign, + Block::BambooSign, + Block::CherrySign, + Block::OakWallSign, + Block::SpruceWallSign, + Block::BirchWallSign, + Block::AcaciaWallSign, + Block::JungleWallSign, + Block::DarkOakWallSign, + Block::CrimsonWallSign, + Block::WarpedWallSign, + Block::MangroveWallSign, + Block::BambooWallSign, + Block::CherryWallSign, + Block::OakHangingSign, + Block::SpruceHangingSign, + Block::BirchHangingSign, + Block::AcaciaHangingSign, + Block::CherryHangingSign, + Block::JungleHangingSign, + Block::DarkOakHangingSign, + Block::CrimsonHangingSign, + Block::WarpedHangingSign, + Block::MangroveHangingSign, + Block::BambooHangingSign, + Block::OakWallHangingSign, + Block::SpruceWallHangingSign, + Block::BirchWallHangingSign, + Block::AcaciaWallHangingSign, + Block::CherryWallHangingSign, + Block::JungleWallHangingSign, + Block::DarkOakWallHangingSign, + Block::CrimsonWallHangingSign, + Block::WarpedWallHangingSign, + Block::MangroveWallHangingSign, + Block::BambooWallHangingSign, + ]) +}); +pub static SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakSign, + Block::SpruceSign, + Block::BirchSign, + Block::AcaciaSign, + Block::JungleSign, + Block::DarkOakSign, + Block::CrimsonSign, + Block::WarpedSign, + Block::MangroveSign, + Block::BambooSign, + Block::CherrySign, + Block::OakWallSign, + Block::SpruceWallSign, + Block::BirchWallSign, + Block::AcaciaWallSign, + Block::JungleWallSign, + Block::DarkOakWallSign, + Block::CrimsonWallSign, + Block::WarpedWallSign, + Block::MangroveWallSign, + Block::BambooWallSign, + Block::CherryWallSign, + ]) +}); +pub static INFINIBURN_NETHER: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Netherrack, Block::MagmaBlock])); +pub static NETHER_CARVER_REPLACEABLES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::SoulSand, + Block::SoulSoil, + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + Block::Netherrack, + Block::Basalt, + Block::Blackstone, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + Block::CrimsonNylium, + Block::WarpedNylium, + Block::NetherWartBlock, + Block::WarpedWartBlock, + ]) +}); +pub static CRYSTAL_SOUND_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::AmethystBlock, Block::BuddingAmethyst])); +pub static DIRT: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + ]) +}); +pub static MOOSHROOMS_SPAWNABLE_ON: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Mycelium])); +pub static PRESSURE_PLATES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::LightWeightedPressurePlate, + Block::HeavyWeightedPressurePlate, + Block::OakPressurePlate, + Block::SprucePressurePlate, + Block::BirchPressurePlate, + Block::JunglePressurePlate, + Block::AcaciaPressurePlate, + Block::DarkOakPressurePlate, + Block::CrimsonPressurePlate, + Block::WarpedPressurePlate, + Block::MangrovePressurePlate, + Block::BambooPressurePlate, + Block::CherryPressurePlate, + Block::StonePressurePlate, + Block::PolishedBlackstonePressurePlate, + ]) +}); +pub static LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::CrimsonStem, + Block::StrippedCrimsonStem, + Block::CrimsonHyphae, + Block::StrippedCrimsonHyphae, + Block::WarpedStem, + Block::StrippedWarpedStem, + Block::WarpedHyphae, + Block::StrippedWarpedHyphae, + Block::DarkOakLog, + Block::DarkOakWood, + Block::StrippedDarkOakLog, + Block::StrippedDarkOakWood, + Block::OakLog, + Block::OakWood, + Block::StrippedOakLog, + Block::StrippedOakWood, + Block::AcaciaLog, + Block::AcaciaWood, + Block::StrippedAcaciaLog, + Block::StrippedAcaciaWood, + Block::BirchLog, + Block::BirchWood, + Block::StrippedBirchLog, + Block::StrippedBirchWood, + Block::JungleLog, + Block::JungleWood, + Block::StrippedJungleLog, + Block::StrippedJungleWood, + Block::SpruceLog, + Block::SpruceWood, + Block::StrippedSpruceLog, + Block::StrippedSpruceWood, + Block::MangroveLog, + Block::MangroveWood, + Block::StrippedMangroveLog, + Block::StrippedMangroveWood, + Block::CherryLog, + Block::CherryWood, + Block::StrippedCherryLog, + Block::StrippedCherryWood, + ]) +}); +pub static MANGROVE_ROOTS_CAN_GROW_THROUGH: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Mud, + Block::MuddyMangroveRoots, + Block::MangroveRoots, + Block::MossCarpet, + Block::Vine, + Block::MangrovePropagule, + Block::Snow, + ]) +}); +pub static CLIMBABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Ladder, + Block::Vine, + Block::Scaffolding, + Block::WeepingVines, + Block::WeepingVinesPlant, + Block::TwistingVines, + Block::TwistingVinesPlant, + Block::CaveVines, + Block::CaveVinesPlant, + ]) +}); +pub static WOODEN_BUTTONS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakButton, + Block::SpruceButton, + Block::BirchButton, + Block::JungleButton, + Block::AcaciaButton, + Block::DarkOakButton, + Block::CrimsonButton, + Block::WarpedButton, + Block::MangroveButton, + Block::BambooButton, + Block::CherryButton, + ]) +}); +pub static ENCHANTMENT_POWER_PROVIDER: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Bookshelf])); +pub static CAULDRONS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Cauldron, + Block::WaterCauldron, + Block::LavaCauldron, + Block::PowderSnowCauldron, + ]) +}); +pub static SMELTS_TO_GLASS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Sand, Block::RedSand])); +pub static WALL_HANGING_SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakWallHangingSign, + Block::SpruceWallHangingSign, + Block::BirchWallHangingSign, + Block::AcaciaWallHangingSign, + Block::CherryWallHangingSign, + Block::JungleWallHangingSign, + Block::DarkOakWallHangingSign, + Block::CrimsonWallHangingSign, + Block::WarpedWallHangingSign, + Block::MangroveWallHangingSign, + Block::BambooWallHangingSign, + ]) +}); +pub static WALL_POST_OVERRIDE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Torch, + Block::SoulTorch, + Block::RedstoneTorch, + Block::Tripwire, + Block::WhiteBanner, + Block::OrangeBanner, + Block::MagentaBanner, + Block::LightBlueBanner, + Block::YellowBanner, + Block::LimeBanner, + Block::PinkBanner, + Block::GrayBanner, + Block::LightGrayBanner, + Block::CyanBanner, + Block::PurpleBanner, + Block::BlueBanner, + Block::BrownBanner, + Block::GreenBanner, + Block::RedBanner, + Block::BlackBanner, + Block::WhiteWallBanner, + Block::OrangeWallBanner, + Block::MagentaWallBanner, + Block::LightBlueWallBanner, + Block::YellowWallBanner, + Block::LimeWallBanner, + Block::PinkWallBanner, + Block::GrayWallBanner, + Block::LightGrayWallBanner, + Block::CyanWallBanner, + Block::PurpleWallBanner, + Block::BlueWallBanner, + Block::BrownWallBanner, + Block::GreenWallBanner, + Block::RedWallBanner, + Block::BlackWallBanner, + Block::LightWeightedPressurePlate, + Block::HeavyWeightedPressurePlate, + Block::OakSign, + Block::SpruceSign, + Block::BirchSign, + Block::AcaciaSign, + Block::JungleSign, + Block::DarkOakSign, + Block::CrimsonSign, + Block::WarpedSign, + Block::MangroveSign, + Block::BambooSign, + Block::CherrySign, + Block::OakWallSign, + Block::SpruceWallSign, + Block::BirchWallSign, + Block::AcaciaWallSign, + Block::JungleWallSign, + Block::DarkOakWallSign, + Block::CrimsonWallSign, + Block::WarpedWallSign, + Block::MangroveWallSign, + Block::BambooWallSign, + Block::CherryWallSign, + Block::OakPressurePlate, + Block::SprucePressurePlate, + Block::BirchPressurePlate, + Block::JunglePressurePlate, + Block::AcaciaPressurePlate, + Block::DarkOakPressurePlate, + Block::CrimsonPressurePlate, + Block::WarpedPressurePlate, + Block::MangrovePressurePlate, + Block::BambooPressurePlate, + Block::CherryPressurePlate, + Block::StonePressurePlate, + Block::PolishedBlackstonePressurePlate, + ]) +}); +pub static HOGLIN_REPELLENTS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::WarpedFungus, + Block::PottedWarpedFungus, + Block::NetherPortal, + Block::RespawnAnchor, + ]) +}); +pub static FLOWER_POTS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::FlowerPot, + Block::PottedPoppy, + Block::PottedBlueOrchid, + Block::PottedAllium, + Block::PottedAzureBluet, + Block::PottedRedTulip, + Block::PottedOrangeTulip, + Block::PottedWhiteTulip, + Block::PottedPinkTulip, + Block::PottedOxeyeDaisy, + Block::PottedDandelion, + Block::PottedOakSapling, + Block::PottedSpruceSapling, + Block::PottedBirchSapling, + Block::PottedJungleSapling, + Block::PottedAcaciaSapling, + Block::PottedDarkOakSapling, + Block::PottedRedMushroom, + Block::PottedBrownMushroom, + Block::PottedDeadBush, + Block::PottedFern, + Block::PottedCactus, + Block::PottedCornflower, + Block::PottedLilyOfTheValley, + Block::PottedWitherRose, + Block::PottedBamboo, + Block::PottedCrimsonFungus, + Block::PottedWarpedFungus, + Block::PottedCrimsonRoots, + Block::PottedWarpedRoots, + Block::PottedAzaleaBush, + Block::PottedFloweringAzaleaBush, + Block::PottedMangrovePropagule, + Block::PottedCherrySapling, + Block::PottedTorchflower, + ]) +}); +pub static JUNGLE_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::JungleLog, + Block::JungleWood, + Block::StrippedJungleLog, + Block::StrippedJungleWood, + ]) +}); +pub static DRIPSTONE_REPLACEABLE_BLOCKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + ]) +}); +pub static SNOW: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Snow, Block::SnowBlock, Block::PowderSnow])); +pub static TRAPDOORS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::IronTrapdoor, + Block::AcaciaTrapdoor, + Block::BirchTrapdoor, + Block::DarkOakTrapdoor, + Block::JungleTrapdoor, + Block::OakTrapdoor, + Block::SpruceTrapdoor, + Block::CrimsonTrapdoor, + Block::WarpedTrapdoor, + Block::MangroveTrapdoor, + Block::BambooTrapdoor, + Block::CherryTrapdoor, + ]) +}); +pub static AXOLOTLS_SPAWNABLE_ON: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Clay])); +pub static TRAIL_RUINS_REPLACEABLE: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Gravel])); +pub static WARPED_STEMS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::WarpedStem, + Block::StrippedWarpedStem, + Block::WarpedHyphae, + Block::StrippedWarpedHyphae, + ]) +}); +pub static SNOW_LAYER_CAN_SURVIVE_ON: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::HoneyBlock, Block::SoulSand, Block::Mud])); +pub static BASE_STONE_NETHER: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Netherrack, Block::Basalt, Block::Blackstone])); +pub static CAMPFIRES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::Campfire, Block::SoulCampfire])); +pub static IRON_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::IronOre, Block::DeepslateIronOre])); +pub static RAILS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Rail, + Block::PoweredRail, + Block::DetectorRail, + Block::ActivatorRail, + ]) +}); +pub static PLANKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakPlanks, + Block::SprucePlanks, + Block::BirchPlanks, + Block::JunglePlanks, + Block::AcaciaPlanks, + Block::DarkOakPlanks, + Block::CrimsonPlanks, + Block::WarpedPlanks, + Block::MangrovePlanks, + Block::BambooPlanks, + Block::CherryPlanks, + ]) +}); +pub static COMBINATION_STEP_SOUND_BLOCKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::MossCarpet, + Block::Snow, + Block::NetherSprouts, + Block::WarpedRoots, + Block::CrimsonRoots, + Block::WhiteCarpet, + Block::OrangeCarpet, + Block::MagentaCarpet, + Block::LightBlueCarpet, + Block::YellowCarpet, + Block::LimeCarpet, + Block::PinkCarpet, + Block::GrayCarpet, + Block::LightGrayCarpet, + Block::CyanCarpet, + Block::PurpleCarpet, + Block::BlueCarpet, + Block::BrownCarpet, + Block::GreenCarpet, + Block::RedCarpet, + Block::BlackCarpet, + ]) +}); +pub static SCULK_REPLACEABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Sand, + Block::RedSand, + Block::Gravel, + Block::SoulSand, + Block::SoulSoil, + Block::Calcite, + Block::SmoothBasalt, + Block::Clay, + Block::DripstoneBlock, + Block::EndStone, + Block::RedSandstone, + Block::Sandstone, + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + Block::Terracotta, + Block::WhiteTerracotta, + Block::OrangeTerracotta, + Block::MagentaTerracotta, + Block::LightBlueTerracotta, + Block::YellowTerracotta, + Block::LimeTerracotta, + Block::PinkTerracotta, + Block::GrayTerracotta, + Block::LightGrayTerracotta, + Block::CyanTerracotta, + Block::PurpleTerracotta, + Block::BlueTerracotta, + Block::BrownTerracotta, + Block::GreenTerracotta, + Block::RedTerracotta, + Block::BlackTerracotta, + Block::CrimsonNylium, + Block::WarpedNylium, + Block::Netherrack, + Block::Basalt, + Block::Blackstone, + ]) +}); +pub static BAMBOO_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::BambooBlock, Block::StrippedBambooBlock])); +pub static MOSS_REPLACEABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + Block::CaveVinesPlant, + Block::CaveVines, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + ]) +}); +pub static CANDLES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Candle, + Block::WhiteCandle, + Block::OrangeCandle, + Block::MagentaCandle, + Block::LightBlueCandle, + Block::YellowCandle, + Block::LimeCandle, + Block::PinkCandle, + Block::GrayCandle, + Block::LightGrayCandle, + Block::CyanCandle, + Block::PurpleCandle, + Block::BlueCandle, + Block::BrownCandle, + Block::GreenCandle, + Block::RedCandle, + Block::BlackCandle, + ]) +}); +pub static SPRUCE_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::SpruceLog, + Block::SpruceWood, + Block::StrippedSpruceLog, + Block::StrippedSpruceWood, + ]) +}); +pub static OCCLUDES_VIBRATION_SIGNALS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::WhiteWool, + Block::OrangeWool, + Block::MagentaWool, + Block::LightBlueWool, + Block::YellowWool, + Block::LimeWool, + Block::PinkWool, + Block::GrayWool, + Block::LightGrayWool, + Block::CyanWool, + Block::PurpleWool, + Block::BlueWool, + Block::BrownWool, + Block::GreenWool, + Block::RedWool, + Block::BlackWool, + ]) +}); +pub static AZALEA_ROOT_REPLACEABLE: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::RedSand, + Block::Clay, + Block::Gravel, + Block::Sand, + Block::SnowBlock, + Block::PowderSnow, + Block::Stone, + Block::Granite, + Block::Diorite, + Block::Andesite, + Block::Tuff, + Block::Deepslate, + Block::Dirt, + Block::GrassBlock, + Block::Podzol, + Block::CoarseDirt, + Block::Mycelium, + Block::RootedDirt, + Block::MossBlock, + Block::Mud, + Block::MuddyMangroveRoots, + Block::Terracotta, + Block::WhiteTerracotta, + Block::OrangeTerracotta, + Block::MagentaTerracotta, + Block::LightBlueTerracotta, + Block::YellowTerracotta, + Block::LimeTerracotta, + Block::PinkTerracotta, + Block::GrayTerracotta, + Block::LightGrayTerracotta, + Block::CyanTerracotta, + Block::PurpleTerracotta, + Block::BlueTerracotta, + Block::BrownTerracotta, + Block::GreenTerracotta, + Block::RedTerracotta, + Block::BlackTerracotta, + ]) +}); +pub static RABBITS_SPAWNABLE_ON: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::GrassBlock, + Block::Snow, + Block::SnowBlock, + Block::Sand, + ]) +}); +pub static SAPLINGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::OakSapling, + Block::SpruceSapling, + Block::BirchSapling, + Block::JungleSapling, + Block::AcaciaSapling, + Block::DarkOakSapling, + Block::Azalea, + Block::FloweringAzalea, + Block::MangrovePropagule, + Block::CherrySapling, + ]) +}); +pub static LEAVES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::JungleLeaves, + Block::OakLeaves, + Block::SpruceLeaves, + Block::DarkOakLeaves, + Block::AcaciaLeaves, + Block::BirchLeaves, + Block::AzaleaLeaves, + Block::FloweringAzaleaLeaves, + Block::MangroveLeaves, + Block::CherryLeaves, + ]) +}); +pub static STONE_BUTTONS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::StoneButton, Block::PolishedBlackstoneButton])); +pub static REDSTONE_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::RedstoneOre, Block::DeepslateRedstoneOre])); +pub static CRIMSON_STEMS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::CrimsonStem, + Block::StrippedCrimsonStem, + Block::CrimsonHyphae, + Block::StrippedCrimsonHyphae, + ]) +}); +pub static FROGS_SPAWNABLE_ON: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::GrassBlock, + Block::Mud, + Block::MangroveRoots, + Block::MuddyMangroveRoots, + ]) +}); +pub static MAINTAINS_FARMLAND: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::PumpkinStem, + Block::AttachedPumpkinStem, + Block::MelonStem, + Block::AttachedMelonStem, + Block::Beetroots, + Block::Carrots, + Block::Potatoes, + Block::TorchflowerCrop, + Block::Torchflower, + Block::PitcherCrop, + Block::Wheat, + ]) +}); +pub static CROPS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::Beetroots, + Block::Carrots, + Block::Potatoes, + Block::Wheat, + Block::MelonStem, + Block::PumpkinStem, + Block::TorchflowerCrop, + Block::PitcherCrop, + ]) +}); +pub static WALLS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::CobblestoneWall, + Block::MossyCobblestoneWall, + Block::BrickWall, + Block::PrismarineWall, + Block::RedSandstoneWall, + Block::MossyStoneBrickWall, + Block::GraniteWall, + Block::StoneBrickWall, + Block::NetherBrickWall, + Block::AndesiteWall, + Block::RedNetherBrickWall, + Block::SandstoneWall, + Block::EndStoneBrickWall, + Block::DioriteWall, + Block::BlackstoneWall, + Block::PolishedBlackstoneBrickWall, + Block::PolishedBlackstoneWall, + Block::CobbledDeepslateWall, + Block::PolishedDeepslateWall, + Block::DeepslateTileWall, + Block::DeepslateBrickWall, + Block::MudBrickWall, + ]) +}); +pub static STONE_PRESSURE_PLATES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Block::StonePressurePlate, + Block::PolishedBlackstonePressurePlate, + ]) +}); +pub static VIBRATION_RESONATORS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Block::AmethystBlock])); diff --git a/azalea-registry/src/tags/fluids.rs b/azalea-registry/src/tags/fluids.rs new file mode 100644 index 00000000..4f177f95 --- /dev/null +++ b/azalea-registry/src/tags/fluids.rs @@ -0,0 +1,12 @@ +// This file was generated by codegen/lib/code/tags.py, don't edit it manually! + +use std::collections::HashSet; + +use once_cell::sync::Lazy; + +use crate::Fluid; + +pub static LAVA: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Fluid::Lava, Fluid::FlowingLava])); +pub static WATER: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Fluid::Water, Fluid::FlowingWater])); diff --git a/azalea-registry/src/tags/items.rs b/azalea-registry/src/tags/items.rs new file mode 100644 index 00000000..d826703d --- /dev/null +++ b/azalea-registry/src/tags/items.rs @@ -0,0 +1,1379 @@ +// This file was generated by codegen/lib/code/tags.py, don't edit it manually! + +use std::collections::HashSet; + +use once_cell::sync::Lazy; + +use crate::Item; + +pub static WOODEN_FENCES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakFence, + Item::AcaciaFence, + Item::DarkOakFence, + Item::SpruceFence, + Item::BirchFence, + Item::JungleFence, + Item::CrimsonFence, + Item::WarpedFence, + Item::MangroveFence, + Item::BambooFence, + Item::CherryFence, + ]) +}); +pub static ACACIA_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::AcaciaLog, + Item::AcaciaWood, + Item::StrippedAcaciaLog, + Item::StrippedAcaciaWood, + ]) +}); +pub static CREEPER_IGNITERS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::FlintAndSteel, Item::FireCharge])); +pub static WOODEN_SLABS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakSlab, + Item::SpruceSlab, + Item::BirchSlab, + Item::JungleSlab, + Item::AcaciaSlab, + Item::DarkOakSlab, + Item::CrimsonSlab, + Item::WarpedSlab, + Item::MangroveSlab, + Item::BambooSlab, + Item::CherrySlab, + ]) +}); +pub static WOODEN_STAIRS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakStairs, + Item::SpruceStairs, + Item::BirchStairs, + Item::JungleStairs, + Item::AcaciaStairs, + Item::DarkOakStairs, + Item::CrimsonStairs, + Item::WarpedStairs, + Item::MangroveStairs, + Item::BambooStairs, + Item::CherryStairs, + ]) +}); +pub static MANGROVE_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::MangroveLog, + Item::MangroveWood, + Item::StrippedMangroveLog, + Item::StrippedMangroveWood, + ]) +}); +pub static SHOVELS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::DiamondShovel, + Item::StoneShovel, + Item::GoldenShovel, + Item::NetheriteShovel, + Item::WoodenShovel, + Item::IronShovel, + ]) +}); +pub static DARK_OAK_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::DarkOakLog, + Item::DarkOakWood, + Item::StrippedDarkOakLog, + Item::StrippedDarkOakWood, + ]) +}); +pub static EMERALD_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::EmeraldOre, Item::DeepslateEmeraldOre])); +pub static TALL_FLOWERS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Sunflower, + Item::Lilac, + Item::Peony, + Item::RoseBush, + Item::PitcherPlant, + ]) +}); +pub static DOORS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::IronDoor, + Item::OakDoor, + Item::SpruceDoor, + Item::BirchDoor, + Item::JungleDoor, + Item::AcaciaDoor, + Item::DarkOakDoor, + Item::CrimsonDoor, + Item::WarpedDoor, + Item::MangroveDoor, + Item::BambooDoor, + Item::CherryDoor, + ]) +}); +pub static BEDS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::RedBed, + Item::BlackBed, + Item::BlueBed, + Item::BrownBed, + Item::CyanBed, + Item::GrayBed, + Item::GreenBed, + Item::LightBlueBed, + Item::LightGrayBed, + Item::LimeBed, + Item::MagentaBed, + Item::OrangeBed, + Item::PinkBed, + Item::PurpleBed, + Item::WhiteBed, + Item::YellowBed, + ]) +}); +pub static COMPASSES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::Compass, Item::RecoveryCompass])); +pub static DECORATED_POT_INGREDIENTS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Brick, + Item::AnglerPotterySherd, + Item::ArcherPotterySherd, + Item::ArmsUpPotterySherd, + Item::BladePotterySherd, + Item::BrewerPotterySherd, + Item::BurnPotterySherd, + Item::DangerPotterySherd, + Item::ExplorerPotterySherd, + Item::FriendPotterySherd, + Item::HeartPotterySherd, + Item::HeartbreakPotterySherd, + Item::HowlPotterySherd, + Item::MinerPotterySherd, + Item::MournerPotterySherd, + Item::PlentyPotterySherd, + Item::PrizePotterySherd, + Item::SheafPotterySherd, + Item::ShelterPotterySherd, + Item::SkullPotterySherd, + Item::SnortPotterySherd, + ]) +}); +pub static COPPER_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::CopperOre, Item::DeepslateCopperOre])); +pub static TRIM_TEMPLATES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::WardArmorTrimSmithingTemplate, + Item::SpireArmorTrimSmithingTemplate, + Item::CoastArmorTrimSmithingTemplate, + Item::EyeArmorTrimSmithingTemplate, + Item::DuneArmorTrimSmithingTemplate, + Item::WildArmorTrimSmithingTemplate, + Item::RibArmorTrimSmithingTemplate, + Item::TideArmorTrimSmithingTemplate, + Item::SentryArmorTrimSmithingTemplate, + Item::VexArmorTrimSmithingTemplate, + Item::SnoutArmorTrimSmithingTemplate, + Item::WayfinderArmorTrimSmithingTemplate, + Item::ShaperArmorTrimSmithingTemplate, + Item::SilenceArmorTrimSmithingTemplate, + Item::RaiserArmorTrimSmithingTemplate, + Item::HostArmorTrimSmithingTemplate, + ]) +}); +pub static WOODEN_PRESSURE_PLATES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakPressurePlate, + Item::SprucePressurePlate, + Item::BirchPressurePlate, + Item::JunglePressurePlate, + Item::AcaciaPressurePlate, + Item::DarkOakPressurePlate, + Item::CrimsonPressurePlate, + Item::WarpedPressurePlate, + Item::MangrovePressurePlate, + Item::BambooPressurePlate, + Item::CherryPressurePlate, + ]) +}); +pub static NOTEBLOCK_TOP_INSTRUMENTS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::ZombieHead, + Item::SkeletonSkull, + Item::CreeperHead, + Item::DragonHead, + Item::WitherSkeletonSkull, + Item::PiglinHead, + Item::PlayerHead, + ]) +}); +pub static BREAKS_DECORATED_POTS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Trident, + Item::DiamondSword, + Item::StoneSword, + Item::GoldenSword, + Item::NetheriteSword, + Item::WoodenSword, + Item::IronSword, + Item::DiamondAxe, + Item::StoneAxe, + Item::GoldenAxe, + Item::NetheriteAxe, + Item::WoodenAxe, + Item::IronAxe, + Item::DiamondPickaxe, + Item::StonePickaxe, + Item::GoldenPickaxe, + Item::NetheritePickaxe, + Item::WoodenPickaxe, + Item::IronPickaxe, + Item::DiamondShovel, + Item::StoneShovel, + Item::GoldenShovel, + Item::NetheriteShovel, + Item::WoodenShovel, + Item::IronShovel, + Item::DiamondHoe, + Item::StoneHoe, + Item::GoldenHoe, + Item::NetheriteHoe, + Item::WoodenHoe, + Item::IronHoe, + ]) +}); +pub static SAND: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Sand, + Item::RedSand, + Item::SuspiciousSand, + Item::SuspiciousSand, + ]) +}); +pub static LOGS_THAT_BURN: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::DarkOakLog, + Item::DarkOakWood, + Item::StrippedDarkOakLog, + Item::StrippedDarkOakWood, + Item::OakLog, + Item::OakWood, + Item::StrippedOakLog, + Item::StrippedOakWood, + Item::AcaciaLog, + Item::AcaciaWood, + Item::StrippedAcaciaLog, + Item::StrippedAcaciaWood, + Item::BirchLog, + Item::BirchWood, + Item::StrippedBirchLog, + Item::StrippedBirchWood, + Item::JungleLog, + Item::JungleWood, + Item::StrippedJungleLog, + Item::StrippedJungleWood, + Item::SpruceLog, + Item::SpruceWood, + Item::StrippedSpruceLog, + Item::StrippedSpruceWood, + Item::MangroveLog, + Item::MangroveWood, + Item::StrippedMangroveLog, + Item::StrippedMangroveWood, + Item::CherryLog, + Item::CherryWood, + Item::StrippedCherryLog, + Item::StrippedCherryWood, + ]) +}); +pub static CHERRY_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::CherryLog, + Item::CherryWood, + Item::StrippedCherryLog, + Item::StrippedCherryWood, + ]) +}); +pub static DAMPENS_VIBRATIONS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::WhiteWool, + Item::OrangeWool, + Item::MagentaWool, + Item::LightBlueWool, + Item::YellowWool, + Item::LimeWool, + Item::PinkWool, + Item::GrayWool, + Item::LightGrayWool, + Item::CyanWool, + Item::PurpleWool, + Item::BlueWool, + Item::BrownWool, + Item::GreenWool, + Item::RedWool, + Item::BlackWool, + Item::WhiteCarpet, + Item::OrangeCarpet, + Item::MagentaCarpet, + Item::LightBlueCarpet, + Item::YellowCarpet, + Item::LimeCarpet, + Item::PinkCarpet, + Item::GrayCarpet, + Item::LightGrayCarpet, + Item::CyanCarpet, + Item::PurpleCarpet, + Item::BlueCarpet, + Item::BrownCarpet, + Item::GreenCarpet, + Item::RedCarpet, + Item::BlackCarpet, + ]) +}); +pub static DIAMOND_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::DiamondOre, Item::DeepslateDiamondOre])); +pub static WOOL: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::WhiteWool, + Item::OrangeWool, + Item::MagentaWool, + Item::LightBlueWool, + Item::YellowWool, + Item::LimeWool, + Item::PinkWool, + Item::GrayWool, + Item::LightGrayWool, + Item::CyanWool, + Item::PurpleWool, + Item::BlueWool, + Item::BrownWool, + Item::GreenWool, + Item::RedWool, + Item::BlackWool, + ]) +}); +pub static WOODEN_TRAPDOORS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::AcaciaTrapdoor, + Item::BirchTrapdoor, + Item::DarkOakTrapdoor, + Item::JungleTrapdoor, + Item::OakTrapdoor, + Item::SpruceTrapdoor, + Item::CrimsonTrapdoor, + Item::WarpedTrapdoor, + Item::MangroveTrapdoor, + Item::BambooTrapdoor, + Item::CherryTrapdoor, + ]) +}); +pub static FLOWERS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::FloweringAzaleaLeaves, + Item::FloweringAzalea, + Item::MangrovePropagule, + Item::CherryLeaves, + Item::PinkPetals, + Item::Dandelion, + Item::Poppy, + Item::BlueOrchid, + Item::Allium, + Item::AzureBluet, + Item::RedTulip, + Item::OrangeTulip, + Item::WhiteTulip, + Item::PinkTulip, + Item::OxeyeDaisy, + Item::Cornflower, + Item::LilyOfTheValley, + Item::WitherRose, + Item::Torchflower, + Item::Sunflower, + Item::Lilac, + Item::Peony, + Item::RoseBush, + Item::PitcherPlant, + ]) +}); +pub static BANNERS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::WhiteBanner, + Item::OrangeBanner, + Item::MagentaBanner, + Item::LightBlueBanner, + Item::YellowBanner, + Item::LimeBanner, + Item::PinkBanner, + Item::GrayBanner, + Item::LightGrayBanner, + Item::CyanBanner, + Item::PurpleBanner, + Item::BlueBanner, + Item::BrownBanner, + Item::GreenBanner, + Item::RedBanner, + Item::BlackBanner, + ]) +}); +pub static TERRACOTTA: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Terracotta, + Item::WhiteTerracotta, + Item::OrangeTerracotta, + Item::MagentaTerracotta, + Item::LightBlueTerracotta, + Item::YellowTerracotta, + Item::LimeTerracotta, + Item::PinkTerracotta, + Item::GrayTerracotta, + Item::LightGrayTerracotta, + Item::CyanTerracotta, + Item::PurpleTerracotta, + Item::BlueTerracotta, + Item::BrownTerracotta, + Item::GreenTerracotta, + Item::RedTerracotta, + Item::BlackTerracotta, + ]) +}); +pub static COALS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::Coal, Item::Charcoal])); +pub static BIRCH_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::BirchLog, + Item::BirchWood, + Item::StrippedBirchLog, + Item::StrippedBirchWood, + ]) +}); +pub static PIGLIN_REPELLENTS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::SoulTorch, Item::SoulLantern, Item::SoulCampfire])); +pub static CREEPER_DROP_MUSIC_DISCS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::MusicDisc13, + Item::MusicDiscCat, + Item::MusicDiscBlocks, + Item::MusicDiscChirp, + Item::MusicDiscFar, + Item::MusicDiscMall, + Item::MusicDiscMellohi, + Item::MusicDiscStal, + Item::MusicDiscStrad, + Item::MusicDiscWard, + Item::MusicDisc11, + Item::MusicDiscWait, + ]) +}); +pub static SLABS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::BambooMosaicSlab, + Item::StoneSlab, + Item::SmoothStoneSlab, + Item::StoneBrickSlab, + Item::SandstoneSlab, + Item::PurpurSlab, + Item::QuartzSlab, + Item::RedSandstoneSlab, + Item::BrickSlab, + Item::CobblestoneSlab, + Item::NetherBrickSlab, + Item::PetrifiedOakSlab, + Item::PrismarineSlab, + Item::PrismarineBrickSlab, + Item::DarkPrismarineSlab, + Item::PolishedGraniteSlab, + Item::SmoothRedSandstoneSlab, + Item::MossyStoneBrickSlab, + Item::PolishedDioriteSlab, + Item::MossyCobblestoneSlab, + Item::EndStoneBrickSlab, + Item::SmoothSandstoneSlab, + Item::SmoothQuartzSlab, + Item::GraniteSlab, + Item::AndesiteSlab, + Item::RedNetherBrickSlab, + Item::PolishedAndesiteSlab, + Item::DioriteSlab, + Item::CutSandstoneSlab, + Item::CutRedSandstoneSlab, + Item::BlackstoneSlab, + Item::PolishedBlackstoneBrickSlab, + Item::PolishedBlackstoneSlab, + Item::CobbledDeepslateSlab, + Item::PolishedDeepslateSlab, + Item::DeepslateTileSlab, + Item::DeepslateBrickSlab, + Item::WaxedWeatheredCutCopperSlab, + Item::WaxedExposedCutCopperSlab, + Item::WaxedCutCopperSlab, + Item::OxidizedCutCopperSlab, + Item::WeatheredCutCopperSlab, + Item::ExposedCutCopperSlab, + Item::CutCopperSlab, + Item::WaxedOxidizedCutCopperSlab, + Item::MudBrickSlab, + Item::OakSlab, + Item::SpruceSlab, + Item::BirchSlab, + Item::JungleSlab, + Item::AcaciaSlab, + Item::DarkOakSlab, + Item::CrimsonSlab, + Item::WarpedSlab, + Item::MangroveSlab, + Item::BambooSlab, + Item::CherrySlab, + ]) +}); +pub static ANVIL: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::Anvil, Item::ChippedAnvil, Item::DamagedAnvil])); +pub static STAIRS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::BambooMosaicStairs, + Item::CobblestoneStairs, + Item::SandstoneStairs, + Item::NetherBrickStairs, + Item::StoneBrickStairs, + Item::BrickStairs, + Item::PurpurStairs, + Item::QuartzStairs, + Item::RedSandstoneStairs, + Item::PrismarineBrickStairs, + Item::PrismarineStairs, + Item::DarkPrismarineStairs, + Item::PolishedGraniteStairs, + Item::SmoothRedSandstoneStairs, + Item::MossyStoneBrickStairs, + Item::PolishedDioriteStairs, + Item::MossyCobblestoneStairs, + Item::EndStoneBrickStairs, + Item::StoneStairs, + Item::SmoothSandstoneStairs, + Item::SmoothQuartzStairs, + Item::GraniteStairs, + Item::AndesiteStairs, + Item::RedNetherBrickStairs, + Item::PolishedAndesiteStairs, + Item::DioriteStairs, + Item::BlackstoneStairs, + Item::PolishedBlackstoneBrickStairs, + Item::PolishedBlackstoneStairs, + Item::CobbledDeepslateStairs, + Item::PolishedDeepslateStairs, + Item::DeepslateTileStairs, + Item::DeepslateBrickStairs, + Item::OxidizedCutCopperStairs, + Item::WeatheredCutCopperStairs, + Item::ExposedCutCopperStairs, + Item::CutCopperStairs, + Item::WaxedWeatheredCutCopperStairs, + Item::WaxedExposedCutCopperStairs, + Item::WaxedCutCopperStairs, + Item::WaxedOxidizedCutCopperStairs, + Item::MudBrickStairs, + Item::OakStairs, + Item::SpruceStairs, + Item::BirchStairs, + Item::JungleStairs, + Item::AcaciaStairs, + Item::DarkOakStairs, + Item::CrimsonStairs, + Item::WarpedStairs, + Item::MangroveStairs, + Item::BambooStairs, + Item::CherryStairs, + ]) +}); +pub static STONE_CRAFTING_MATERIALS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Cobblestone, + Item::Blackstone, + Item::CobbledDeepslate, + ]) +}); +pub static FISHES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Cod, + Item::CookedCod, + Item::Salmon, + Item::CookedSalmon, + Item::Pufferfish, + Item::TropicalFish, + ]) +}); +pub static SOUL_FIRE_BASE_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::SoulSand, Item::SoulSoil])); +pub static AXOLOTL_TEMPT_ITEMS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::TropicalFishBucket])); +pub static WOOL_CARPETS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::WhiteCarpet, + Item::OrangeCarpet, + Item::MagentaCarpet, + Item::LightBlueCarpet, + Item::YellowCarpet, + Item::LimeCarpet, + Item::PinkCarpet, + Item::GrayCarpet, + Item::LightGrayCarpet, + Item::CyanCarpet, + Item::PurpleCarpet, + Item::BlueCarpet, + Item::BrownCarpet, + Item::GreenCarpet, + Item::RedCarpet, + Item::BlackCarpet, + ]) +}); +pub static VILLAGER_PLANTABLE_SEEDS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::WheatSeeds, + Item::Potato, + Item::Carrot, + Item::BeetrootSeeds, + Item::TorchflowerSeeds, + Item::PitcherPod, + ]) +}); +pub static WOODEN_DOORS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakDoor, + Item::SpruceDoor, + Item::BirchDoor, + Item::JungleDoor, + Item::AcaciaDoor, + Item::DarkOakDoor, + Item::CrimsonDoor, + Item::WarpedDoor, + Item::MangroveDoor, + Item::BambooDoor, + Item::CherryDoor, + ]) +}); +pub static COAL_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::CoalOre, Item::DeepslateCoalOre])); +pub static TOOLS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Trident, + Item::DiamondSword, + Item::StoneSword, + Item::GoldenSword, + Item::NetheriteSword, + Item::WoodenSword, + Item::IronSword, + Item::DiamondAxe, + Item::StoneAxe, + Item::GoldenAxe, + Item::NetheriteAxe, + Item::WoodenAxe, + Item::IronAxe, + Item::DiamondPickaxe, + Item::StonePickaxe, + Item::GoldenPickaxe, + Item::NetheritePickaxe, + Item::WoodenPickaxe, + Item::IronPickaxe, + Item::DiamondShovel, + Item::StoneShovel, + Item::GoldenShovel, + Item::NetheriteShovel, + Item::WoodenShovel, + Item::IronShovel, + Item::DiamondHoe, + Item::StoneHoe, + Item::GoldenHoe, + Item::NetheriteHoe, + Item::WoodenHoe, + Item::IronHoe, + ]) +}); +pub static BUTTONS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakButton, + Item::SpruceButton, + Item::BirchButton, + Item::JungleButton, + Item::AcaciaButton, + Item::DarkOakButton, + Item::CrimsonButton, + Item::WarpedButton, + Item::MangroveButton, + Item::BambooButton, + Item::CherryButton, + Item::StoneButton, + Item::PolishedBlackstoneButton, + ]) +}); +pub static GOLD_ORES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::GoldOre, + Item::NetherGoldOre, + Item::DeepslateGoldOre, + ]) +}); +pub static WART_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::NetherWartBlock, Item::WarpedWartBlock])); +pub static NON_FLAMMABLE_WOOD: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::WarpedStem, + Item::StrippedWarpedStem, + Item::WarpedHyphae, + Item::StrippedWarpedHyphae, + Item::CrimsonStem, + Item::StrippedCrimsonStem, + Item::CrimsonHyphae, + Item::StrippedCrimsonHyphae, + Item::CrimsonPlanks, + Item::WarpedPlanks, + Item::CrimsonSlab, + Item::WarpedSlab, + Item::CrimsonPressurePlate, + Item::WarpedPressurePlate, + Item::CrimsonFence, + Item::WarpedFence, + Item::CrimsonTrapdoor, + Item::WarpedTrapdoor, + Item::CrimsonFenceGate, + Item::WarpedFenceGate, + Item::CrimsonStairs, + Item::WarpedStairs, + Item::CrimsonButton, + Item::WarpedButton, + Item::CrimsonDoor, + Item::WarpedDoor, + Item::CrimsonSign, + Item::WarpedSign, + Item::WarpedHangingSign, + Item::CrimsonHangingSign, + ]) +}); +pub static PICKAXES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::DiamondPickaxe, + Item::StonePickaxe, + Item::GoldenPickaxe, + Item::NetheritePickaxe, + Item::WoodenPickaxe, + Item::IronPickaxe, + ]) +}); +pub static HOES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::DiamondHoe, + Item::StoneHoe, + Item::GoldenHoe, + Item::NetheriteHoe, + Item::WoodenHoe, + Item::IronHoe, + ]) +}); +pub static FENCES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::NetherBrickFence, + Item::OakFence, + Item::AcaciaFence, + Item::DarkOakFence, + Item::SpruceFence, + Item::BirchFence, + Item::JungleFence, + Item::CrimsonFence, + Item::WarpedFence, + Item::MangroveFence, + Item::BambooFence, + Item::CherryFence, + ]) +}); +pub static COMPLETES_FIND_TREE_TUTORIAL: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::JungleLeaves, + Item::OakLeaves, + Item::SpruceLeaves, + Item::DarkOakLeaves, + Item::AcaciaLeaves, + Item::BirchLeaves, + Item::AzaleaLeaves, + Item::FloweringAzaleaLeaves, + Item::MangroveLeaves, + Item::CherryLeaves, + Item::NetherWartBlock, + Item::WarpedWartBlock, + Item::CrimsonStem, + Item::StrippedCrimsonStem, + Item::CrimsonHyphae, + Item::StrippedCrimsonHyphae, + Item::WarpedStem, + Item::StrippedWarpedStem, + Item::WarpedHyphae, + Item::StrippedWarpedHyphae, + Item::DarkOakLog, + Item::DarkOakWood, + Item::StrippedDarkOakLog, + Item::StrippedDarkOakWood, + Item::OakLog, + Item::OakWood, + Item::StrippedOakLog, + Item::StrippedOakWood, + Item::AcaciaLog, + Item::AcaciaWood, + Item::StrippedAcaciaLog, + Item::StrippedAcaciaWood, + Item::BirchLog, + Item::BirchWood, + Item::StrippedBirchLog, + Item::StrippedBirchWood, + Item::JungleLog, + Item::JungleWood, + Item::StrippedJungleLog, + Item::StrippedJungleWood, + Item::SpruceLog, + Item::SpruceWood, + Item::StrippedSpruceLog, + Item::StrippedSpruceWood, + Item::MangroveLog, + Item::MangroveWood, + Item::StrippedMangroveLog, + Item::StrippedMangroveWood, + Item::CherryLog, + Item::CherryWood, + Item::StrippedCherryLog, + Item::StrippedCherryWood, + ]) +}); +pub static SMALL_FLOWERS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Dandelion, + Item::Poppy, + Item::BlueOrchid, + Item::Allium, + Item::AzureBluet, + Item::RedTulip, + Item::OrangeTulip, + Item::WhiteTulip, + Item::PinkTulip, + Item::OxeyeDaisy, + Item::Cornflower, + Item::LilyOfTheValley, + Item::WitherRose, + Item::Torchflower, + ]) +}); +pub static PIGLIN_FOOD: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::Porkchop, Item::CookedPorkchop])); +pub static FENCE_GATES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::AcaciaFenceGate, + Item::BirchFenceGate, + Item::DarkOakFenceGate, + Item::JungleFenceGate, + Item::OakFenceGate, + Item::SpruceFenceGate, + Item::CrimsonFenceGate, + Item::WarpedFenceGate, + Item::MangroveFenceGate, + Item::BambooFenceGate, + Item::CherryFenceGate, + ]) +}); +pub static OAK_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakLog, + Item::OakWood, + Item::StrippedOakLog, + Item::StrippedOakWood, + ]) +}); +pub static TRIM_MATERIALS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::IronIngot, + Item::CopperIngot, + Item::GoldIngot, + Item::LapisLazuli, + Item::Emerald, + Item::Diamond, + Item::NetheriteIngot, + Item::Redstone, + Item::Quartz, + Item::AmethystShard, + ]) +}); +pub static STONE_BRICKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::StoneBricks, + Item::MossyStoneBricks, + Item::CrackedStoneBricks, + Item::ChiseledStoneBricks, + ]) +}); +pub static STONE_TOOL_MATERIALS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Cobblestone, + Item::Blackstone, + Item::CobbledDeepslate, + ]) +}); +pub static LAPIS_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::LapisOre, Item::DeepslateLapisOre])); +pub static SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakSign, + Item::SpruceSign, + Item::BirchSign, + Item::AcaciaSign, + Item::JungleSign, + Item::DarkOakSign, + Item::CrimsonSign, + Item::WarpedSign, + Item::MangroveSign, + Item::BambooSign, + Item::CherrySign, + ]) +}); +pub static DIRT: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Dirt, + Item::GrassBlock, + Item::Podzol, + Item::CoarseDirt, + Item::Mycelium, + Item::RootedDirt, + Item::MossBlock, + Item::Mud, + Item::MuddyMangroveRoots, + ]) +}); +pub static LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::CrimsonStem, + Item::StrippedCrimsonStem, + Item::CrimsonHyphae, + Item::StrippedCrimsonHyphae, + Item::WarpedStem, + Item::StrippedWarpedStem, + Item::WarpedHyphae, + Item::StrippedWarpedHyphae, + Item::DarkOakLog, + Item::DarkOakWood, + Item::StrippedDarkOakLog, + Item::StrippedDarkOakWood, + Item::OakLog, + Item::OakWood, + Item::StrippedOakLog, + Item::StrippedOakWood, + Item::AcaciaLog, + Item::AcaciaWood, + Item::StrippedAcaciaLog, + Item::StrippedAcaciaWood, + Item::BirchLog, + Item::BirchWood, + Item::StrippedBirchLog, + Item::StrippedBirchWood, + Item::JungleLog, + Item::JungleWood, + Item::StrippedJungleLog, + Item::StrippedJungleWood, + Item::SpruceLog, + Item::SpruceWood, + Item::StrippedSpruceLog, + Item::StrippedSpruceWood, + Item::MangroveLog, + Item::MangroveWood, + Item::StrippedMangroveLog, + Item::StrippedMangroveWood, + Item::CherryLog, + Item::CherryWood, + Item::StrippedCherryLog, + Item::StrippedCherryWood, + ]) +}); +pub static AXES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::DiamondAxe, + Item::StoneAxe, + Item::GoldenAxe, + Item::NetheriteAxe, + Item::WoodenAxe, + Item::IronAxe, + ]) +}); +pub static CHEST_BOATS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakChestBoat, + Item::SpruceChestBoat, + Item::BirchChestBoat, + Item::JungleChestBoat, + Item::AcaciaChestBoat, + Item::DarkOakChestBoat, + Item::MangroveChestBoat, + Item::BambooChestRaft, + Item::CherryChestBoat, + ]) +}); +pub static BOOKSHELF_BOOKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Book, + Item::WrittenBook, + Item::EnchantedBook, + Item::WritableBook, + Item::KnowledgeBook, + ]) +}); +pub static ARROWS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::Arrow, Item::TippedArrow, Item::SpectralArrow])); +pub static PIGLIN_LOVED: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::GoldBlock, + Item::GildedBlackstone, + Item::LightWeightedPressurePlate, + Item::GoldIngot, + Item::Bell, + Item::Clock, + Item::GoldenCarrot, + Item::GlisteringMelonSlice, + Item::GoldenApple, + Item::EnchantedGoldenApple, + Item::GoldenHelmet, + Item::GoldenChestplate, + Item::GoldenLeggings, + Item::GoldenBoots, + Item::GoldenHorseArmor, + Item::GoldenSword, + Item::GoldenPickaxe, + Item::GoldenShovel, + Item::GoldenAxe, + Item::GoldenHoe, + Item::RawGold, + Item::RawGoldBlock, + Item::GoldOre, + Item::NetherGoldOre, + Item::DeepslateGoldOre, + ]) +}); +pub static WOODEN_BUTTONS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakButton, + Item::SpruceButton, + Item::BirchButton, + Item::JungleButton, + Item::AcaciaButton, + Item::DarkOakButton, + Item::CrimsonButton, + Item::WarpedButton, + Item::MangroveButton, + Item::BambooButton, + Item::CherryButton, + ]) +}); +pub static SMELTS_TO_GLASS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::Sand, Item::RedSand])); +pub static JUNGLE_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::JungleLog, + Item::JungleWood, + Item::StrippedJungleLog, + Item::StrippedJungleWood, + ]) +}); +pub static TRAPDOORS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::IronTrapdoor, + Item::AcaciaTrapdoor, + Item::BirchTrapdoor, + Item::DarkOakTrapdoor, + Item::JungleTrapdoor, + Item::OakTrapdoor, + Item::SpruceTrapdoor, + Item::CrimsonTrapdoor, + Item::WarpedTrapdoor, + Item::MangroveTrapdoor, + Item::BambooTrapdoor, + Item::CherryTrapdoor, + ]) +}); +pub static IGNORED_BY_PIGLIN_BABIES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::Leather])); +pub static WARPED_STEMS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::WarpedStem, + Item::StrippedWarpedStem, + Item::WarpedHyphae, + Item::StrippedWarpedHyphae, + ]) +}); +pub static BEACON_PAYMENT_ITEMS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::NetheriteIngot, + Item::Emerald, + Item::Diamond, + Item::GoldIngot, + Item::IronIngot, + ]) +}); +pub static IRON_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::IronOre, Item::DeepslateIronOre])); +pub static BOATS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakBoat, + Item::SpruceBoat, + Item::BirchBoat, + Item::JungleBoat, + Item::AcaciaBoat, + Item::DarkOakBoat, + Item::MangroveBoat, + Item::BambooRaft, + Item::CherryBoat, + Item::OakChestBoat, + Item::SpruceChestBoat, + Item::BirchChestBoat, + Item::JungleChestBoat, + Item::AcaciaChestBoat, + Item::DarkOakChestBoat, + Item::MangroveChestBoat, + Item::BambooChestRaft, + Item::CherryChestBoat, + ]) +}); +pub static RAILS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Rail, + Item::PoweredRail, + Item::DetectorRail, + Item::ActivatorRail, + ]) +}); +pub static TRIMMABLE_ARMOR: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::NetheriteHelmet, + Item::NetheriteChestplate, + Item::NetheriteLeggings, + Item::NetheriteBoots, + Item::DiamondHelmet, + Item::DiamondChestplate, + Item::DiamondLeggings, + Item::DiamondBoots, + Item::GoldenHelmet, + Item::GoldenChestplate, + Item::GoldenLeggings, + Item::GoldenBoots, + Item::IronHelmet, + Item::IronChestplate, + Item::IronLeggings, + Item::IronBoots, + Item::ChainmailHelmet, + Item::ChainmailChestplate, + Item::ChainmailLeggings, + Item::ChainmailBoots, + Item::LeatherHelmet, + Item::LeatherChestplate, + Item::LeatherLeggings, + Item::LeatherBoots, + Item::TurtleHelmet, + ]) +}); +pub static PLANKS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakPlanks, + Item::SprucePlanks, + Item::BirchPlanks, + Item::JunglePlanks, + Item::AcaciaPlanks, + Item::DarkOakPlanks, + Item::CrimsonPlanks, + Item::WarpedPlanks, + Item::MangrovePlanks, + Item::BambooPlanks, + Item::CherryPlanks, + ]) +}); +pub static FOX_FOOD: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::SweetBerries, Item::GlowBerries])); +pub static BAMBOO_BLOCKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::BambooBlock, Item::StrippedBambooBlock])); +pub static SNIFFER_FOOD: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::TorchflowerSeeds])); +pub static CANDLES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::Candle, + Item::WhiteCandle, + Item::OrangeCandle, + Item::MagentaCandle, + Item::LightBlueCandle, + Item::YellowCandle, + Item::LimeCandle, + Item::PinkCandle, + Item::GrayCandle, + Item::LightGrayCandle, + Item::CyanCandle, + Item::PurpleCandle, + Item::BlueCandle, + Item::BrownCandle, + Item::GreenCandle, + Item::RedCandle, + Item::BlackCandle, + ]) +}); +pub static SPRUCE_LOGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::SpruceLog, + Item::SpruceWood, + Item::StrippedSpruceLog, + Item::StrippedSpruceWood, + ]) +}); +pub static SWORDS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::DiamondSword, + Item::StoneSword, + Item::GoldenSword, + Item::NetheriteSword, + Item::WoodenSword, + Item::IronSword, + ]) +}); +pub static LECTERN_BOOKS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::WrittenBook, Item::WritableBook])); +pub static DECORATED_POT_SHERDS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::AnglerPotterySherd, + Item::ArcherPotterySherd, + Item::ArmsUpPotterySherd, + Item::BladePotterySherd, + Item::BrewerPotterySherd, + Item::BurnPotterySherd, + Item::DangerPotterySherd, + Item::ExplorerPotterySherd, + Item::FriendPotterySherd, + Item::HeartPotterySherd, + Item::HeartbreakPotterySherd, + Item::HowlPotterySherd, + Item::MinerPotterySherd, + Item::MournerPotterySherd, + Item::PlentyPotterySherd, + Item::PrizePotterySherd, + Item::SheafPotterySherd, + Item::ShelterPotterySherd, + Item::SkullPotterySherd, + Item::SnortPotterySherd, + ]) +}); +pub static SAPLINGS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakSapling, + Item::SpruceSapling, + Item::BirchSapling, + Item::JungleSapling, + Item::AcaciaSapling, + Item::DarkOakSapling, + Item::Azalea, + Item::FloweringAzalea, + Item::MangrovePropagule, + Item::CherrySapling, + ]) +}); +pub static LEAVES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::JungleLeaves, + Item::OakLeaves, + Item::SpruceLeaves, + Item::DarkOakLeaves, + Item::AcaciaLeaves, + Item::BirchLeaves, + Item::AzaleaLeaves, + Item::FloweringAzaleaLeaves, + Item::MangroveLeaves, + Item::CherryLeaves, + ]) +}); +pub static STONE_BUTTONS: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::StoneButton, Item::PolishedBlackstoneButton])); +pub static REDSTONE_ORES: Lazy> = + Lazy::new(|| HashSet::from_iter(vec![Item::RedstoneOre, Item::DeepslateRedstoneOre])); +pub static CRIMSON_STEMS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::CrimsonStem, + Item::StrippedCrimsonStem, + Item::CrimsonHyphae, + Item::StrippedCrimsonHyphae, + ]) +}); +pub static HANGING_SIGNS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::OakHangingSign, + Item::SpruceHangingSign, + Item::BirchHangingSign, + Item::AcaciaHangingSign, + Item::CherryHangingSign, + Item::JungleHangingSign, + Item::DarkOakHangingSign, + Item::CrimsonHangingSign, + Item::WarpedHangingSign, + Item::MangroveHangingSign, + Item::BambooHangingSign, + ]) +}); +pub static WALLS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::CobblestoneWall, + Item::MossyCobblestoneWall, + Item::BrickWall, + Item::PrismarineWall, + Item::RedSandstoneWall, + Item::MossyStoneBrickWall, + Item::GraniteWall, + Item::StoneBrickWall, + Item::NetherBrickWall, + Item::AndesiteWall, + Item::RedNetherBrickWall, + Item::SandstoneWall, + Item::EndStoneBrickWall, + Item::DioriteWall, + Item::BlackstoneWall, + Item::PolishedBlackstoneBrickWall, + Item::PolishedBlackstoneWall, + Item::CobbledDeepslateWall, + Item::PolishedDeepslateWall, + Item::DeepslateTileWall, + Item::DeepslateBrickWall, + Item::MudBrickWall, + ]) +}); +pub static CLUSTER_MAX_HARVESTABLES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::DiamondPickaxe, + Item::GoldenPickaxe, + Item::IronPickaxe, + Item::NetheritePickaxe, + Item::StonePickaxe, + Item::WoodenPickaxe, + ]) +}); +pub static MUSIC_DISCS: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::MusicDiscPigstep, + Item::MusicDiscOtherside, + Item::MusicDisc5, + Item::MusicDiscRelic, + Item::MusicDisc13, + Item::MusicDiscCat, + Item::MusicDiscBlocks, + Item::MusicDiscChirp, + Item::MusicDiscFar, + Item::MusicDiscMall, + Item::MusicDiscMellohi, + Item::MusicDiscStal, + Item::MusicDiscStrad, + Item::MusicDiscWard, + Item::MusicDisc11, + Item::MusicDiscWait, + ]) +}); +pub static FREEZE_IMMUNE_WEARABLES: Lazy> = Lazy::new(|| { + HashSet::from_iter(vec![ + Item::LeatherBoots, + Item::LeatherLeggings, + Item::LeatherChestplate, + Item::LeatherHelmet, + Item::LeatherHorseArmor, + ]) +}); diff --git a/azalea-registry/src/tags/mod.rs b/azalea-registry/src/tags/mod.rs new file mode 100644 index 00000000..7ac46e6a --- /dev/null +++ b/azalea-registry/src/tags/mod.rs @@ -0,0 +1,3 @@ +pub mod blocks; +pub mod fluids; +pub mod items; diff --git a/azalea-world/src/container.rs b/azalea-world/src/container.rs index 2cf8da8e..f1884265 100644 --- a/azalea-world/src/container.rs +++ b/azalea-world/src/container.rs @@ -1,5 +1,6 @@ use azalea_core::ResourceLocation; -use bevy_ecs::system::Resource; +use bevy_ecs::{component::Component, system::Resource}; +use derive_more::{Deref, DerefMut}; use log::error; use nohash_hasher::IntMap; use parking_lot::RwLock; @@ -8,7 +9,7 @@ use std::{ sync::{Arc, Weak}, }; -use crate::{entity::WorldName, ChunkStorage, Instance}; +use crate::{ChunkStorage, Instance}; /// A container of [`Instance`]s (aka worlds). Instances are stored as a Weak /// pointer here, so if no clients are using an instance it will be forgotten. @@ -37,7 +38,7 @@ impl InstanceContainer { } /// Get a world from the container. - pub fn get(&self, name: &WorldName) -> Option>> { + pub fn get(&self, name: &InstanceName) -> Option>> { self.worlds.get(name).and_then(|world| world.upgrade()) } @@ -76,3 +77,9 @@ impl InstanceContainer { } } } + +/// The name of the [`Instance`](crate::Instance) (world) the entity is +/// in. If two entities share the same world name, we assume they're in the same +/// instance. +#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)] +pub struct InstanceName(pub ResourceLocation); diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 77498efd..be2c46c1 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -6,7 +6,6 @@ mod bit_storage; mod chunk_storage; mod container; -pub mod entity; pub mod iterators; pub mod palette; mod world; diff --git a/azalea-world/src/world.rs b/azalea-world/src/world.rs index a2b351c2..4784880b 100644 --- a/azalea-world/src/world.rs +++ b/azalea-world/src/world.rs @@ -1,19 +1,8 @@ -use crate::{ - entity::{ - EntityInfos, EntityUuid, LoadedBy, Local, MinecraftEntityId, PartialEntityInfos, WorldName, - }, - iterators::ChunkIterator, - palette::Palette, - ChunkStorage, InstanceContainer, PartialChunkStorage, -}; -use azalea_block::{BlockState, BlockStates}; +use crate::{iterators::ChunkIterator, palette::Palette, ChunkStorage, PartialChunkStorage}; +use azalea_block::{BlockState, BlockStates, FluidState}; use azalea_core::{BlockPos, ChunkPos}; -use bevy_ecs::{ - entity::Entity, - query::{Changed, With, Without}, - system::{Commands, Query, Res, ResMut}, -}; -use log::{debug, error, info}; +use bevy_ecs::{component::Component, entity::Entity}; +use derive_more::{Deref, DerefMut}; use nohash_hasher::IntMap; use std::fmt::Formatter; use std::{ @@ -45,133 +34,45 @@ impl PartialInstance { } } -/// Remove new entities that have the same id as an existing entity, and -/// increase the reference counts. -/// -/// This is the reason why spawning entities into the ECS when you get a spawn -/// entity packet is okay. This system will make sure the new entity gets -/// combined into the old one. -#[allow(clippy::type_complexity)] -pub fn deduplicate_entities( - mut commands: Commands, - mut query: Query< - (Entity, &MinecraftEntityId, &WorldName), - (Changed, Without), - >, - mut loaded_by_query: Query<&mut LoadedBy>, - instance_container: Res, -) { - // if this entity already exists, remove it - for (new_entity, id, world_name) in query.iter_mut() { - if let Some(world_lock) = instance_container.get(world_name) { - let world = world_lock.write(); - if let Some(old_entity) = world.entity_by_id.get(id) { - if old_entity == &new_entity { - continue; - } +/// An entity ID used by Minecraft. These are not guaranteed to be unique in +/// shared worlds, that's what [`Entity`] is for. +#[derive(Component, Copy, Clone, Debug, PartialEq, Eq, Deref, DerefMut)] +pub struct MinecraftEntityId(pub u32); - // this entity already exists!!! remove the one we just added but increase - // the reference count - let new_loaded_by = loaded_by_query - .get(new_entity) - .unwrap_or_else(|_| panic!( - "Entities should always have the LoadedBy component ({new_entity:?} did not)" - )) - .clone(); - let old_loaded_by = loaded_by_query.get_mut(*old_entity); - // merge them if possible - if let Ok(mut old_loaded_by) = old_loaded_by { - old_loaded_by.extend(new_loaded_by.iter()); - } - commands.entity(new_entity).despawn(); - info!( - "Entity with id {id:?} / {new_entity:?} already existed in the world, merging it with {old_entity:?}" - ); - break; - } - } else { - error!("Entity was inserted into a world that doesn't exist."); +impl std::hash::Hash for MinecraftEntityId { + fn hash(&self, hasher: &mut H) { + hasher.write_u32(self.0); + } +} +impl nohash_hasher::IsEnabled for MinecraftEntityId {} + +/// Keep track of certain metadatas that are only relevant for this partial +/// world. +#[derive(Debug, Default)] +pub struct PartialEntityInfos { + // note: using MinecraftEntityId for entity ids is acceptable here since + // there's no chance of collisions here + /// The entity id of the player that owns this partial world. This will + /// make `RelativeEntityUpdate` pretend the entity doesn't exist so + /// it doesn't get modified from outside sources. + pub owner_entity: Option, + /// A counter for each entity that tracks how many updates we've observed + /// for it. + /// + /// This is used for shared worlds (i.e. swarms), to make sure we don't + /// update entities twice on accident. + pub updates_received: IntMap, +} + +impl PartialEntityInfos { + pub fn new(owner_entity: Option) -> Self { + Self { + owner_entity, + updates_received: IntMap::default(), } } } -// when a local entity is added, if there was already an entity with the same id -// then delete the old entity -#[allow(clippy::type_complexity)] -pub fn deduplicate_local_entities( - mut commands: Commands, - mut query: Query< - (Entity, &MinecraftEntityId, &WorldName), - (Changed, With), - >, - instance_container: Res, -) { - // if this entity already exists, remove the old one - for (new_entity, id, world_name) in query.iter_mut() { - if let Some(world_lock) = instance_container.get(world_name) { - let world = world_lock.write(); - if let Some(old_entity) = world.entity_by_id.get(id) { - if old_entity == &new_entity { - // lol - continue; - } - - commands.entity(*old_entity).despawn(); - debug!( - "Added local entity {id:?} / {new_entity:?} but already existed in world as {old_entity:?}, despawning {old_entity:?}" - ); - break; - } - } else { - error!("Entity was inserted into a world that doesn't exist."); - } - } -} - -pub fn update_uuid_index( - mut entity_infos: ResMut, - query: Query<(Entity, &EntityUuid, Option<&Local>), Changed>, -) { - for (entity, &uuid, local) in query.iter() { - // only add it if it doesn't already exist in - // entity_infos.entity_by_uuid - if local.is_none() { - if let Some(old_entity) = entity_infos.entity_by_uuid.get(&uuid) { - debug!( - "Entity with UUID {uuid:?} already existed in the world, not adding to - index (old ecs id: {old_entity:?} / new ecs id: {entity:?})" - ); - continue; - } - } - entity_infos.entity_by_uuid.insert(*uuid, entity); - } -} - -// /// Clear all entities in a chunk. This will not clear them from the -// /// shared storage unless there are no other references to them. -// pub fn clear_entities_in_chunk( -// mut commands: Commands, -// partial_entity_infos: &mut PartialEntityInfos, -// chunk: &ChunkPos, -// instance_container: &WorldContainer, -// world_name: &WorldName, -// mut query: Query<(&MinecraftEntityId, &mut ReferenceCount)>, -// ) { -// let world_lock = instance_container.get(world_name).unwrap(); -// let world = world_lock.read(); - -// if let Some(entities) = world.entities_by_chunk.get(chunk).cloned() { -// for &entity in &entities { -// let (id, mut reference_count) = query.get_mut(entity).unwrap(); -// if partial_entity_infos.loaded_entity_ids.remove(id) { -// // decrease the reference count -// **reference_count -= 1; -// } -// } -// } -// } - /// A world where the chunks are stored as weak pointers. This is used for /// shared worlds. #[derive(Default, Debug)] @@ -191,6 +92,18 @@ impl Instance { self.entity_by_id.get(entity_id).copied() } + pub fn get_block_state(&self, pos: &BlockPos) -> Option { + self.chunks.get_block_state(pos) + } + + pub fn get_fluid_state(&self, pos: &BlockPos) -> Option { + self.chunks.get_block_state(pos).map(FluidState::from) + } + + pub fn set_block_state(&self, pos: &BlockPos, state: BlockState) -> Option { + self.chunks.set_block_state(pos, state) + } + /// Find the coordinates of a block in the world. /// /// Note that this is sorted by `x+y+z` and not `x^2+y^2+z^2`, for @@ -290,31 +203,6 @@ impl Default for PartialInstance { } } -/// System to keep the entity_by_id index up-to-date. -pub fn update_entity_by_id_index( - mut query: Query< - (Entity, &MinecraftEntityId, &WorldName, Option<&Local>), - Changed, - >, - instance_container: Res, -) { - for (entity, id, world_name, local) in query.iter_mut() { - let world_lock = instance_container.get(world_name).unwrap(); - let mut world = world_lock.write(); - if local.is_none() { - if let Some(old_entity) = world.entity_by_id.get(id) { - debug!( - "Entity with ID {id:?} already existed in the world, not adding to - index (old ecs id: {old_entity:?} / new ecs id: {entity:?})" - ); - continue; - } - } - world.entity_by_id.insert(*id, entity); - debug!("Added {entity:?} to {world_name:?} with {id:?}."); - } -} - impl From for Instance { /// Make an empty world from this `ChunkStorage`. This is meant to be a /// convenience function for tests. diff --git a/azalea/Cargo.toml b/azalea/Cargo.toml index 4b396e39..da574353 100644 --- a/azalea/Cargo.toml +++ b/azalea/Cargo.toml @@ -40,6 +40,7 @@ thiserror = "^1.0.43" tokio = "^1.29.1" uuid = "1.4.0" bevy_log = "0.11.0" +azalea-entity = { version = "0.1.0", path = "../azalea-entity" } [features] default = ["log"] diff --git a/azalea/examples/testbot.rs b/azalea/examples/testbot.rs index 1774d005..d9bd8681 100644 --- a/azalea/examples/testbot.rs +++ b/azalea/examples/testbot.rs @@ -89,7 +89,7 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result< bot.disconnect(); } let Some(sender) = m.username() else { - return Ok(()) + return Ok(()); }; // let mut ecs = bot.ecs.lock(); // let entity = bot @@ -164,6 +164,21 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result< bot.chat("no diamond block found"); } } + "mineblock" => { + let target_pos = bot + .world() + .read() + .find_block(bot.position(), &azalea::Block::DiamondBlock.into()); + if let Some(target_pos) = target_pos { + // +1 to stand on top of the block + bot.chat("ok mining diamond block"); + bot.look_at(target_pos.center()); + bot.mine(target_pos).await; + bot.chat("finished mining"); + } else { + bot.chat("no diamond block found"); + } + } "lever" => { let target_pos = bot .world() @@ -171,7 +186,7 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result< .find_block(bot.position(), &azalea::Block::Lever.into()); let Some(target_pos) = target_pos else { bot.chat("no lever found"); - return Ok(()) + return Ok(()); }; bot.goto(BlockPosGoal::from(target_pos)); bot.look_at(target_pos.center()); @@ -188,7 +203,7 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result< .find_block(bot.position(), &azalea::Block::Chest.into()); let Some(target_pos) = target_pos else { bot.chat("no chest found"); - return Ok(()) + return Ok(()); }; bot.look_at(target_pos.center()); let container = bot.open_container(target_pos).await; diff --git a/azalea/src/bot.rs b/azalea/src/bot.rs index 47c825ca..7940e7b0 100644 --- a/azalea/src/bot.rs +++ b/azalea/src/bot.rs @@ -9,9 +9,10 @@ use crate::ecs::{ system::{Commands, Query}, }; use azalea_core::Vec3; +use azalea_entity::{ + clamp_look_direction, metadata::Player, EyeHeight, Jumping, Local, LookDirection, Position, +}; use azalea_physics::{force_jump_listener, PhysicsSet}; -use azalea_world::entity::{clamp_look_direction, EyeHeight, LookDirection}; -use azalea_world::entity::{metadata::Player, Jumping, Local, Position}; use bevy_app::{FixedUpdate, Update}; use bevy_ecs::prelude::Event; use bevy_ecs::schedule::IntoSystemConfigs; diff --git a/azalea/src/lib.rs b/azalea/src/lib.rs index 1c6966c5..297199a0 100644 --- a/azalea/src/lib.rs +++ b/azalea/src/lib.rs @@ -6,6 +6,7 @@ mod auto_respawn; mod bot; mod container; +pub mod mining; pub mod pathfinder; pub mod prelude; pub mod swarm; @@ -17,9 +18,10 @@ pub use azalea_brigadier as brigadier; pub use azalea_chat::FormattedText; pub use azalea_client::*; pub use azalea_core::{BlockPos, Vec3}; +pub use azalea_entity as entity; pub use azalea_protocol as protocol; pub use azalea_registry::{Block, EntityKind, Item}; -pub use azalea_world::{entity, Instance}; +pub use azalea_world::Instance; pub use bot::DefaultBotPlugins; use ecs::component::Component; use futures::Future; diff --git a/azalea/src/mining.rs b/azalea/src/mining.rs new file mode 100644 index 00000000..8ba16436 --- /dev/null +++ b/azalea/src/mining.rs @@ -0,0 +1,40 @@ +use azalea_client::{ + interact::SwingArmEvent, + mining::{Mining, StartMiningBlockEvent}, + Client, TickBroadcast, +}; +use azalea_core::BlockPos; + +pub trait MiningExt { + /// Start mining a block. + async fn mine(&mut self, position: BlockPos); +} + +impl MiningExt for Client { + /// Start mining a block. This won't turn the bot's head towards the block, + /// so you'll have to do that yourself with [`look_at`]. + /// + /// [`look_at`]: crate::prelude::BotClientExt::look_at + async fn mine(&mut self, position: BlockPos) { + self.ecs.lock().send_event(StartMiningBlockEvent { + entity: self.entity, + position, + }); + // vanilla sends an extra swing arm packet when we start mining + self.ecs.lock().send_event(SwingArmEvent { + entity: self.entity, + }); + + let mut receiver = { + let ecs = self.ecs.lock(); + let tick_broadcast = ecs.resource::(); + tick_broadcast.subscribe() + }; + while receiver.recv().await.is_ok() { + let ecs = self.ecs.lock(); + if ecs.get::(self.entity).is_none() { + break; + } + } + } +} diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index 9547d263..f4e4d599 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -16,13 +16,11 @@ use crate::ecs::{ use astar::Edge; use azalea_client::{StartSprintEvent, StartWalkEvent}; use azalea_core::{BlockPos, CardinalDirection}; +use azalea_entity::metadata::Player; +use azalea_entity::Local; +use azalea_entity::{Physics, Position}; use azalea_physics::PhysicsSet; -use azalea_world::entity::metadata::Player; -use azalea_world::entity::Local; -use azalea_world::{ - entity::{Physics, Position, WorldName}, - InstanceContainer, -}; +use azalea_world::{InstanceContainer, InstanceName}; use bevy_app::{FixedUpdate, Update}; use bevy_ecs::prelude::Event; use bevy_ecs::schedule::IntoSystemConfigs; @@ -106,7 +104,7 @@ pub struct ComputePath(Task>); fn goto_listener( mut commands: Commands, mut events: EventReader, - mut query: Query<(&Position, &WorldName)>, + mut query: Query<(&Position, &InstanceName)>, instance_container: Res, ) { let thread_pool = AsyncComputeTaskPool::get(); diff --git a/azalea/src/prelude.rs b/azalea/src/prelude.rs index 87cb0b53..ff3c11de 100644 --- a/azalea/src/prelude.rs +++ b/azalea/src/prelude.rs @@ -2,8 +2,8 @@ //! re-exported here. pub use crate::{ - bot::BotClientExt, container::ContainerClientExt, pathfinder::PathfinderClientExt, - ClientBuilder, + bot::BotClientExt, container::ContainerClientExt, mining::MiningExt, + pathfinder::PathfinderClientExt, ClientBuilder, }; pub use azalea_client::{Account, Client, Event}; // this is necessary to make the macros that reference bevy_ecs work diff --git a/azalea/src/swarm/events.rs b/azalea/src/swarm/events.rs index b4752abf..3b290608 100644 --- a/azalea/src/swarm/events.rs +++ b/azalea/src/swarm/events.rs @@ -1,5 +1,5 @@ use azalea_client::LocalPlayer; -use azalea_world::entity::MinecraftEntityId; +use azalea_world::MinecraftEntityId; use bevy_app::{App, Plugin, Update}; use bevy_ecs::prelude::*; use derive_more::{Deref, DerefMut}; diff --git a/codegen/.gitignore b/codegen/.gitignore index 2ef6e1be..ee2504d7 100755 --- a/codegen/.gitignore +++ b/codegen/.gitignore @@ -1,3 +1,5 @@ -downloads __pycache__ *.tmp + +downloads +__cache__ diff --git a/codegen/genblocks.py b/codegen/genblocks.py index 45e7683e..5e28b60a 100755 --- a/codegen/genblocks.py +++ b/codegen/genblocks.py @@ -20,7 +20,7 @@ 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) + block_states_burger, block_states_report, pixlyzer_block_datas, ordered_blocks, mappings) lib.code.shapes.generate_block_shapes( pixlyzer_block_datas, shape_datas['shapes'], shape_datas['aabbs'], block_states_report, block_states_burger, mappings) diff --git a/codegen/genregistries.py b/codegen/genregistries.py index e24dcc6a..01e84cb3 100755 --- a/codegen/genregistries.py +++ b/codegen/genregistries.py @@ -3,16 +3,30 @@ import lib.code.registry import lib.code.version import lib.code.packet import lib.code.utils +import lib.code.tags import lib.download import lib.extract import lib.utils -version_id = lib.code.version.get_version_id() -registries = lib.extract.get_registries_report(version_id) +def generate(version_id: str): + registries = lib.extract.get_registries_report(version_id) -lib.code.registry.generate_registries(registries) -lib.code.inventory.update_menus(registries['minecraft:menu']['entries']) + lib.code.registry.generate_registries(registries) + lib.code.inventory.update_menus(registries['minecraft:menu']['entries']) -lib.code.utils.fmt() -print('Done!') + block_tags = lib.extract.get_registry_tags(version_id, 'blocks') + item_tags = lib.extract.get_registry_tags(version_id, 'items') + fluid_tags = lib.extract.get_registry_tags(version_id, 'fluids') + + lib.code.tags.generate_tags(block_tags, 'blocks', 'Block') + lib.code.tags.generate_tags(item_tags, 'items', 'Item') + lib.code.tags.generate_tags(fluid_tags, 'fluids', 'Fluid') + + lib.code.utils.fmt() + + print('Done!') + +if __name__ == '__main__': + version_id = lib.code.version.get_version_id() + generate(version_id) diff --git a/codegen/lib/code/blocks.py b/codegen/lib/code/blocks.py index a01df648..3af19fa8 100755 --- a/codegen/lib/code/blocks.py +++ b/codegen/lib/code/blocks.py @@ -13,7 +13,7 @@ BLOCKS_RS_DIR = get_dir_location('../azalea-block/src/generated.rs') # - Block: Has properties and states. -def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: list[str], mappings: Mappings): +def generate_blocks(blocks_burger: dict, blocks_report: dict, pixlyzer_block_datas: dict, ordered_blocks: list[str], mappings: Mappings): with open(BLOCKS_RS_DIR, 'r') as f: existing_code = f.read().splitlines() @@ -90,6 +90,7 @@ def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: li for block_id in ordered_blocks: block_data_burger = blocks_burger[block_id] block_data_report = blocks_report['minecraft:' + block_id] + block_data_pixlyzer = pixlyzer_block_datas[f'minecraft:{block_id}'] block_properties = block_data_burger.get('states', []) block_properties_burger = block_data_burger.get('states', []) @@ -134,9 +135,28 @@ def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: li else: properties_code += '\n }' + # make the block behavior + behavior_constructor = 'BlockBehavior::new()' + # requires tool + if block_data_pixlyzer.get('requires_tool'): + behavior_constructor += '.requires_correct_tool_for_drops()' + # strength + destroy_time = block_data_pixlyzer.get('hardness') + explosion_resistance = block_data_pixlyzer.get('explosion_resistance') + if destroy_time and explosion_resistance: + behavior_constructor += f'.strength({destroy_time}, {explosion_resistance})' + elif destroy_time: + behavior_constructor += f'.destroy_time({destroy_time})' + elif explosion_resistance: + behavior_constructor += f'.explosion_resistance({explosion_resistance})' + # friction + friction = block_data_pixlyzer.get('friction') + if friction != None: + behavior_constructor += f'.friction({friction})' + # TODO: use burger to generate the blockbehavior new_make_block_states_macro_code.append( - f' {block_id} => BlockBehavior::default(), {properties_code},') + f' {block_id} => {behavior_constructor}, {properties_code},') new_make_block_states_macro_code.append(' }') new_make_block_states_macro_code.append('}') diff --git a/codegen/lib/code/shapes.py b/codegen/lib/code/shapes.py index 7682fe53..18f2ccbd 100755 --- a/codegen/lib/code/shapes.py +++ b/codegen/lib/code/shapes.py @@ -66,7 +66,7 @@ def simplify_shapes(blocks: dict, shapes: dict, aabbs: dict): def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report, block_datas_burger, mappings: Mappings): - # look at downloads/generator-mod-*/blockCollisionShapes.json for format of blocks and shapes + # look at __cache__/generator-mod-*/blockCollisionShapes.json for format of blocks and shapes generated_shape_code = '' for (shape_id, shape) in sorted(shapes.items(), key=lambda shape: int(shape[0])): diff --git a/codegen/lib/code/tags.py b/codegen/lib/code/tags.py new file mode 100644 index 00000000..40b60ae3 --- /dev/null +++ b/codegen/lib/code/tags.py @@ -0,0 +1,35 @@ +from lib.utils import to_snake_case, upper_first_letter, get_dir_location, to_camel_case + +REGISTRIES_DIR = get_dir_location('../azalea-registry/src/tags') + + +def generate_tags(registries: dict, file_name: str, struct_name: str): + tags_dir = f'{REGISTRIES_DIR}/{file_name}.rs' + + generated = f'''// This file was generated by codegen/lib/code/tags.py, don't edit it manually! + +use std::collections::HashSet; + +use once_cell::sync::Lazy; + +use crate::{struct_name}; + +''' + + for tag_name, tag in registries.items(): + tag_name = tag_name.replace('/', '_') + static_set_name = to_snake_case(tag_name).upper() + generated += f'pub static {static_set_name}: Lazy> = Lazy::new(|| HashSet::from_iter(vec![' + + queue = tag['values'].copy() + while queue != []: + item = queue.pop(0) + namespace, item_name = item.split(':') + if namespace[0] == '#': + queue += registries[item_name]['values'] + continue + generated += f'{struct_name}::{upper_first_letter(to_camel_case(item_name))},\n' + generated += ']));\n' + + with open(tags_dir, 'w') as f: + f.write(generated) \ No newline at end of file diff --git a/codegen/lib/download.py b/codegen/lib/download.py index 1b22fbcc..319c6080 100755 --- a/codegen/lib/download.py +++ b/codegen/lib/download.py @@ -5,47 +5,47 @@ import requests import json import os -# make sure the downloads directory exists -print('Making downloads') -if not os.path.exists(get_dir_location('downloads')): - print('Made downloads directory.', get_dir_location('downloads')) - os.mkdir(get_dir_location('downloads')) +# make sure the cache directory exists +print('Making __cache__') +if not os.path.exists(get_dir_location('__cache__')): + print('Made __cache__ directory.', get_dir_location('__cache__')) + os.mkdir(get_dir_location('__cache__')) def get_burger(): - if not os.path.exists(get_dir_location('downloads/Burger')): + if not os.path.exists(get_dir_location('__cache__/Burger')): print('\033[92mDownloading Burger...\033[m') os.system( - f'cd {get_dir_location("downloads")} && git clone https://github.com/pokechu22/Burger && cd Burger && git pull') + f'cd {get_dir_location("__cache__")} && git clone https://github.com/pokechu22/Burger && cd Burger && git pull') print('\033[92mInstalling dependencies...\033[m') - os.system(f'cd {get_dir_location("downloads")}/Burger && pip install six jawa') + os.system(f'cd {get_dir_location("__cache__")}/Burger && pip install six jawa') def get_pixlyzer(): - if not os.path.exists(get_dir_location('downloads/pixlyzer')): + if not os.path.exists(get_dir_location('__cache__/pixlyzer')): print('\033[92mDownloading bixilon/pixlyzer...\033[m') os.system( - f'cd {get_dir_location("downloads")} && git clone https://gitlab.bixilon.de/bixilon/pixlyzer.git && cd pixlyzer && git pull') - return get_dir_location('downloads/pixlyzer') + f'cd {get_dir_location("__cache__")} && git clone https://gitlab.bixilon.de/bixilon/pixlyzer.git && cd pixlyzer && git pull') + return get_dir_location('__cache__/pixlyzer') def get_version_manifest(): - if not os.path.exists(get_dir_location(f'downloads/version_manifest.json')): + if not os.path.exists(get_dir_location(f'__cache__/version_manifest.json')): print( f'\033[92mDownloading version manifest...\033[m') version_manifest_data = requests.get( 'https://piston-meta.mojang.com/mc/game/version_manifest_v2.json').json() - with open(get_dir_location(f'downloads/version_manifest.json'), 'w') as f: + with open(get_dir_location(f'__cache__/version_manifest.json'), 'w') as f: json.dump(version_manifest_data, f) else: - with open(get_dir_location(f'downloads/version_manifest.json'), 'r') as f: + with open(get_dir_location(f'__cache__/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(get_dir_location(f'downloads/{version_id}.json')): + if not os.path.exists(get_dir_location(f'__cache__/{version_id}.json')): version_manifest_data = get_version_manifest() print( @@ -55,60 +55,60 @@ def get_version_data(version_id: str): filter(lambda v: v['id'] == version_id, version_manifest_data['versions']))['url'] except StopIteration: raise ValueError( - f'No version with id {version_id} found. Maybe delete downloads/version_manifest.json and try again?') + f'No version with id {version_id} found. Maybe delete __cache__/version_manifest.json and try again?') package_data = requests.get(package_url).json() - with open(get_dir_location(f'downloads/{version_id}.json'), 'w') as f: + with open(get_dir_location(f'__cache__/{version_id}.json'), 'w') as f: json.dump(package_data, f) else: - with open(get_dir_location(f'downloads/{version_id}.json'), 'r') as f: + with open(get_dir_location(f'__cache__/{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(get_dir_location(f'downloads/client-{version_id}.jar')): + if not os.path.exists(get_dir_location(f'__cache__/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(get_dir_location(f'downloads/client-{version_id}.jar'), 'wb') as f: + with open(get_dir_location(f'__cache__/client-{version_id}.jar'), 'wb') as f: f.write(requests.get(client_jar_url).content) def get_server_jar(version_id: str): - if not os.path.exists(get_dir_location(f'downloads/server-{version_id}.jar')): + if not os.path.exists(get_dir_location(f'__cache__/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: + with open(get_dir_location(f'__cache__/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(get_dir_location(f'downloads/mappings-{version_id}.txt')): + if not os.path.exists(get_dir_location(f'__cache__/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(get_dir_location(f'downloads/mappings-{version_id}.txt'), 'w') as f: + with open(get_dir_location(f'__cache__/mappings-{version_id}.txt'), 'w') as f: f.write(mappings_text) else: - with open(get_dir_location(f'downloads/mappings-{version_id}.txt'), 'r') as f: + with open(get_dir_location(f'__cache__/mappings-{version_id}.txt'), 'r') as f: mappings_text = f.read() return Mappings.parse(mappings_text) def get_yarn_versions(): # https://meta.fabricmc.net/v2/versions/yarn - if not os.path.exists(get_dir_location('downloads/yarn_versions.json')): + if not os.path.exists(get_dir_location('__cache__/yarn_versions.json')): print('\033[92mDownloading yarn versions...\033[m') yarn_versions_data = requests.get( 'https://meta.fabricmc.net/v2/versions/yarn').json() - with open(get_dir_location('downloads/yarn_versions.json'), 'w') as f: + with open(get_dir_location('__cache__/yarn_versions.json'), 'w') as f: json.dump(yarn_versions_data, f) else: - with open(get_dir_location('downloads/yarn_versions.json'), 'r') as f: + with open(get_dir_location('__cache__/yarn_versions.json'), 'r') as f: yarn_versions_data = json.load(f) return yarn_versions_data @@ -121,7 +121,7 @@ def get_yarn_data(version_id: str): def get_fabric_api_versions(): # https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api/maven-metadata.xml - if not os.path.exists(get_dir_location('downloads/fabric_api_versions.json')): + if not os.path.exists(get_dir_location('__cache__/fabric_api_versions.json')): print('\033[92mDownloading Fabric API versions...\033[m') fabric_api_versions_xml_text = requests.get( 'https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api/maven-metadata.xml').text @@ -138,17 +138,17 @@ def get_fabric_api_versions(): for version_el in versions_el.findall('version'): fabric_api_versions.append(version_el.text) - with open(get_dir_location('downloads/fabric_api_versions.json'), 'w') as f: + with open(get_dir_location('__cache__/fabric_api_versions.json'), 'w') as f: f.write(json.dumps(fabric_api_versions)) else: - with open(get_dir_location('downloads/fabric_api_versions.json'), 'r') as f: + with open(get_dir_location('__cache__/fabric_api_versions.json'), 'r') as f: fabric_api_versions = json.loads(f.read()) return fabric_api_versions def get_fabric_loader_versions(): # https://meta.fabricmc.net/v2/versions/loader - if not os.path.exists(get_dir_location('downloads/fabric_loader_versions.json')): + if not os.path.exists(get_dir_location('__cache__/fabric_loader_versions.json')): print('\033[92mDownloading Fabric loader versions...\033[m') fabric_api_versions_json = requests.get( 'https://meta.fabricmc.net/v2/versions/loader').json() @@ -157,10 +157,10 @@ def get_fabric_loader_versions(): for version in fabric_api_versions_json: fabric_api_versions.append(version['version']) - with open(get_dir_location('downloads/fabric_loader_versions.json'), 'w') as f: + with open(get_dir_location('__cache__/fabric_loader_versions.json'), 'w') as f: f.write(json.dumps(fabric_api_versions)) else: - with open(get_dir_location('downloads/fabric_loader_versions.json'), 'r') as f: + with open(get_dir_location('__cache__/fabric_loader_versions.json'), 'r') as f: fabric_api_versions = json.loads(f.read()) return fabric_api_versions @@ -174,14 +174,14 @@ def clear_version_cache(): 'fabric_loader_versions.json' ] for file in files: - if os.path.exists(get_dir_location(f'downloads/{file}')): - os.remove(get_dir_location(f'downloads/{file}')) + if os.path.exists(get_dir_location(f'__cache__/{file}')): + os.remove(get_dir_location(f'__cache__/{file}')) - burger_path = get_dir_location("downloads/Burger") + burger_path = get_dir_location("__cache__/Burger") if os.path.exists(burger_path): os.system( f'cd {burger_path} && git pull') - pixlyzer_path = get_dir_location('downloads/pixlyzer') + pixlyzer_path = get_dir_location('__cache__/pixlyzer') if os.path.exists(pixlyzer_path): os.system( f'cd {pixlyzer_path} && git pull') \ No newline at end of file diff --git a/codegen/lib/extract.py b/codegen/lib/extract.py index f7c78d29..608673fa 100755 --- a/codegen/lib/extract.py +++ b/codegen/lib/extract.py @@ -12,27 +12,44 @@ import os def generate_data_from_server_jar(version_id: str): - if os.path.exists(get_dir_location(f'downloads/generated-{version_id}')): + if os.path.exists(get_dir_location(f'__cache__/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}")}\"' + f'cd {get_dir_location(f"__cache__")} && java -DbundlerMainClass=net.minecraft.data.Main -jar {get_dir_location(f"__cache__/server-{version_id}.jar")} --all --output \"{get_dir_location(f"__cache__/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: + with open(get_dir_location(f'__cache__/generated-{version_id}/reports/blocks.json'), 'r') as f: return json.load(f) def get_registries_report(version_id: str): generate_data_from_server_jar(version_id) - with open(get_dir_location(f'downloads/generated-{version_id}/reports/registries.json'), 'r') as f: + with open(get_dir_location(f'__cache__/generated-{version_id}/reports/registries.json'), 'r') as f: return json.load(f) +def get_registry_tags(version_id: str, name: str): + generate_data_from_server_jar(version_id) + tags_directory = get_dir_location(f'__cache__/generated-{version_id}/data/minecraft/tags/{name}') + if not os.path.exists(tags_directory): + return {} + tags = {} + for root, dirs, files in os.walk(tags_directory, topdown=False): + for name in files: + file = os.path.join(root, name) + relative_path = file.replace(tags_directory, '')[1:] + if not file.endswith('.json'): + continue + with open(file, 'r') as f: + tags[relative_path[:-5]] = json.load(f) + return tags + + def get_block_states_burger(version_id: str): burger_data = get_burger_data_for_version(version_id) return burger_data[0]['blocks']['block'] @@ -96,15 +113,15 @@ def run_python_command_and_download_deps(command): def get_burger_data_for_version(version_id: str): - if not os.path.exists(get_dir_location(f'downloads/burger-{version_id}.json')): + if not os.path.exists(get_dir_location(f'__cache__/burger-{version_id}.json')): get_burger() get_client_jar(version_id) print('\033[92mRunning Burger...\033[m') run_python_command_and_download_deps( - f'cd {get_dir_location("downloads/Burger")} && {determine_python_command()} munch.py {get_dir_location("downloads")}/client-{version_id}.jar --output {get_dir_location("downloads")}/burger-{version_id}.json' + f'cd {get_dir_location("__cache__/Burger")} && {determine_python_command()} munch.py {get_dir_location("__cache__")}/client-{version_id}.jar --output {get_dir_location("__cache__")}/burger-{version_id}.json' ) - with open(get_dir_location(f'downloads/burger-{version_id}.json'), 'r') as f: + with open(get_dir_location(f'__cache__/burger-{version_id}.json'), 'r') as f: return json.load(f) @@ -113,7 +130,7 @@ def get_pixlyzer_data(version_id: str, category: str): Gets data from Pixlyzer. Note that this requires Yarn to release updates first. ''' - target_dir = get_dir_location(f'downloads/pixlyzer-{version_id}') + target_dir = get_dir_location(f'__cache__/pixlyzer-{version_id}') # TODO: right now this False is hard-coded, it should retry with this # enabled if # initially getting the data fails @@ -249,7 +266,7 @@ def get_pixlyzer_data(version_id: str, category: str): def get_file_from_jar(version_id: str, file_dir: str): get_client_jar(version_id) - with ZipFile(get_dir_location(f'downloads/client-{version_id}.jar')) as z: + with ZipFile(get_dir_location(f'__cache__/client-{version_id}.jar')) as z: with z.open(file_dir) as f: return f.read() diff --git a/codegen/migrate.py b/codegen/migrate.py index 0222ab00..6e51c2df 100755 --- a/codegen/migrate.py +++ b/codegen/migrate.py @@ -133,9 +133,8 @@ language = lib.extract.get_en_us_lang(new_version_id) lib.code.language.write_language(language) print('Generating registries...') -registries = lib.extract.get_registries_report(new_version_id) -lib.code.registry.generate_registries(registries) -lib.code.inventory.update_menus(registries['minecraft:menu']['entries']) +import genregistries +genregistries.generate(new_version_id) print('Generating entity metadata...') burger_entities_data = new_burger_data[0]['entities']