From 09790fc0939c29592e57bf72e921f2c729e982d2 Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Sat, 29 Aug 2026 15:58:32 +0200 Subject: [PATCH] fix: slime spawns --- Cargo.lock | 295 ++-- Cargo.toml | 2 +- assets/entities.json | 2 +- .../pumpkin-data/src/generated/entity_type.rs | 709 +++++++++- crates/pumpkin-inventory/Cargo.toml | 1 + crates/pumpkin-inventory/src/lib.rs | 9 +- .../src/merchant/merchant_screen_handler.rs | 3 +- .../src/player/player_inventory.rs | 6 +- crates/pumpkin-plugin-utils/Cargo.toml | 2 +- crates/pumpkin-plugin-utils/src/http.rs | 37 +- crates/pumpkin-util/Cargo.toml | 2 +- crates/pumpkin-util/src/jwt/mod.rs | 58 +- .../pumpkin-world/src/chunk/format/linear.rs | 8 +- crates/pumpkin-world/src/chunk/format/mod.rs | 44 +- .../src/chunk_system/schedule.rs | 229 ++- crates/pumpkin-world/src/lighting/engine.rs | 640 ++++++--- crates/pumpkin-world/src/lighting/storage.rs | 6 + crates/pumpkin-world/src/poi/mod.rs | 22 +- crates/pumpkin/Cargo.toml | 2 +- .../src/block/blocks/sculk/sculk_vein.rs | 8 +- .../pumpkin/src/block/blocks/trial_spawner.rs | 101 +- .../pumpkin/src/block/entities/mob_spawner.rs | 14 +- .../src/block/entities/trial_spawner.rs | 1243 ++++++++++++++++- crates/pumpkin/src/block/entities/vault.rs | 8 +- .../pumpkin/src/command/args/gameprofile.rs | 4 +- .../command/argument_types/game_profile.rs | 4 +- .../src/command/commands/fetchprofile.rs | 20 +- .../pumpkin/src/command/commands/fillbiome.rs | 6 +- .../pumpkin/src/command/commands/pumpkin.rs | 54 +- crates/pumpkin/src/data/usercache.rs | 6 +- crates/pumpkin/src/entity/attributes.rs | 8 +- crates/pumpkin/src/entity/effect/weaving.rs | 5 +- crates/pumpkin/src/entity/lightning.rs | 6 +- crates/pumpkin/src/entity/living.rs | 46 +- crates/pumpkin/src/entity/mod.rs | 29 +- .../src/entity/passive/villager/mod.rs | 6 +- crates/pumpkin/src/entity/player.rs | 509 ++----- .../pumpkin/src/entity/player/statistics.rs | 4 +- crates/pumpkin/src/net/authentication.rs | 91 +- crates/pumpkin/src/net/chunk_sender.rs | 311 +++++ .../src/net/java/login/encryption_response.rs | 10 +- .../pumpkin/src/net/java/play/chunk_batch.rs | 4 +- crates/pumpkin/src/net/mod.rs | 2 + .../plugin/loader/wasm/wasm_host/signature.rs | 46 +- crates/pumpkin/src/server/enchantment.rs | 6 +- crates/pumpkin/src/server/mod.rs | 24 +- crates/pumpkin/src/world/chunker.rs | 60 +- crates/pumpkin/src/world/custom_bossbar.rs | 6 +- crates/pumpkin/src/world/entity_tracker.rs | 461 ++++++ crates/pumpkin/src/world/mod.rs | 171 ++- crates/pumpkin/src/world/natural_spawner.rs | 9 +- crates/pumpkin/src/world/scoreboard.rs | 30 +- tools/pumpkin-codegen/src/entity_type.rs | 47 + 53 files changed, 4229 insertions(+), 1207 deletions(-) create mode 100644 crates/pumpkin/src/net/chunk_sender.rs create mode 100644 crates/pumpkin/src/world/entity_tracker.rs diff --git a/Cargo.lock b/Cargo.lock index a67dac32a..be4bd2e19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -832,35 +832,6 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" -[[package]] -name = "cookie" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cookie_store" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" -dependencies = [ - "cookie", - "document-features", - "idna", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "time", - "url", -] - [[package]] name = "cpp_demangle" version = "0.5.1" @@ -1444,15 +1415,6 @@ dependencies = [ "syn 3.0.4", ] -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - [[package]] name = "ecdsa" version = "0.16.9" @@ -1824,8 +1786,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1835,9 +1799,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "rand_core 0.10.1", + "wasm-bindgen", ] [[package]] @@ -2096,6 +2062,22 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + [[package]] name = "hyper-timeout" version = "0.5.2" @@ -2115,13 +2097,16 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", "futures-util", "http", "http-body", "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", "socket2", "tokio", @@ -2466,12 +2451,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" - [[package]] name = "lock_api" version = "0.4.14" @@ -2487,6 +2466,12 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lz4-java-wrc" version = "0.2.0" @@ -3346,6 +3331,7 @@ dependencies = [ "pumpkin-world", "rand", "rayon", + "reqwest", "rsa", "rustc-hash", "rustc_version_runtime", @@ -3364,7 +3350,6 @@ dependencies = [ "tracing", "tracing-serde-structured", "tracing-subscriber", - "ureq", "uuid", "wasm-encoder 0.257.1", "wasmparser 0.257.1", @@ -3455,6 +3440,7 @@ dependencies = [ "pumpkin-util", "pumpkin-world", "rand", + "rustc-hash", "thiserror 2.0.20", "tracing", ] @@ -3502,12 +3488,12 @@ name = "pumpkin-plugin-utils" version = "0.1.0" dependencies = [ "pumpkin-plugin-api", + "reqwest", "serde", "serde_json", "tempfile", "thiserror 2.0.20", "tracing", - "ureq", ] [[package]] @@ -3554,13 +3540,13 @@ dependencies = [ "pumpkin-codecs", "pumpkin-nbt", "quote", + "reqwest", "rsa", "serde", "serde_json", "sha2 0.11.0", "syn 3.0.4", "thiserror 2.0.20", - "ureq", "uuid", ] @@ -3605,6 +3591,62 @@ version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" +[[package]] +name = "quinn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp 0.5.15", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.20", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83" +dependencies = [ + "bytes", + "getrandom 0.4.3", + "lru-slab", + "rand", + "rand_pcg", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.20", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.61.2", +] + [[package]] name = "quinn-udp" version = "0.6.1" @@ -3668,6 +3710,15 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "rayon" version = "1.12.0" @@ -3775,6 +3826,47 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -4217,6 +4309,7 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ + "web-time", "zeroize", ] @@ -4262,6 +4355,12 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a252f5e20f038fe7b4ea53e073e65398d652c864cc162fc77c56c2f13717b888" +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + [[package]] name = "same-file" version = "1.0.6" @@ -4385,6 +4484,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serdect" version = "0.4.3" @@ -4631,6 +4742,9 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] [[package]] name = "synstructure" @@ -4986,6 +5100,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.13.1", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -5121,37 +5253,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "ureq" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972d7902c8735f2695410b8aed7df6ed12a47394aa1c8d7af49f0497b731a94d" -dependencies = [ - "base64 0.23.1", - "cookie_store", - "log", - "percent-encoding", - "rustls", - "rustls-pki-types", - "serde", - "serde_json", - "ureq-proto", - "utf8-zero", - "webpki-roots", -] - -[[package]] -name = "ureq-proto" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da5f78b09e6941e1a0f2e30e695e4b120377b54d5e0aec11b594bb57b3971613" -dependencies = [ - "base64 0.23.1", - "http", - "httparse", - "log", -] - [[package]] name = "url" version = "2.5.8" @@ -5164,12 +5265,6 @@ dependencies = [ "serde", ] -[[package]] -name = "utf8-zero" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -5245,6 +5340,16 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.127" @@ -5656,6 +5761,26 @@ dependencies = [ "wasmtime", ] +[[package]] +name = "web-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "1.0.9" @@ -5678,7 +5803,7 @@ dependencies = [ "event-listener", "futures", "log", - "quinn-udp", + "quinn-udp 0.6.1", "rtc", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 7c803e971..321d346e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -207,7 +207,7 @@ time = { version = "0.3", default-features = false, features = ["std"] } arc-swap = { version = "1.9", default-features = false } tokio-util = { version = "0.7.19", default-features = false } toml = { version = "1.1", default-features = false, features = ["parse", "display", "serde"] } -ureq = { version = "3.4.0", default-features = false, features = ["rustls"] } +reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json", "http2"] } notify = { version = "8.2.0", default-features = false, features = ["macos_fsevent"] } sysinfo = { version = "0.39", default-features = false, features = ["system"] } diff --git a/assets/entities.json b/assets/entities.json index 853a00402..3f7fb945a 100644 --- a/assets/entities.json +++ b/assets/entities.json @@ -1 +1 @@ -{"acacia_boat":{"id":0,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"acacia_chest_boat":{"id":1,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"allay":{"id":2,"max_health":20.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.10000000149011612},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.10000000149011612},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.35,0.6],"eye_height":0.36,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/allay"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"area_effect_cloud":{"id":3,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":true,"category":"MISC","can_spawn_far_from_player":true,"dimension":[6.0,0.5],"eye_height":0.425,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"armadillo":{"id":4,"max_health":12.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":12.0},{"movement_efficiency":0.0},{"movement_speed":0.14},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.7,0.65],"eye_height":0.26,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/armadillo"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"armor_stand":{"id":5,"max_health":20.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,1.975],"eye_height":1.7775,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/armor_stand"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"arrow":{"id":6,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,0.5],"eye_height":0.13,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"axolotl":{"id":7,"max_health":14.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":14.0},{"movement_efficiency":0.0},{"movement_speed":1.0},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"AXOLOTLS","can_spawn_far_from_player":false,"dimension":[0.75,0.42],"eye_height":0.2751,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/axolotl"},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bamboo_chest_raft":{"id":8,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bamboo_raft":{"id":9,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bat":{"id":10,"max_health":6.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":6.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"AMBIENT","can_spawn_far_from_player":false,"dimension":[0.5,0.9],"eye_height":0.45,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/bat"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bee":{"id":11,"max_health":10.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.6000000238418579},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.55,0.5],"eye_height":0.3,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/bee"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"birch_boat":{"id":12,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"birch_chest_boat":{"id":13,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"blaze":{"id":14,"max_health":20.0,"experience_reward":10,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":48.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.8],"eye_height":1.53,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/blaze","pools":[{"entries":[{"name":"minecraft:blaze_rod","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"block_display":{"id":15,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bogged":{"id":16,"max_health":16.0,"experience_reward":5,"hurt_sound":"entity.bogged.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":16.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.99],"eye_height":1.74,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/bogged","pools":[{"entries":[{"name":"minecraft:arrow","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:tipped_arrow","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"limit":1,"function":"minecraft:enchanted_count_increase"},{"id":"minecraft:poison","function":"minecraft:set_potion"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"breeze":{"id":17,"max_health":30.0,"experience_reward":10,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":24.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.6299999952316284},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.77],"eye_height":1.3452,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/breeze","pools":[{"entries":[{"name":"minecraft:breeze_rod","functions":[{"count":{"min":1.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":1.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"breeze_wind_charge":{"id":18,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.3125,0.3125],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"camel":{"id":19,"max_health":32.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":32.0},{"movement_efficiency":0.0},{"movement_speed":0.09000000357627869},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.5},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.7,2.375],"eye_height":2.275,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/camel"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"camel_husk":{"id":20,"max_health":32.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":32.0},{"movement_efficiency":0.0},{"movement_speed":0.09000000357627869},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.5},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[1.7,2.375],"eye_height":2.275,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/camel_husk","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":2.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cat":{"id":21,"max_health":10.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.6,0.7],"eye_height":0.35,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/cat","pools":[{"entries":[{"name":"minecraft:string","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cave_spider":{"id":22,"max_health":12.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":12.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.7,0.5],"eye_height":0.45,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/cave_spider","pools":[{"entries":[{"name":"minecraft:string","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:spider_eye","functions":[{"count":{"min":-1.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cherry_boat":{"id":23,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cherry_chest_boat":{"id":24,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"chest_minecart":{"id":25,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"chicken":{"id":26,"max_health":4.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":4.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.4,0.7],"eye_height":0.644,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/chicken","pools":[{"entries":[{"name":"minecraft:feather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:chicken","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cod":{"id":27,"max_health":3.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":8,"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_AMBIENT","can_spawn_far_from_player":false,"dimension":[0.5,0.3],"eye_height":0.195,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/cod","pools":[{"entries":[{"name":"minecraft:cod","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone_meal","type":"minecraft:item"}],"conditions":[{"chance":0.05,"condition":"minecraft:random_chance"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"copper_golem":{"id":28,"max_health":12.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":12.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.49,0.98],"eye_height":0.8125,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/copper_golem","pools":[{"entries":[{"name":"minecraft:copper_ingot","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"command_block_minecart":{"id":29,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cow":{"id":30,"max_health":10.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.9,1.4],"eye_height":1.3,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/cow","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:beef","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"creaking":{"id":31,"max_health":1.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":32.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":1.0},{"movement_efficiency":0.0},{"movement_speed":0.4000000059604645},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0625},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.9,2.7],"eye_height":2.3,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/creaking"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"creeper":{"id":32,"max_health":20.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.7],"eye_height":1.445,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/creeper","pools":[{"entries":[{"name":"minecraft:gunpowder","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:creeper_drop_music_discs","expand":true,"type":"minecraft:tag"}],"conditions":[{"predicate":{"minecraft:entity_type":"#minecraft:skeletons"},"entity":"attacker","condition":"minecraft:entity_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"dark_oak_boat":{"id":33,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"dark_oak_chest_boat":{"id":34,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"dolphin":{"id":35,"max_health":10.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":1.2000000476837158},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_CREATURE","can_spawn_far_from_player":false,"dimension":[0.9,0.6],"eye_height":0.3,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/dolphin","pools":[{"entries":[{"name":"minecraft:cod","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"donkey":{"id":36,"max_health":53.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.5},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.3964844,1.5],"eye_height":1.425,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/donkey","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"dragon_fireball":{"id":37,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.0,1.0],"eye_height":0.85,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"drowned":{"id":38,"max_health":20.0,"experience_reward":5,"hurt_sound":"entity.drowned.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.74,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/drowned","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:copper_ingot","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.11,"enchanted_chance":{"base":0.13,"per_level_above_first":0.02,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"egg":{"id":39,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"elder_guardian":{"id":40,"max_health":80.0,"experience_reward":10,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":8.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":80.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[1.9975,1.9975],"eye_height":0.99875,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/elder_guardian","pools":[{"entries":[{"name":"minecraft:prismarine_shard","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:cod","weight":3,"functions":[{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"},{"name":"minecraft:prismarine_crystals","weight":2,"functions":[{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"type":"minecraft:empty"}],"rolls":1.0},{"entries":[{"name":"minecraft:wet_sponge","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0},{"entries":[{"value":"minecraft:gameplay/fishing/fish","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:loot_table"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0},{"entries":[{"weight":4,"type":"minecraft:empty"},{"name":"minecraft:tide_armor_trim_smithing_template","type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"enderman":{"id":41,"max_health":40.0,"experience_reward":5,"hurt_sound":"entity.enderman.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":7.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":64.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":40.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,2.9],"eye_height":2.55,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/enderman","pools":[{"entries":[{"name":"minecraft:ender_pearl","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"endermite":{"id":42,"max_health":8.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":8.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.4,0.3],"eye_height":0.13,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/endermite"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ender_dragon":{"id":43,"max_health":200.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":16.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":200.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[16.0,8.0],"eye_height":6.8,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/ender_dragon"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ender_pearl":{"id":44,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"end_crystal":{"id":45,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":true,"category":"MISC","can_spawn_far_from_player":true,"dimension":[2.0,2.0],"eye_height":1.7,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"evoker":{"id":46,"max_health":24.0,"experience_reward":10,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":12.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":24.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.6575,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/evoker","pools":[{"entries":[{"name":"minecraft:totem_of_undying","type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:emerald","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"evoker_fangs":{"id":47,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,0.8],"eye_height":0.68,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"experience_bottle":{"id":48,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"experience_orb":{"id":49,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,0.5],"eye_height":0.425,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"eye_of_ender":{"id":50,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"falling_block":{"id":51,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.98],"eye_height":0.83300006,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"fireball":{"id":52,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.0,1.0],"eye_height":0.85,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"firework_rocket":{"id":53,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"fox":{"id":54,"max_health":10.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":32.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":5.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.6,0.7],"eye_height":0.4,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/fox"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"frog":{"id":55,"max_health":10.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":10.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":1.0},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.5,0.5],"eye_height":0.425,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/frog"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"furnace_minecart":{"id":56,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ghast":{"id":57,"max_health":10.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":8.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.06},{"follow_range":100.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":1,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[4.0,4.0],"eye_height":2.6,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/ghast","pools":[{"entries":[{"name":"minecraft:ghast_tear","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:gunpowder","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:music_disc_tears","type":"minecraft:item"}],"conditions":[{"predicate":{"tags":[{"id":"minecraft:is_projectile","expected":true}],"direct_entity":{"minecraft:entity_type":"minecraft:fireball"}},"condition":"minecraft:damage_source_properties"},{"condition":"minecraft:killed_by_player"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"happy_ghast":{"id":58,"max_health":20.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":8.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.05},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.05},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":16.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":1,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[4.0,4.0],"eye_height":2.6,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/happy_ghast"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"giant":{"id":59,"max_health":100.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":50.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":16.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":100.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[3.6,12.0],"eye_height":10.44,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/giant"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"glow_item_frame":{"id":60,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,0.5],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"glow_squid":{"id":61,"max_health":10.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"UNDERGROUND_WATER_CREATURE","can_spawn_far_from_player":false,"dimension":[0.8,0.8],"eye_height":0.4,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/glow_squid","pools":[{"entries":[{"name":"minecraft:glow_ink_sac","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"goat":{"id":62,"max_health":10.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.9,1.3],"eye_height":1.105,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/goat"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"guardian":{"id":63,"max_health":30.0,"experience_reward":10,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.85,0.85],"eye_height":0.425,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/guardian","pools":[{"entries":[{"name":"minecraft:prismarine_shard","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:cod","weight":2,"functions":[{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"},{"name":"minecraft:prismarine_crystals","weight":2,"functions":[{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"type":"minecraft:empty"}],"rolls":1.0},{"entries":[{"value":"minecraft:gameplay/fishing/fish","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:loot_table"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"hoglin":{"id":64,"max_health":40.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":1.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.6000000238418579},{"max_absorption":0.0},{"max_health":40.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[1.3964844,1.4],"eye_height":1.19,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/hoglin","pools":[{"entries":[{"name":"minecraft:porkchop","functions":[{"count":{"min":2.0,"max":4.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"hopper_minecart":{"id":65,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"horse":{"id":66,"max_health":53.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.7},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.22499999403953552},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.3964844,1.6],"eye_height":1.52,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/horse","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"husk":{"id":67,"max_health":20.0,"experience_reward":5,"hurt_sound":"entity.husk.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.74,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/husk","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:rabbit_foot","conditions":[{"predicate":{"minecraft:vehicle":{"minecraft:entity_type":"minecraft:camel_husk"}},"entity":"this","condition":"minecraft:entity_properties"}],"functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:iron_ingot","type":"minecraft:item"},{"name":"minecraft:carrot","type":"minecraft:item"},{"name":"minecraft:potato","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"illusioner":{"id":68,"max_health":32.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":18.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":32.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.6575,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/illusioner"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"interaction":{"id":69,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"iron_golem":{"id":70,"max_health":100.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":15.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":1.0},{"max_absorption":0.0},{"max_health":100.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.4,2.7],"eye_height":2.295,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/iron_golem","pools":[{"entries":[{"name":"minecraft:poppy","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:iron_ingot","functions":[{"count":{"min":3.0,"max":5.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"item":{"id":71,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"item_display":{"id":72,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"item_frame":{"id":73,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,0.5],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"jungle_boat":{"id":74,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"jungle_chest_boat":{"id":75,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"leash_knot":{"id":76,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":false,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.375,0.5],"eye_height":0.0625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"lightning_bolt":{"id":77,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":false,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"llama":{"id":78,"max_health":53.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.5},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.9,1.87],"eye_height":1.7765,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/llama","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"llama_spit":{"id":79,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"magma_cube":{"id":80,"max_health":20.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.52,0.52],"eye_height":0.325,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/magma_cube","pools":[{"entries":[{"name":"minecraft:magma_cream","conditions":[{"term":{"predicate":{"source_entity":{"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"},"condition":"minecraft:inverted"},{"predicate":{"minecraft:type_specific/cube_mob":{"size":{"min":2}}},"entity":"this","condition":"minecraft:entity_properties"}],"functions":[{"count":{"min":-2.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:pearlescent_froglight","conditions":[{"predicate":{"source_entity":{"minecraft:components":{"minecraft:frog/variant":"minecraft:warm"},"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"},{"name":"minecraft:verdant_froglight","conditions":[{"predicate":{"source_entity":{"minecraft:components":{"minecraft:frog/variant":"minecraft:cold"},"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"},{"name":"minecraft:ochre_froglight","conditions":[{"predicate":{"source_entity":{"minecraft:components":{"minecraft:frog/variant":"minecraft:temperate"},"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mangrove_boat":{"id":81,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mangrove_chest_boat":{"id":82,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mannequin":{"id":83,"max_health":20.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.6,1.8],"eye_height":1.62,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/mannequin"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"marker":{"id":84,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"minecart":{"id":85,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mooshroom":{"id":86,"max_health":10.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.9,1.4],"eye_height":1.3,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/mooshroom","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:beef","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mule":{"id":87,"max_health":53.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.5},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.3964844,1.6],"eye_height":1.52,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/mule","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"nautilus":{"id":88,"max_health":15.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.30000001192092896},{"max_absorption":0.0},{"max_health":15.0},{"movement_efficiency":0.0},{"movement_speed":1.0},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_CREATURE","can_spawn_far_from_player":false,"dimension":[0.875,0.95],"eye_height":0.2751,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/nautilus","pools":[{"entries":[{"name":"minecraft:nautilus_shell","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.05,"enchanted_chance":{"base":0.060000002,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"oak_boat":{"id":89,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"oak_chest_boat":{"id":90,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ocelot":{"id":91,"max_health":10.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.6,0.7],"eye_height":0.595,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/ocelot"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING"}},"ominous_item_spawner":{"id":92,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"painting":{"id":93,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,0.5],"eye_height":0.425,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pale_oak_boat":{"id":94,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pale_oak_chest_boat":{"id":95,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"panda":{"id":96,"max_health":20.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.15000000596046448},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.3,1.25],"eye_height":1.0625,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/panda","pools":[{"entries":[{"name":"minecraft:bamboo","functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"parched":{"id":97,"max_health":16.0,"experience_reward":5,"hurt_sound":"entity.parched.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":16.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.99],"eye_height":1.74,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/parched","pools":[{"entries":[{"name":"minecraft:arrow","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:tipped_arrow","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"limit":1,"function":"minecraft:enchanted_count_increase"},{"id":"minecraft:weakness","function":"minecraft:set_potion"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"parrot":{"id":98,"max_health":6.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.4000000059604645},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":6.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.5,0.9],"eye_height":0.54,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/parrot","pools":[{"entries":[{"name":"minecraft:feather","functions":[{"count":{"min":1.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING"}},"phantom":{"id":99,"max_health":20.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.9,0.5],"eye_height":0.175,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/phantom","pools":[{"entries":[{"name":"minecraft:phantom_membrane","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pig":{"id":100,"max_health":10.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.9,0.9],"eye_height":0.765,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/pig","pools":[{"entries":[{"name":"minecraft:porkchop","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"piglin":{"id":101,"max_health":16.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":5.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":16.0},{"movement_efficiency":0.0},{"movement_speed":0.3499999940395355},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.79,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/piglin"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"piglin_brute":{"id":102,"max_health":50.0,"experience_reward":20,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":7.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":12.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":50.0},{"movement_efficiency":0.0},{"movement_speed":0.3499999940395355},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.79,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/piglin_brute"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pillager":{"id":103,"max_health":24.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":5.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":32.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":24.0},{"movement_efficiency":0.0},{"movement_speed":0.3499999940395355},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":1,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":true,"dimension":[0.6,1.95],"eye_height":1.6575,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/pillager","pools":[{"entries":[{"name":"minecraft:ominous_bottle","functions":[{"count":1.0,"function":"minecraft:set_count"},{"amplifier":{"min":0.0,"max":4.0,"type":"minecraft:uniform"},"function":"minecraft:set_ominous_bottle_amplifier"}],"type":"minecraft:item"}],"conditions":[{"predicate":{"minecraft:type_specific/raider":{"is_captain":true}},"entity":"this","condition":"minecraft:entity_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"polar_bear":{"id":104,"max_health":30.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":20.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.4,1.4],"eye_height":1.19,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/polar_bear","pools":[{"entries":[{"name":"minecraft:cod","weight":3,"functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:salmon","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"splash_potion":{"id":105,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"lingering_potion":{"id":106,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pufferfish":{"id":107,"max_health":3.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":8,"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_AMBIENT","can_spawn_far_from_player":false,"dimension":[0.7,0.7],"eye_height":0.455,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/pufferfish","pools":[{"entries":[{"name":"minecraft:pufferfish","functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone_meal","type":"minecraft:item"}],"conditions":[{"chance":0.05,"condition":"minecraft:random_chance"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"rabbit":{"id":108,"max_health":3.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.49,0.6],"eye_height":0.59,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/rabbit","pools":[{"entries":[{"name":"minecraft:rabbit_hide","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:rabbit","functions":[{"count":1.0,"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:rabbit_foot","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.1,"enchanted_chance":{"base":0.13,"per_level_above_first":0.03,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ravager":{"id":109,"max_health":100.0,"experience_reward":20,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":12.0},{"attack_knockback":1.5},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":32.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.75},{"max_absorption":0.0},{"max_health":100.0},{"movement_efficiency":0.0},{"movement_speed":0.3},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[1.95,2.2],"eye_height":1.8700001,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/ravager","pools":[{"entries":[{"name":"minecraft:saddle","functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"salmon":{"id":110,"max_health":3.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":5,"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_AMBIENT","can_spawn_far_from_player":false,"dimension":[0.7,0.4],"eye_height":0.26,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/salmon","pools":[{"entries":[{"name":"minecraft:salmon","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone_meal","type":"minecraft:item"}],"conditions":[{"chance":0.05,"condition":"minecraft:random_chance"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"sheep":{"id":111,"max_health":8.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":8.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.9,1.3],"eye_height":1.235,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/sheep","pools":[{"entries":[{"name":"minecraft:mutton","functions":[{"count":{"min":1.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"children":[{"value":"minecraft:entities/sheep/white","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"white"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/orange","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"orange"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/magenta","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"magenta"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/light_blue","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"light_blue"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/yellow","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"yellow"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/lime","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"lime"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/pink","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"pink"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/gray","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"gray"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/light_gray","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"light_gray"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/cyan","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"cyan"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/purple","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"purple"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/blue","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"blue"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/brown","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"brown"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/green","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"green"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/red","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"red"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/black","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"black"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"}],"type":"minecraft:alternatives"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"shulker":{"id":112,"max_health":30.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":true,"dimension":[1.0,1.0],"eye_height":0.5,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/shulker","pools":[{"entries":[{"name":"minecraft:shulker_shell","type":"minecraft:item"}],"conditions":[{"unenchanted_chance":0.5,"enchanted_chance":{"base":0.5625,"per_level_above_first":0.0625,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"shulker_bullet":{"id":113,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.3125,0.3125],"eye_height":0.265625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"silverfish":{"id":114,"max_health":8.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":1.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":8.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.4,0.3],"eye_height":0.13,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/silverfish"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"skeleton":{"id":115,"max_health":20.0,"experience_reward":5,"hurt_sound":"entity.skeleton.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.99],"eye_height":1.74,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/skeleton","pools":[{"entries":[{"name":"minecraft:arrow","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"skeleton_horse":{"id":116,"max_health":15.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.7},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":15.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.3964844,1.6],"eye_height":1.52,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/skeleton_horse","pools":[{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"slime":{"id":117,"max_health":20.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.52,0.52],"eye_height":0.325,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/slime","pools":[{"entries":[{"name":"minecraft:slime_ball","conditions":[{"term":{"predicate":{"source_entity":{"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"},"condition":"minecraft:inverted"}],"functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:slime_ball","conditions":[{"predicate":{"source_entity":{"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"conditions":[{"predicate":{"minecraft:type_specific/cube_mob":{"size":1}},"entity":"this","condition":"minecraft:entity_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"small_fireball":{"id":118,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.3125,0.3125],"eye_height":0.265625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"sniffer":{"id":119,"max_health":14.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":14.0},{"movement_efficiency":0.0},{"movement_speed":0.10000000149011612},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.9,1.75],"eye_height":1.05,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/sniffer"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"snowball":{"id":120,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"snow_golem":{"id":121,"max_health":4.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":4.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.7,1.9],"eye_height":1.7,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/snow_golem","pools":[{"entries":[{"name":"minecraft:snowball","functions":[{"count":{"min":0.0,"max":15.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spawner_minecart":{"id":122,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spectral_arrow":{"id":123,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,0.5],"eye_height":0.13,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spider":{"id":124,"max_health":16.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":16.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[1.4,0.9],"eye_height":0.65,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/spider","pools":[{"entries":[{"name":"minecraft:string","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:spider_eye","functions":[{"count":{"min":-1.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spruce_boat":{"id":125,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spruce_chest_boat":{"id":126,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"squid":{"id":127,"max_health":10.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_CREATURE","can_spawn_far_from_player":false,"dimension":[0.8,0.8],"eye_height":0.4,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/squid","pools":[{"entries":[{"name":"minecraft:ink_sac","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"stray":{"id":128,"max_health":20.0,"experience_reward":5,"hurt_sound":"entity.stray.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.99],"eye_height":1.74,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/stray","pools":[{"entries":[{"name":"minecraft:arrow","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:tipped_arrow","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"limit":1,"function":"minecraft:enchanted_count_increase"},{"id":"minecraft:slowness","function":"minecraft:set_potion"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"strider":{"id":129,"max_health":20.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.9,1.7],"eye_height":1.445,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/strider","pools":[{"entries":[{"name":"minecraft:string","functions":[{"count":{"min":2.0,"max":5.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_LAVA","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"sulfur_cube":{"id":130,"max_health":20.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":8.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.49,0.49],"eye_height":0.175,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/sulfur_cube"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"tadpole":{"id":131,"max_health":6.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":6.0},{"movement_efficiency":0.0},{"movement_speed":1.0},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":8,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.4,0.3],"eye_height":0.19500001,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/tadpole"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"text_display":{"id":132,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"tnt":{"id":133,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":true,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.98],"eye_height":0.15,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"tnt_minecart":{"id":134,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"trader_llama":{"id":135,"max_health":53.0,"experience_reward":1,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.5},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.9,1.87],"eye_height":1.7765,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/trader_llama","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"trident":{"id":136,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.5,0.5],"eye_height":0.13,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"tropical_fish":{"id":137,"max_health":3.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":8,"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_AMBIENT","can_spawn_far_from_player":false,"dimension":[0.5,0.4],"eye_height":0.26,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/tropical_fish","pools":[{"entries":[{"name":"minecraft:tropical_fish","functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone_meal","type":"minecraft:item"}],"conditions":[{"chance":0.05,"condition":"minecraft:random_chance"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"turtle":{"id":138,"max_health":30.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[1.2,0.4],"eye_height":0.34,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/turtle","pools":[{"entries":[{"name":"minecraft:seagrass","weight":3,"functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bowl","type":"minecraft:item"}],"conditions":[{"predicate":{"tags":[{"id":"minecraft:is_lightning","expected":true}]},"condition":"minecraft:damage_source_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"vex":{"id":139,"max_health":14.0,"experience_reward":3,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":4.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":14.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.4,0.8],"eye_height":0.51875,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/vex"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"villager":{"id":140,"max_health":20.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.6,1.95],"eye_height":1.62,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/villager"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"vindicator":{"id":141,"max_health":24.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":5.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":12.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":24.0},{"movement_efficiency":0.0},{"movement_speed":0.3499999940395355},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.6575,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/vindicator","pools":[{"entries":[{"name":"minecraft:emerald","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wandering_trader":{"id":142,"max_health":20.0,"experience_reward":0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.6,1.95],"eye_height":1.62,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/wandering_trader"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"warden":{"id":143,"max_health":500.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":30.0},{"attack_knockback":1.5},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":24.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":1.0},{"max_absorption":0.0},{"max_health":500.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.9,2.9],"eye_height":2.4650002,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/warden","pools":[{"entries":[{"name":"minecraft:sculk_catalyst","type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wind_charge":{"id":144,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.3125,0.3125],"eye_height":0.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"witch":{"id":145,"max_health":26.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":26.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.62,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/witch","pools":[{"entries":[{"name":"minecraft:glowstone_dust","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:sugar","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:spider_eye","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:glass_bottle","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:gunpowder","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:stick","weight":2,"functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":{"min":1.0,"max":3.0,"type":"minecraft:uniform"}},{"entries":[{"name":"minecraft:redstone","functions":[{"count":{"min":4.0,"max":8.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wither":{"id":146,"max_health":300.0,"experience_reward":50,"attributes":[{"air_drag_modifier":1.0},{"armor":4.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.6000000238418579},{"follow_range":40.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":300.0},{"movement_efficiency":0.0},{"movement_speed":0.6000000238418579},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.9,3.5],"eye_height":2.9750001,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/wither"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wither_skeleton":{"id":147,"max_health":20.0,"experience_reward":5,"hurt_sound":"entity.wither_skeleton.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.7,2.4],"eye_height":2.1,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/wither_skeleton","pools":[{"entries":[{"name":"minecraft:coal","functions":[{"count":{"min":-1.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:wither_skeleton_skull","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wither_skull":{"id":148,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.3125,0.3125],"eye_height":0.265625,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wolf":{"id":149,"max_health":8.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":4.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":8.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":8,"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"dimension":[0.6,0.85],"eye_height":0.68,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/wolf"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zoglin":{"id":150,"max_health":40.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":1.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.6000000238418579},{"max_absorption":0.0},{"max_health":40.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[1.3964844,1.4],"eye_height":1.19,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zoglin","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombie":{"id":151,"max_health":20.0,"experience_reward":5,"hurt_sound":"entity.zombie.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.74,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombie","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:red_mushroom","conditions":[{"predicate":{"minecraft:vehicle":{"minecraft:entity_type":"minecraft:zombie_horse"}},"entity":"this","condition":"minecraft:entity_properties"}],"functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:iron_ingot","type":"minecraft:item"},{"name":"minecraft:carrot","type":"minecraft:item"},{"name":"minecraft:potato","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0},{"entries":[{"name":"minecraft:music_disc_lava_chicken","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"predicate":{"minecraft:flags":{"is_baby":true},"minecraft:vehicle":{"minecraft:entity_type":"minecraft:chicken"}},"entity":"this","condition":"minecraft:entity_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombie_horse":{"id":152,"max_health":25.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.7},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":25.0},{"movement_efficiency":0.0},{"movement_speed":0.22499999403953552},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":6,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[1.3964844,1.6],"eye_height":1.52,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombie_horse","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":2.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombie_nautilus":{"id":153,"max_health":15.0,"experience_reward":2,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.30000001192092896},{"max_absorption":0.0},{"max_health":15.0},{"movement_efficiency":0.0},{"movement_speed":1.100000023841858},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.875,0.95],"eye_height":0.2751,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombie_nautilus","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombie_villager":{"id":154,"max_health":20.0,"experience_reward":5,"hurt_sound":"entity.zombie_villager.hurt","attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.74,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombie_villager","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:iron_ingot","type":"minecraft:item"},{"name":"minecraft:carrot","type":"minecraft:item"},{"name":"minecraft:potato","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombified_piglin":{"id":155,"max_health":20.0,"experience_reward":5,"attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":5.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"attackable":true,"mob":true,"limit_per_chunk":4,"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"dimension":[0.6,1.95],"eye_height":1.79,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombified_piglin","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:gold_nugget","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:gold_ingot","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"player":{"id":156,"summonable":false,"saveable":false,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.6,1.8],"eye_height":1.62,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/player"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"},"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":1.0},{"attack_knockback":0.0},{"attack_speed":4.0},{"below_name_distance":10.0},{"block_break_speed":1.0},{"block_interaction_range":4.5},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"luck":0.0},{"max_absorption":0.0},{"max_health":20.0},{"mining_efficiency":0.0},{"movement_efficiency":0.0},{"movement_speed":0.1},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"sneaking_speed":0.3},{"step_height":0.6},{"submerged_mining_speed":0.2},{"sweeping_damage_ratio":0.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0},{"waypoint_receive_range":0.0}],"max_health":20.0,"experience_reward":0},"fishing_bobber":{"id":157,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":false,"saveable":false,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}}} \ No newline at end of file +{"acacia_boat":{"id":0,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"acacia_chest_boat":{"id":1,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"allay":{"id":2,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.10000000149011612},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.10000000149011612},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":2,"track_deltas":true,"dimension":[0.35,0.6],"eye_height":0.36,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/allay"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"area_effect_cloud":{"id":3,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":true,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":2147483647,"track_deltas":true,"dimension":[6.0,0.5],"eye_height":0.425,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"armadillo":{"id":4,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":12.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":12.0},{"movement_efficiency":0.0},{"movement_speed":0.14},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.7,0.65],"eye_height":0.26,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/armadillo"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"armor_stand":{"id":5,"experience_reward":0,"attackable":true,"mob":false,"limit_per_chunk":0,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.5,1.975],"eye_height":1.7775,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/armor_stand"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"arrow":{"id":6,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":20,"track_deltas":true,"dimension":[0.5,0.5],"eye_height":0.13,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"axolotl":{"id":7,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":14.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":14.0},{"movement_efficiency":0.0},{"movement_speed":1.0},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"AXOLOTLS","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.75,0.42],"eye_height":0.2751,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/axolotl"},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bamboo_chest_raft":{"id":8,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bamboo_raft":{"id":9,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bat":{"id":10,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":6.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":6.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"AMBIENT","can_spawn_far_from_player":false,"client_tracking_range":5,"update_interval":3,"track_deltas":false,"dimension":[0.5,0.9],"eye_height":0.45,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/bat"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bee":{"id":11,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.6000000238418579},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.55,0.5],"eye_height":0.3,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/bee"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"birch_boat":{"id":12,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"birch_chest_boat":{"id":13,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"blaze":{"id":14,"experience_reward":10,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":48.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.8],"eye_height":1.53,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/blaze","pools":[{"entries":[{"name":"minecraft:blaze_rod","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"block_display":{"id":15,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":1,"track_deltas":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"bogged":{"id":16,"experience_reward":5,"hurt_sound":"entity.bogged.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":16.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":16.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.99],"eye_height":1.74,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/bogged","pools":[{"entries":[{"name":"minecraft:arrow","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:tipped_arrow","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"limit":1,"function":"minecraft:enchanted_count_increase"},{"id":"minecraft:poison","function":"minecraft:set_potion"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"breeze":{"id":17,"experience_reward":10,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":30.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":24.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.6299999952316284},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.77],"eye_height":1.3452,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/breeze","pools":[{"entries":[{"name":"minecraft:breeze_rod","functions":[{"count":{"min":1.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":1.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"breeze_wind_charge":{"id":18,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.3125,0.3125],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"camel":{"id":19,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":32.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":32.0},{"movement_efficiency":0.0},{"movement_speed":0.09000000357627869},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.5},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.7,2.375],"eye_height":2.275,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/camel"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"camel_husk":{"id":20,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":32.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":32.0},{"movement_efficiency":0.0},{"movement_speed":0.09000000357627869},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.5},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.7,2.375],"eye_height":2.275,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/camel_husk","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":2.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cat":{"id":21,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,0.7],"eye_height":0.35,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/cat","pools":[{"entries":[{"name":"minecraft:string","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cave_spider":{"id":22,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":12.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":12.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.7,0.5],"eye_height":0.45,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/cave_spider","pools":[{"entries":[{"name":"minecraft:string","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:spider_eye","functions":[{"count":{"min":-1.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cherry_boat":{"id":23,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cherry_chest_boat":{"id":24,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"chest_minecart":{"id":25,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"chicken":{"id":26,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":4.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":4.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.4,0.7],"eye_height":0.644,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/chicken","pools":[{"entries":[{"name":"minecraft:feather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:chicken","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cod":{"id":27,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":8,"max_health":3.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_AMBIENT","can_spawn_far_from_player":false,"client_tracking_range":4,"update_interval":3,"track_deltas":true,"dimension":[0.5,0.3],"eye_height":0.195,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/cod","pools":[{"entries":[{"name":"minecraft:cod","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone_meal","type":"minecraft:item"}],"conditions":[{"chance":0.05,"condition":"minecraft:random_chance"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"copper_golem":{"id":28,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":12.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":12.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.49,0.98],"eye_height":0.8125,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/copper_golem","pools":[{"entries":[{"name":"minecraft:copper_ingot","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"command_block_minecart":{"id":29,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"cow":{"id":30,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.9,1.4],"eye_height":1.3,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/cow","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:beef","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"creaking":{"id":31,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":1.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":32.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":1.0},{"movement_efficiency":0.0},{"movement_speed":0.4000000059604645},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0625},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.9,2.7],"eye_height":2.3,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/creaking"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"creeper":{"id":32,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.7],"eye_height":1.445,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/creeper","pools":[{"entries":[{"name":"minecraft:gunpowder","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:creeper_drop_music_discs","expand":true,"type":"minecraft:tag"}],"conditions":[{"predicate":{"minecraft:entity_type":"#minecraft:skeletons"},"entity":"attacker","condition":"minecraft:entity_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"dark_oak_boat":{"id":33,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"dark_oak_chest_boat":{"id":34,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"dolphin":{"id":35,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":1.2000000476837158},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_CREATURE","can_spawn_far_from_player":false,"client_tracking_range":5,"update_interval":3,"track_deltas":true,"dimension":[0.9,0.6],"eye_height":0.3,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/dolphin","pools":[{"entries":[{"name":"minecraft:cod","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"donkey":{"id":36,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":53.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.5},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.3964844,1.5],"eye_height":1.425,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/donkey","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"dragon_fireball":{"id":37,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[1.0,1.0],"eye_height":0.85,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"drowned":{"id":38,"experience_reward":5,"hurt_sound":"entity.drowned.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.74,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/drowned","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:copper_ingot","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.11,"enchanted_chance":{"base":0.13,"per_level_above_first":0.02,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"egg":{"id":39,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"elder_guardian":{"id":40,"experience_reward":10,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":80.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":8.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":80.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.9975,1.9975],"eye_height":0.99875,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/elder_guardian","pools":[{"entries":[{"name":"minecraft:prismarine_shard","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:cod","weight":3,"functions":[{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"},{"name":"minecraft:prismarine_crystals","weight":2,"functions":[{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"type":"minecraft:empty"}],"rolls":1.0},{"entries":[{"name":"minecraft:wet_sponge","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0},{"entries":[{"value":"minecraft:gameplay/fishing/fish","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:loot_table"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0},{"entries":[{"weight":4,"type":"minecraft:empty"},{"name":"minecraft:tide_armor_trim_smithing_template","type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"enderman":{"id":41,"experience_reward":5,"hurt_sound":"entity.enderman.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":40.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":7.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":64.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":40.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,2.9],"eye_height":2.55,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/enderman","pools":[{"entries":[{"name":"minecraft:ender_pearl","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"endermite":{"id":42,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":8.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":8.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.4,0.3],"eye_height":0.13,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/endermite"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ender_dragon":{"id":43,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":200.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":16.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":200.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[16.0,8.0],"eye_height":6.8,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/ender_dragon"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ender_pearl":{"id":44,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"end_crystal":{"id":45,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":true,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":16,"update_interval":2147483647,"track_deltas":false,"dimension":[2.0,2.0],"eye_height":1.7,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"evoker":{"id":46,"experience_reward":10,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":24.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":12.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":24.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.6575,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/evoker","pools":[{"entries":[{"name":"minecraft:totem_of_undying","type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:emerald","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"evoker_fangs":{"id":47,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":6,"update_interval":2,"track_deltas":false,"dimension":[0.5,0.8],"eye_height":0.68,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"experience_bottle":{"id":48,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"experience_orb":{"id":49,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":6,"update_interval":20,"track_deltas":true,"dimension":[0.5,0.5],"eye_height":0.425,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"eye_of_ender":{"id":50,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":4,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"falling_block":{"id":51,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":20,"track_deltas":true,"dimension":[0.98,0.98],"eye_height":0.83300006,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"fireball":{"id":52,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[1.0,1.0],"eye_height":0.85,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"firework_rocket":{"id":53,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"fox":{"id":54,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":32.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":5.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,0.7],"eye_height":0.4,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/fox"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"frog":{"id":55,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":10.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":1.0},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.5,0.5],"eye_height":0.425,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/frog"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"furnace_minecart":{"id":56,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ghast":{"id":57,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":1,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":8.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.06},{"follow_range":100.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[4.0,4.0],"eye_height":2.6,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/ghast","pools":[{"entries":[{"name":"minecraft:ghast_tear","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:gunpowder","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:music_disc_tears","type":"minecraft:item"}],"conditions":[{"predicate":{"tags":[{"id":"minecraft:is_projectile","expected":true}],"direct_entity":{"minecraft:entity_type":"minecraft:fireball"}},"condition":"minecraft:damage_source_properties"},{"condition":"minecraft:killed_by_player"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"happy_ghast":{"id":58,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":1,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":8.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.05},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.05},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":16.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[4.0,4.0],"eye_height":2.6,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/happy_ghast"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"giant":{"id":59,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":100.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":50.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":16.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":100.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[3.6,12.0],"eye_height":10.44,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/giant"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"glow_item_frame":{"id":60,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":2147483647,"track_deltas":false,"dimension":[0.5,0.5],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"glow_squid":{"id":61,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"UNDERGROUND_WATER_CREATURE","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.8,0.8],"eye_height":0.4,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/glow_squid","pools":[{"entries":[{"name":"minecraft:glow_ink_sac","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"goat":{"id":62,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.9,1.3],"eye_height":1.105,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/goat"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"guardian":{"id":63,"experience_reward":10,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":30.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.85,0.85],"eye_height":0.425,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/guardian","pools":[{"entries":[{"name":"minecraft:prismarine_shard","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:cod","weight":2,"functions":[{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"},{"name":"minecraft:prismarine_crystals","weight":2,"functions":[{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"type":"minecraft:empty"}],"rolls":1.0},{"entries":[{"value":"minecraft:gameplay/fishing/fish","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:loot_table"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"hoglin":{"id":64,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":40.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":1.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.6000000238418579},{"max_absorption":0.0},{"max_health":40.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[1.3964844,1.4],"eye_height":1.19,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/hoglin","pools":[{"entries":[{"name":"minecraft:porkchop","functions":[{"count":{"min":2.0,"max":4.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"hopper_minecart":{"id":65,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"horse":{"id":66,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":53.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.7},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.22499999403953552},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.3964844,1.6],"eye_height":1.52,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/horse","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"husk":{"id":67,"experience_reward":5,"hurt_sound":"entity.husk.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.74,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/husk","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:rabbit_foot","conditions":[{"predicate":{"minecraft:vehicle":{"minecraft:entity_type":"minecraft:camel_husk"}},"entity":"this","condition":"minecraft:entity_properties"}],"functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:iron_ingot","type":"minecraft:item"},{"name":"minecraft:carrot","type":"minecraft:item"},{"name":"minecraft:potato","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"illusioner":{"id":68,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":32.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":18.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":32.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.6575,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/illusioner"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"interaction":{"id":69,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"iron_golem":{"id":70,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":100.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":15.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":1.0},{"max_absorption":0.0},{"max_health":100.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.4,2.7],"eye_height":2.295,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/iron_golem","pools":[{"entries":[{"name":"minecraft:poppy","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:iron_ingot","functions":[{"count":{"min":3.0,"max":5.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"item":{"id":71,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":6,"update_interval":20,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"item_display":{"id":72,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":1,"track_deltas":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"item_frame":{"id":73,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":2147483647,"track_deltas":false,"dimension":[0.5,0.5],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"jungle_boat":{"id":74,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"jungle_chest_boat":{"id":75,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"leash_knot":{"id":76,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":false,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":2147483647,"track_deltas":false,"dimension":[0.375,0.5],"eye_height":0.0625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"lightning_bolt":{"id":77,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":false,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":16,"update_interval":2147483647,"track_deltas":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"llama":{"id":78,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":53.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.5},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.9,1.87],"eye_height":1.7765,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/llama","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"llama_spit":{"id":79,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":false,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"magma_cube":{"id":80,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.52,0.52],"eye_height":0.325,"spawn_dimensions_scale":4.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/magma_cube","pools":[{"entries":[{"name":"minecraft:magma_cream","conditions":[{"term":{"predicate":{"source_entity":{"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"},"condition":"minecraft:inverted"},{"predicate":{"minecraft:type_specific/cube_mob":{"size":{"min":2}}},"entity":"this","condition":"minecraft:entity_properties"}],"functions":[{"count":{"min":-2.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:pearlescent_froglight","conditions":[{"predicate":{"source_entity":{"minecraft:components":{"minecraft:frog/variant":"minecraft:warm"},"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"},{"name":"minecraft:verdant_froglight","conditions":[{"predicate":{"source_entity":{"minecraft:components":{"minecraft:frog/variant":"minecraft:cold"},"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"},{"name":"minecraft:ochre_froglight","conditions":[{"predicate":{"source_entity":{"minecraft:components":{"minecraft:frog/variant":"minecraft:temperate"},"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mangrove_boat":{"id":81,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mangrove_chest_boat":{"id":82,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mannequin":{"id":83,"experience_reward":0,"attackable":true,"mob":false,"limit_per_chunk":0,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":32,"update_interval":2,"track_deltas":true,"dimension":[0.6,1.8],"eye_height":1.62,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/mannequin"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"marker":{"id":84,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":0,"update_interval":3,"track_deltas":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"minecart":{"id":85,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mooshroom":{"id":86,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.9,1.4],"eye_height":1.3,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/mooshroom","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:beef","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"mule":{"id":87,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":53.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.5},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[1.3964844,1.6],"eye_height":1.52,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/mule","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"nautilus":{"id":88,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":15.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.30000001192092896},{"max_absorption":0.0},{"max_health":15.0},{"movement_efficiency":0.0},{"movement_speed":1.0},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_CREATURE","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.875,0.95],"eye_height":0.2751,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/nautilus","pools":[{"entries":[{"name":"minecraft:nautilus_shell","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.05,"enchanted_chance":{"base":0.060000002,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"oak_boat":{"id":89,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"oak_chest_boat":{"id":90,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ocelot":{"id":91,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.6,0.7],"eye_height":0.595,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/ocelot"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING"}},"ominous_item_spawner":{"id":92,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"painting":{"id":93,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":2147483647,"track_deltas":false,"dimension":[0.5,0.5],"eye_height":0.425,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pale_oak_boat":{"id":94,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pale_oak_chest_boat":{"id":95,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"panda":{"id":96,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.15000000596046448},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.3,1.25],"eye_height":1.0625,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/panda","pools":[{"entries":[{"name":"minecraft:bamboo","functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"parched":{"id":97,"experience_reward":5,"hurt_sound":"entity.parched.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":16.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":16.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.99],"eye_height":1.74,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/parched","pools":[{"entries":[{"name":"minecraft:arrow","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:tipped_arrow","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"limit":1,"function":"minecraft:enchanted_count_increase"},{"id":"minecraft:weakness","function":"minecraft:set_potion"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"parrot":{"id":98,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":6.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.4000000059604645},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":6.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.5,0.9],"eye_height":0.54,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/parrot","pools":[{"entries":[{"name":"minecraft:feather","functions":[{"count":{"min":1.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING"}},"phantom":{"id":99,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.9,0.5],"eye_height":0.175,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/phantom","pools":[{"entries":[{"name":"minecraft:phantom_membrane","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pig":{"id":100,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.9,0.9],"eye_height":0.765,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/pig","pools":[{"entries":[{"name":"minecraft:porkchop","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"piglin":{"id":101,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":16.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":5.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":16.0},{"movement_efficiency":0.0},{"movement_speed":0.3499999940395355},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.79,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/piglin"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"piglin_brute":{"id":102,"experience_reward":20,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":50.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":7.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":12.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":50.0},{"movement_efficiency":0.0},{"movement_speed":0.3499999940395355},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.79,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/piglin_brute"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pillager":{"id":103,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":1,"max_health":24.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":5.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":32.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":24.0},{"movement_efficiency":0.0},{"movement_speed":0.3499999940395355},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.6575,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/pillager","pools":[{"entries":[{"name":"minecraft:ominous_bottle","functions":[{"count":1.0,"function":"minecraft:set_count"},{"amplifier":{"min":0.0,"max":4.0,"type":"minecraft:uniform"},"function":"minecraft:set_ominous_bottle_amplifier"}],"type":"minecraft:item"}],"conditions":[{"predicate":{"minecraft:type_specific/raider":{"is_captain":true}},"entity":"this","condition":"minecraft:entity_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"polar_bear":{"id":104,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":30.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":20.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.4,1.4],"eye_height":1.19,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/polar_bear","pools":[{"entries":[{"name":"minecraft:cod","weight":3,"functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:salmon","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"splash_potion":{"id":105,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"lingering_potion":{"id":106,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"pufferfish":{"id":107,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":8,"max_health":3.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_AMBIENT","can_spawn_far_from_player":false,"client_tracking_range":4,"update_interval":3,"track_deltas":true,"dimension":[0.7,0.7],"eye_height":0.455,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/pufferfish","pools":[{"entries":[{"name":"minecraft:pufferfish","functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone_meal","type":"minecraft:item"}],"conditions":[{"chance":0.05,"condition":"minecraft:random_chance"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"rabbit":{"id":108,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":3.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.49,0.6],"eye_height":0.59,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/rabbit","pools":[{"entries":[{"name":"minecraft:rabbit_hide","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:rabbit","functions":[{"count":1.0,"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:rabbit_foot","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.1,"enchanted_chance":{"base":0.13,"per_level_above_first":0.03,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"ravager":{"id":109,"experience_reward":20,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":100.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":12.0},{"attack_knockback":1.5},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":32.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.75},{"max_absorption":0.0},{"max_health":100.0},{"movement_efficiency":0.0},{"movement_speed":0.3},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.95,2.2],"eye_height":1.8700001,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/ravager","pools":[{"entries":[{"name":"minecraft:saddle","functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"salmon":{"id":110,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":5,"max_health":3.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_AMBIENT","can_spawn_far_from_player":false,"client_tracking_range":4,"update_interval":3,"track_deltas":true,"dimension":[0.7,0.4],"eye_height":0.26,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/salmon","pools":[{"entries":[{"name":"minecraft:salmon","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone_meal","type":"minecraft:item"}],"conditions":[{"chance":0.05,"condition":"minecraft:random_chance"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"sheep":{"id":111,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":8.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":8.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.9,1.3],"eye_height":1.235,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/sheep","pools":[{"entries":[{"name":"minecraft:mutton","functions":[{"count":{"min":1.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"children":[{"value":"minecraft:entities/sheep/white","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"white"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/orange","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"orange"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/magenta","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"magenta"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/light_blue","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"light_blue"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/yellow","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"yellow"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/lime","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"lime"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/pink","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"pink"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/gray","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"gray"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/light_gray","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"light_gray"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/cyan","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"cyan"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/purple","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"purple"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/blue","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"blue"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/brown","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"brown"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/green","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"green"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/red","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"red"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"},{"value":"minecraft:entities/sheep/black","conditions":[{"predicate":{"minecraft:components":{"minecraft:sheep/color":"black"},"minecraft:type_specific/sheep":{"sheared":false}},"entity":"this","condition":"minecraft:entity_properties"}],"type":"minecraft:loot_table"}],"type":"minecraft:alternatives"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"shulker":{"id":112,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":30.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.0,1.0],"eye_height":0.5,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/shulker","pools":[{"entries":[{"name":"minecraft:shulker_shell","type":"minecraft:item"}],"conditions":[{"unenchanted_chance":0.5,"enchanted_chance":{"base":0.5625,"per_level_above_first":0.0625,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"shulker_bullet":{"id":113,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.3125,0.3125],"eye_height":0.265625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"silverfish":{"id":114,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":8.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":1.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":8.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.4,0.3],"eye_height":0.13,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/silverfish"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"skeleton":{"id":115,"experience_reward":5,"hurt_sound":"entity.skeleton.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.99],"eye_height":1.74,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/skeleton","pools":[{"entries":[{"name":"minecraft:arrow","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"skeleton_horse":{"id":116,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":15.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.7},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":15.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.3964844,1.6],"eye_height":1.52,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/skeleton_horse","pools":[{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"slime":{"id":117,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.52,0.52],"eye_height":0.325,"spawn_dimensions_scale":4.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/slime","pools":[{"entries":[{"name":"minecraft:slime_ball","conditions":[{"term":{"predicate":{"source_entity":{"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"},"condition":"minecraft:inverted"}],"functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:slime_ball","conditions":[{"predicate":{"source_entity":{"minecraft:entity_type":"minecraft:frog"}},"condition":"minecraft:damage_source_properties"}],"functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"conditions":[{"predicate":{"minecraft:type_specific/cube_mob":{"size":1}},"entity":"this","condition":"minecraft:entity_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"small_fireball":{"id":118,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.3125,0.3125],"eye_height":0.265625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"sniffer":{"id":119,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":14.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":14.0},{"movement_efficiency":0.0},{"movement_speed":0.10000000149011612},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.9,1.75],"eye_height":1.05,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/sniffer"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"snowball":{"id":120,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"snow_golem":{"id":121,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":4.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":4.0},{"movement_efficiency":0.0},{"movement_speed":0.20000000298023224},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.7,1.9],"eye_height":1.7,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/snow_golem","pools":[{"entries":[{"name":"minecraft:snowball","functions":[{"count":{"min":0.0,"max":15.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spawner_minecart":{"id":122,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spectral_arrow":{"id":123,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":20,"track_deltas":true,"dimension":[0.5,0.5],"eye_height":0.13,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spider":{"id":124,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":16.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":16.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[1.4,0.9],"eye_height":0.65,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/spider","pools":[{"entries":[{"name":"minecraft:string","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:spider_eye","functions":[{"count":{"min":-1.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spruce_boat":{"id":125,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"spruce_chest_boat":{"id":126,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.375,0.5625],"eye_height":0.5625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"squid":{"id":127,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":10.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":10.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_CREATURE","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.8,0.8],"eye_height":0.4,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/squid","pools":[{"entries":[{"name":"minecraft:ink_sac","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"stray":{"id":128,"experience_reward":5,"hurt_sound":"entity.stray.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.99],"eye_height":1.74,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/stray","pools":[{"entries":[{"name":"minecraft:arrow","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:tipped_arrow","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"limit":1,"function":"minecraft:enchanted_count_increase"},{"id":"minecraft:slowness","function":"minecraft:set_potion"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"strider":{"id":129,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.9,1.7],"eye_height":1.445,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/strider","pools":[{"entries":[{"name":"minecraft:string","functions":[{"count":{"min":2.0,"max":5.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_LAVA","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"sulfur_cube":{"id":130,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":8.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.49,0.49],"eye_height":0.175,"spawn_dimensions_scale":2.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/sulfur_cube"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"tadpole":{"id":131,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":8,"max_health":6.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":6.0},{"movement_efficiency":0.0},{"movement_speed":1.0},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.4,0.3],"eye_height":0.19500001,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/tadpole"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"text_display":{"id":132,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":1,"track_deltas":true,"dimension":[0.0,0.0],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"tnt":{"id":133,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":true,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":10,"track_deltas":true,"dimension":[0.98,0.98],"eye_height":0.15,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"tnt_minecart":{"id":134,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.98,0.7],"eye_height":0.595,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"trader_llama":{"id":135,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":53.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.5},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":53.0},{"movement_efficiency":0.0},{"movement_speed":0.17499999701976776},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.9,1.87],"eye_height":1.7765,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/trader_llama","pools":[{"entries":[{"name":"minecraft:leather","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"trident":{"id":136,"attackable":false,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":20,"track_deltas":true,"dimension":[0.5,0.5],"eye_height":0.13,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"tropical_fish":{"id":137,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":8,"max_health":3.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":3.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"WATER_AMBIENT","can_spawn_far_from_player":false,"client_tracking_range":4,"update_interval":3,"track_deltas":true,"dimension":[0.5,0.4],"eye_height":0.26,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/tropical_fish","pools":[{"entries":[{"name":"minecraft:tropical_fish","functions":[{"count":1.0,"function":"minecraft:set_count"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone_meal","type":"minecraft:item"}],"conditions":[{"chance":0.05,"condition":"minecraft:random_chance"}],"rolls":1.0}]},"spawn_restriction":{"location":"IN_WATER","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"turtle":{"id":138,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":30.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":30.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.2,0.4],"eye_height":0.34,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/turtle","pools":[{"entries":[{"name":"minecraft:seagrass","weight":3,"functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bowl","type":"minecraft:item"}],"conditions":[{"predicate":{"tags":[{"id":"minecraft:is_lightning","expected":true}]},"condition":"minecraft:damage_source_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"vex":{"id":139,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":14.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":4.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":14.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.4,0.8],"eye_height":0.51875,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/vex"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"villager":{"id":140,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.5},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.62,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/villager"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"vindicator":{"id":141,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":24.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":5.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":12.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":24.0},{"movement_efficiency":0.0},{"movement_speed":0.3499999940395355},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.6575,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/vindicator","pools":[{"entries":[{"name":"minecraft:emerald","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wandering_trader":{"id":142,"experience_reward":0,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.7},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.62,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/wandering_trader"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"warden":{"id":143,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":500.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":30.0},{"attack_knockback":1.5},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":24.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":1.0},{"max_absorption":0.0},{"max_health":500.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":16,"update_interval":3,"track_deltas":true,"dimension":[0.9,2.9],"eye_height":2.4650002,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/warden","pools":[{"entries":[{"name":"minecraft:sculk_catalyst","type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wind_charge":{"id":144,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.3125,0.3125],"eye_height":0.0,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"witch":{"id":145,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":26.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":26.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.62,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/witch","pools":[{"entries":[{"name":"minecraft:glowstone_dust","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:sugar","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:spider_eye","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:glass_bottle","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:gunpowder","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"},{"name":"minecraft:stick","weight":2,"functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":{"min":1.0,"max":3.0,"type":"minecraft:uniform"}},{"entries":[{"name":"minecraft:redstone","functions":[{"count":{"min":4.0,"max":8.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wither":{"id":146,"experience_reward":50,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":300.0,"attributes":[{"air_drag_modifier":1.0},{"armor":4.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"flying_speed":0.6000000238418579},{"follow_range":40.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":300.0},{"movement_efficiency":0.0},{"movement_speed":0.6000000238418579},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":false,"dimension":[0.9,3.5],"eye_height":2.9750001,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/wither"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wither_skeleton":{"id":147,"experience_reward":5,"hurt_sound":"entity.wither_skeleton.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":2.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.25},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.7,2.4],"eye_height":2.1,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/wither_skeleton","pools":[{"entries":[{"name":"minecraft:coal","functions":[{"count":{"min":-1.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:bone","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:wither_skeleton_skull","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wither_skull":{"id":148,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":true,"saveable":true,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":10,"track_deltas":true,"dimension":[0.3125,0.3125],"eye_height":0.265625,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"wolf":{"id":149,"experience_reward":1,"attackable":true,"mob":true,"limit_per_chunk":8,"max_health":8.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":4.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":8.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"CREATURE","can_spawn_far_from_player":true,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.6,0.85],"eye_height":0.68,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/wolf"},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zoglin":{"id":150,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":40.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":6.0},{"attack_knockback":1.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.6000000238418579},{"max_absorption":0.0},{"max_health":40.0},{"movement_efficiency":0.0},{"movement_speed":0.30000001192092896},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[1.3964844,1.4],"eye_height":1.19,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zoglin","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":1.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombie":{"id":151,"experience_reward":5,"hurt_sound":"entity.zombie.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.74,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombie","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:red_mushroom","conditions":[{"predicate":{"minecraft:vehicle":{"minecraft:entity_type":"minecraft:zombie_horse"}},"entity":"this","condition":"minecraft:entity_properties"}],"functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:iron_ingot","type":"minecraft:item"},{"name":"minecraft:carrot","type":"minecraft:item"},{"name":"minecraft:potato","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0},{"entries":[{"name":"minecraft:music_disc_lava_chicken","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"predicate":{"minecraft:flags":{"is_baby":true},"minecraft:vehicle":{"minecraft:entity_type":"minecraft:chicken"}},"entity":"this","condition":"minecraft:entity_properties"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombie_horse":{"id":152,"experience_reward":2,"attackable":true,"mob":true,"limit_per_chunk":6,"max_health":25.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":0.5},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.7},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":25.0},{"movement_efficiency":0.0},{"movement_speed":0.22499999403953552},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":6.0},{"scale":1.0},{"step_height":1.0},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[1.3964844,1.6],"eye_height":1.52,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombie_horse","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":2.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombie_nautilus":{"id":153,"experience_reward":3,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":15.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":16.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.30000001192092896},{"max_absorption":0.0},{"max_health":15.0},{"movement_efficiency":0.0},{"movement_speed":1.100000023841858},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"step_height":0.6},{"tempt_range":10.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":10,"update_interval":3,"track_deltas":true,"dimension":[0.875,0.95],"eye_height":0.2751,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombie_nautilus","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":3.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"}],"rolls":1.0}]},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombie_villager":{"id":154,"experience_reward":5,"hurt_sound":"entity.zombie_villager.hurt","attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":3.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":false,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.74,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombie_villager","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":2.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:iron_ingot","type":"minecraft:item"},{"name":"minecraft:carrot","type":"minecraft:item"},{"name":"minecraft:potato","functions":[{"conditions":[{"terms":[{"predicate":{"minecraft:flags":{"is_on_fire":true}},"entity":"this","condition":"minecraft:entity_properties"},{"predicate":{"minecraft:equipment":{"mainhand":{"predicates":{"minecraft:enchantments":[{"enchantments":"#minecraft:smelts_loot"}]}}}},"entity":"direct_attacker","condition":"minecraft:entity_properties"}],"condition":"minecraft:any_of"}],"function":"minecraft:furnace_smelt"}],"type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"zombified_piglin":{"id":155,"experience_reward":5,"attackable":true,"mob":true,"limit_per_chunk":4,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":2.0},{"armor_toughness":0.0},{"attack_damage":5.0},{"attack_knockback":0.0},{"below_name_distance":10.0},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"follow_range":35.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"max_absorption":0.0},{"max_health":20.0},{"movement_efficiency":0.0},{"movement_speed":0.23000000417232513},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"spawn_reinforcements":0.0},{"step_height":0.6},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":0.0}],"summonable":true,"saveable":true,"fire_immune":true,"category":"MONSTER","can_spawn_far_from_player":false,"client_tracking_range":8,"update_interval":3,"track_deltas":true,"dimension":[0.6,1.95],"eye_height":1.79,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/zombified_piglin","pools":[{"entries":[{"name":"minecraft:rotten_flesh","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:gold_nugget","functions":[{"count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:set_count"},{"enchantment":"minecraft:looting","count":{"min":0.0,"max":1.0,"type":"minecraft:uniform"},"function":"minecraft:enchanted_count_increase"}],"type":"minecraft:item"}],"rolls":1.0},{"entries":[{"name":"minecraft:gold_ingot","type":"minecraft:item"}],"conditions":[{"condition":"minecraft:killed_by_player"},{"unenchanted_chance":0.025,"enchanted_chance":{"base":0.035,"per_level_above_first":0.01,"type":"minecraft:linear"},"enchantment":"minecraft:looting","condition":"minecraft:random_chance_with_enchanted_bonus"}],"rolls":1.0}]},"spawn_restriction":{"location":"ON_GROUND","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"player":{"id":156,"max_health":20.0,"attributes":[{"air_drag_modifier":1.0},{"armor":0.0},{"armor_toughness":0.0},{"attack_damage":1.0},{"attack_knockback":0.0},{"attack_speed":4.0},{"below_name_distance":10.0},{"block_break_speed":1.0},{"block_interaction_range":4.5},{"bounciness":0.0},{"burning_time":1.0},{"camera_distance":4.0},{"explosion_knockback_resistance":0.0},{"entity_interaction_range":3.0},{"fall_damage_multiplier":1.0},{"friction_modifier":1.0},{"gravity":0.08},{"jump_strength":0.41999998688697815},{"knockback_resistance":0.0},{"luck":0.0},{"max_absorption":0.0},{"max_health":20.0},{"mining_efficiency":0.0},{"movement_efficiency":0.0},{"movement_speed":0.10000000149011612},{"name_tag_distance":64.0},{"oxygen_bonus":0.0},{"safe_fall_distance":3.0},{"scale":1.0},{"sneaking_speed":0.3},{"step_height":0.6},{"submerged_mining_speed":0.2},{"sweeping_damage_ratio":0.0},{"water_movement_efficiency":0.0},{"waypoint_transmit_range":6.0E7},{"waypoint_receive_range":6.0E7}],"summonable":false,"saveable":false,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":32,"update_interval":2,"track_deltas":false,"dimension":[0.6,1.8],"eye_height":1.62,"spawn_dimensions_scale":1.0,"loot_table":{"type":"minecraft:entity","random_sequence":"minecraft:entities/player"},"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}},"fishing_bobber":{"id":157,"attackable":true,"mob":false,"limit_per_chunk":0,"summonable":false,"saveable":false,"fire_immune":false,"category":"MISC","can_spawn_far_from_player":true,"client_tracking_range":4,"update_interval":5,"track_deltas":true,"dimension":[0.25,0.25],"eye_height":0.2125,"spawn_dimensions_scale":1.0,"spawn_restriction":{"location":"UNRESTRICTED","heightmap":"MOTION_BLOCKING_NO_LEAVES"}}} \ No newline at end of file diff --git a/crates/pumpkin-data/src/generated/entity_type.rs b/crates/pumpkin-data/src/generated/entity_type.rs index 6cef1c7a8..9a87063d6 100644 --- a/crates/pumpkin-data/src/generated/entity_type.rs +++ b/crates/pumpkin-data/src/generated/entity_type.rs @@ -6,6 +6,8 @@ use crate::tag::RegistryKey; use crate::tag::Taggable; use pumpkin_util::HeightMap; use pumpkin_util::loot_table::*; +use pumpkin_util::math::boundingbox::BoundingBox; +use pumpkin_util::math::vector3::Vector3; use std::hash::Hash; #[derive(Debug, Clone)] pub struct EntityType { @@ -21,9 +23,13 @@ pub struct EntityType { pub fire_immune: bool, pub category: &'static MobCategory, pub can_spawn_far_from_player: bool, + pub client_tracking_range: u32, + pub update_interval: u32, + pub track_deltas: bool, pub loot_table: Option, pub dimension: [f32; 2], pub eye_height: f32, + pub spawn_dimensions_scale: f32, pub spawn_restriction: SpawnRestriction, pub resource_name: &'static str, } @@ -160,9 +166,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -182,9 +192,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -234,6 +248,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 2u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/allay"), @@ -241,6 +258,7 @@ impl EntityType { }), dimension: [0.35f32, 0.6f32], eye_height: 0.36f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -260,9 +278,13 @@ impl EntityType { fire_immune: true, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 2147483647u32, + track_deltas: true, loot_table: None, dimension: [6f32, 0.5f32], eye_height: 0.425f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -311,6 +333,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/armadillo"), @@ -318,6 +343,7 @@ impl EntityType { }), dimension: [0.7f32, 0.65f32], eye_height: 0.26f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -364,6 +390,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/armor_stand"), @@ -371,6 +400,7 @@ impl EntityType { }), dimension: [0.5f32, 1.975f32], eye_height: 1.7775f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -390,9 +420,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 20u32, + track_deltas: true, loot_table: None, dimension: [0.5f32, 0.5f32], eye_height: 0.13f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -432,7 +466,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 3u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -442,6 +476,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::AXOLOTLS, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/axolotl"), @@ -449,6 +486,7 @@ impl EntityType { }), dimension: [0.75f32, 0.42f32], eye_height: 0.2751f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -468,9 +506,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -490,9 +532,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -540,6 +586,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::AMBIENT, can_spawn_far_from_player: false, + client_tracking_range: 5u32, + update_interval: 3u32, + track_deltas: false, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/bat"), @@ -547,6 +596,7 @@ impl EntityType { }), dimension: [0.5f32, 0.9f32], eye_height: 0.45f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -597,6 +647,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/bee"), @@ -604,6 +657,7 @@ impl EntityType { }), dimension: [0.55f32, 0.5f32], eye_height: 0.3f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -623,9 +677,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -645,9 +703,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -696,6 +758,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/blaze"), @@ -739,6 +804,7 @@ impl EntityType { }), dimension: [0.6f32, 1.8f32], eye_height: 1.53f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -758,9 +824,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 1u32, + track_deltas: true, loot_table: None, dimension: [0f32, 0f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -809,6 +879,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/bogged"), @@ -934,6 +1007,7 @@ impl EntityType { }), dimension: [0.6f32, 1.99f32], eye_height: 1.74f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -982,6 +1056,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/breeze"), @@ -1025,6 +1102,7 @@ impl EntityType { }), dimension: [0.6f32, 1.77f32], eye_height: 1.3452f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1044,9 +1122,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.3125f32, 0.3125f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1095,6 +1177,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/camel"), @@ -1102,6 +1187,7 @@ impl EntityType { }), dimension: [1.7f32, 2.375f32], eye_height: 2.275f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1150,6 +1236,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/camel_husk"), @@ -1193,6 +1282,7 @@ impl EntityType { }), dimension: [1.7f32, 2.375f32], eye_height: 2.275f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1242,6 +1332,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/cat"), @@ -1272,6 +1365,7 @@ impl EntityType { }), dimension: [0.6f32, 0.7f32], eye_height: 0.35f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1320,6 +1414,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/cave_spider"), @@ -1402,6 +1499,7 @@ impl EntityType { }), dimension: [0.7f32, 0.5f32], eye_height: 0.45f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1421,9 +1519,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1443,9 +1545,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1465,9 +1571,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.7f32], eye_height: 0.595f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1516,6 +1626,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/chicken"), @@ -1605,6 +1718,7 @@ impl EntityType { }), dimension: [0.4f32, 0.7f32], eye_height: 0.644f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1642,7 +1756,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 3u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -1652,6 +1766,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::WATER_AMBIENT, can_spawn_far_from_player: false, + client_tracking_range: 4u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/cod"), @@ -1706,6 +1823,7 @@ impl EntityType { }), dimension: [0.5f32, 0.3f32], eye_height: 0.195f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1725,9 +1843,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.7f32], eye_height: 0.595f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1775,6 +1897,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/copper_golem"), @@ -1818,6 +1943,7 @@ impl EntityType { }), dimension: [0.49f32, 0.98f32], eye_height: 0.8125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -1866,6 +1992,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/cow"), @@ -1965,6 +2094,7 @@ impl EntityType { }), dimension: [0.9f32, 1.4f32], eye_height: 1.3f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2013,6 +2143,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/creaking"), @@ -2020,6 +2153,7 @@ impl EntityType { }), dimension: [0.9f32, 2.7f32], eye_height: 2.3f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2068,6 +2202,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/creeper"), @@ -2134,6 +2271,7 @@ impl EntityType { }), dimension: [0.6f32, 1.7f32], eye_height: 1.445f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2153,9 +2291,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2175,9 +2317,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2226,6 +2372,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::WATER_CREATURE, can_spawn_far_from_player: false, + client_tracking_range: 5u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/dolphin"), @@ -2286,6 +2435,7 @@ impl EntityType { }), dimension: [0.9f32, 0.6f32], eye_height: 0.3f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2334,6 +2484,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/donkey"), @@ -2377,6 +2530,7 @@ impl EntityType { }), dimension: [1.3964844f32, 1.5f32], eye_height: 1.425f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2396,9 +2550,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [1f32, 1f32], eye_height: 0.85f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2448,6 +2606,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/drowned"), @@ -2514,6 +2675,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.74f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2533,9 +2695,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2584,6 +2750,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/elder_guardian"), @@ -2779,6 +2948,7 @@ impl EntityType { }), dimension: [1.9975f32, 1.9975f32], eye_height: 0.99875f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2798,9 +2968,13 @@ impl EntityType { fire_immune: true, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 16u32, + update_interval: 2147483647u32, + track_deltas: false, loot_table: None, dimension: [2f32, 2f32], eye_height: 1.7f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2848,6 +3022,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/ender_dragon"), @@ -2855,6 +3032,7 @@ impl EntityType { }), dimension: [16f32, 8f32], eye_height: 6.8f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2874,9 +3052,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -2925,6 +3107,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/enderman"), @@ -2968,6 +3153,7 @@ impl EntityType { }), dimension: [0.6f32, 2.9f32], eye_height: 2.55f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3016,6 +3202,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/endermite"), @@ -3023,6 +3212,7 @@ impl EntityType { }), dimension: [0.4f32, 0.3f32], eye_height: 0.13f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3071,6 +3261,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/evoker"), @@ -3131,6 +3324,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.6575f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3150,9 +3344,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 6u32, + update_interval: 2u32, + track_deltas: false, loot_table: None, dimension: [0.5f32, 0.8f32], eye_height: 0.68f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3172,9 +3370,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3194,9 +3396,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 6u32, + update_interval: 20u32, + track_deltas: true, loot_table: None, dimension: [0.5f32, 0.5f32], eye_height: 0.425f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3216,9 +3422,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 4u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3238,9 +3448,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 20u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.98f32], eye_height: 0.83300006f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3260,9 +3474,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [1f32, 1f32], eye_height: 0.85f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3282,9 +3500,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3304,9 +3526,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 5u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3346,7 +3572,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 3u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -3356,6 +3582,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/fox"), @@ -3363,6 +3592,7 @@ impl EntityType { }), dimension: [0.6f32, 0.7f32], eye_height: 0.4f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3402,7 +3632,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 3u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -3412,6 +3642,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/frog"), @@ -3419,6 +3652,7 @@ impl EntityType { }), dimension: [0.5f32, 0.5f32], eye_height: 0.425f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3438,9 +3672,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.7f32], eye_height: 0.595f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3489,6 +3727,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/ghast"), @@ -3598,6 +3839,7 @@ impl EntityType { }), dimension: [4f32, 4f32], eye_height: 2.6f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3646,6 +3888,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/giant"), @@ -3653,6 +3898,7 @@ impl EntityType { }), dimension: [3.6f32, 12f32], eye_height: 10.44f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3672,9 +3918,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 2147483647u32, + track_deltas: false, loot_table: None, dimension: [0.5f32, 0.5f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3712,7 +3962,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 3u32, + experience_reward: 2u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -3722,6 +3972,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::UNDERGROUND_WATER_CREATURE, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/glow_squid"), @@ -3765,6 +4018,7 @@ impl EntityType { }), dimension: [0.8f32, 0.8f32], eye_height: 0.4f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3804,7 +4058,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 3u32, + experience_reward: 2u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -3814,6 +4068,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/goat"), @@ -3821,6 +4078,7 @@ impl EntityType { }), dimension: [0.9f32, 1.3f32], eye_height: 1.105f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -3869,6 +4127,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/guardian"), @@ -4025,6 +4286,7 @@ impl EntityType { }), dimension: [0.85f32, 0.85f32], eye_height: 0.425f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4064,7 +4326,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 3u32, + experience_reward: 2u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -4074,6 +4336,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/happy_ghast"), @@ -4081,6 +4346,7 @@ impl EntityType { }), dimension: [4f32, 4f32], eye_height: 2.6f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4129,6 +4395,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/hoglin"), @@ -4228,6 +4497,7 @@ impl EntityType { }), dimension: [1.3964844f32, 1.4f32], eye_height: 1.19f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4247,9 +4517,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.7f32], eye_height: 0.595f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4288,7 +4562,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 1u32, + experience_reward: 3u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -4298,6 +4572,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/horse"), @@ -4341,6 +4618,7 @@ impl EntityType { }), dimension: [1.3964844f32, 1.6f32], eye_height: 1.52f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4390,6 +4668,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/husk"), @@ -4534,6 +4815,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.74f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4582,6 +4864,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/illusioner"), @@ -4589,6 +4874,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.6575f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4608,9 +4894,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0f32, 0f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4659,6 +4949,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/iron_golem"), @@ -4715,6 +5008,7 @@ impl EntityType { }), dimension: [1.4f32, 2.7f32], eye_height: 2.295f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4734,9 +5028,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 6u32, + update_interval: 20u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4756,9 +5054,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 1u32, + track_deltas: true, loot_table: None, dimension: [0f32, 0f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4778,9 +5080,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 2147483647u32, + track_deltas: false, loot_table: None, dimension: [0.5f32, 0.5f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4800,9 +5106,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4822,9 +5132,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4844,9 +5158,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 2147483647u32, + track_deltas: false, loot_table: None, dimension: [0.375f32, 0.5f32], eye_height: 0.0625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4866,9 +5184,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 16u32, + update_interval: 2147483647u32, + track_deltas: true, loot_table: None, dimension: [0f32, 0f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4888,9 +5210,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -4929,7 +5255,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -4939,6 +5265,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/llama"), @@ -4982,6 +5311,7 @@ impl EntityType { }), dimension: [0.9f32, 1.87f32], eye_height: 1.7765f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5001,9 +5331,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: false, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5052,6 +5386,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/magma_cube"), @@ -5162,6 +5499,7 @@ impl EntityType { }), dimension: [0.52f32, 0.52f32], eye_height: 0.325f32, + spawn_dimensions_scale: 4f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5181,9 +5519,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5203,9 +5545,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5252,6 +5598,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 32u32, + update_interval: 2u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/mannequin"), @@ -5259,6 +5608,7 @@ impl EntityType { }), dimension: [0.6f32, 1.8f32], eye_height: 1.62f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5278,9 +5628,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 0u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0f32, 0f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5300,9 +5654,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.7f32], eye_height: 0.595f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5341,7 +5699,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -5351,6 +5709,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/mooshroom"), @@ -5450,6 +5811,7 @@ impl EntityType { }), dimension: [0.9f32, 1.4f32], eye_height: 1.3f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5488,7 +5850,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -5498,6 +5860,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/mule"), @@ -5541,6 +5906,7 @@ impl EntityType { }), dimension: [1.3964844f32, 1.6f32], eye_height: 1.52f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5580,7 +5946,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 1u32, + experience_reward: 2u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -5590,6 +5956,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::WATER_CREATURE, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/nautilus"), @@ -5617,6 +5986,7 @@ impl EntityType { }), dimension: [0.875f32, 0.95f32], eye_height: 0.2751f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5636,9 +6006,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5658,9 +6032,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5700,7 +6078,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -5710,6 +6088,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/ocelot"), @@ -5717,6 +6098,7 @@ impl EntityType { }), dimension: [0.6f32, 0.7f32], eye_height: 0.595f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlocking, @@ -5736,9 +6118,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5758,9 +6144,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 2147483647u32, + track_deltas: false, loot_table: None, dimension: [0.5f32, 0.5f32], eye_height: 0.425f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5780,9 +6170,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5802,9 +6196,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5854,6 +6252,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/panda"), @@ -5881,6 +6282,7 @@ impl EntityType { }), dimension: [1.3f32, 1.25f32], eye_height: 1.0625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -5929,6 +6331,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/parched"), @@ -6054,6 +6459,7 @@ impl EntityType { }), dimension: [0.6f32, 1.99f32], eye_height: 1.74f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6104,6 +6510,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/parrot"), @@ -6147,6 +6556,7 @@ impl EntityType { }), dimension: [0.5f32, 0.9f32], eye_height: 0.54f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlocking, @@ -6195,6 +6605,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/phantom"), @@ -6238,6 +6651,7 @@ impl EntityType { }), dimension: [0.9f32, 0.5f32], eye_height: 0.175f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6276,7 +6690,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -6286,6 +6700,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/pig"), @@ -6346,6 +6763,7 @@ impl EntityType { }), dimension: [0.9f32, 0.9f32], eye_height: 0.765f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6394,6 +6812,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/piglin"), @@ -6401,6 +6822,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.79f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6449,6 +6871,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/piglin_brute"), @@ -6456,6 +6881,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.79f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6504,6 +6930,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/pillager"), @@ -6542,6 +6971,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.6575f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6575,7 +7005,7 @@ impl EntityType { (Attributes::MAX_HEALTH, 20f64), (Attributes::MINING_EFFICIENCY, 0f64), (Attributes::MOVEMENT_EFFICIENCY, 0f64), - (Attributes::MOVEMENT_SPEED, 0.1f64), + (Attributes::MOVEMENT_SPEED, 0.10000000149011612f64), (Attributes::NAME_TAG_DISTANCE, 64f64), (Attributes::OXYGEN_BONUS, 0f64), (Attributes::SAFE_FALL_DISTANCE, 3f64), @@ -6585,8 +7015,8 @@ impl EntityType { (Attributes::SUBMERGED_MINING_SPEED, 0.2f64), (Attributes::SWEEPING_DAMAGE_RATIO, 0f64), (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), - (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), - (Attributes::WAYPOINT_RECEIVE_RANGE, 0f64), + (Attributes::WAYPOINT_TRANSMIT_RANGE, 60000000f64), + (Attributes::WAYPOINT_RECEIVE_RANGE, 60000000f64), ], experience_reward: 0u32, hurt_sound: None, @@ -6598,6 +7028,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 32u32, + update_interval: 2u32, + track_deltas: false, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/player"), @@ -6605,6 +7038,7 @@ impl EntityType { }), dimension: [0.6f32, 1.8f32], eye_height: 1.62f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6644,7 +7078,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 1u32, + experience_reward: 3u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -6654,6 +7088,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/polar_bear"), @@ -6764,6 +7201,7 @@ impl EntityType { }), dimension: [1.4f32, 1.4f32], eye_height: 1.19f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6811,6 +7249,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::WATER_AMBIENT, can_spawn_far_from_player: false, + client_tracking_range: 4u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/pufferfish"), @@ -6855,6 +7296,7 @@ impl EntityType { }), dimension: [0.7f32, 0.7f32], eye_height: 0.455f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -6904,6 +7346,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/rabbit"), @@ -7021,6 +7466,7 @@ impl EntityType { }), dimension: [0.49f32, 0.6f32], eye_height: 0.59f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7069,6 +7515,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/ravager"), @@ -7096,6 +7545,7 @@ impl EntityType { }), dimension: [1.95f32, 2.2f32], eye_height: 1.8700001f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7133,7 +7583,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -7143,6 +7593,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::WATER_AMBIENT, can_spawn_far_from_player: false, + client_tracking_range: 4u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/salmon"), @@ -7197,6 +7650,7 @@ impl EntityType { }), dimension: [0.7f32, 0.4f32], eye_height: 0.26f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7245,6 +7699,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/sheep"), @@ -7547,6 +8004,7 @@ impl EntityType { }), dimension: [0.9f32, 1.3f32], eye_height: 1.235f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7594,6 +8052,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/shulker"), @@ -7618,6 +8079,7 @@ impl EntityType { }), dimension: [1f32, 1f32], eye_height: 0.5f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7637,9 +8099,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.3125f32, 0.3125f32], eye_height: 0.265625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7688,6 +8154,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/silverfish"), @@ -7695,6 +8164,7 @@ impl EntityType { }), dimension: [0.4f32, 0.3f32], eye_height: 0.13f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7743,6 +8213,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/skeleton"), @@ -7825,6 +8298,7 @@ impl EntityType { }), dimension: [0.6f32, 1.99f32], eye_height: 1.74f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7873,6 +8347,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/skeleton_horse"), @@ -7916,6 +8393,7 @@ impl EntityType { }), dimension: [1.3964844f32, 1.6f32], eye_height: 1.52f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -7964,6 +8442,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/slime"), @@ -8037,6 +8518,7 @@ impl EntityType { }), dimension: [0.52f32, 0.52f32], eye_height: 0.325f32, + spawn_dimensions_scale: 4f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8056,9 +8538,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.3125f32, 0.3125f32], eye_height: 0.265625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8097,7 +8583,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 1u32, + experience_reward: 3u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -8107,6 +8593,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/sniffer"), @@ -8114,6 +8603,7 @@ impl EntityType { }), dimension: [1.9f32, 1.75f32], eye_height: 1.05f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8161,6 +8651,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/snow_golem"), @@ -8191,6 +8684,7 @@ impl EntityType { }), dimension: [0.7f32, 1.9f32], eye_height: 1.7f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8210,9 +8704,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8232,9 +8730,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.7f32], eye_height: 0.595f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8254,9 +8756,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 20u32, + track_deltas: true, loot_table: None, dimension: [0.5f32, 0.5f32], eye_height: 0.13f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8305,6 +8811,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/spider"), @@ -8387,6 +8896,7 @@ impl EntityType { }), dimension: [1.4f32, 0.9f32], eye_height: 0.65f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8406,9 +8916,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.25f32, 0.25f32], eye_height: 0.2125f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8428,9 +8942,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8450,9 +8968,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [1.375f32, 0.5625f32], eye_height: 0.5625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8490,7 +9012,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 1u32, + experience_reward: 2u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -8500,6 +9022,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::WATER_CREATURE, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/squid"), @@ -8543,6 +9068,7 @@ impl EntityType { }), dimension: [0.8f32, 0.8f32], eye_height: 0.4f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8591,6 +9117,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/stray"), @@ -8716,6 +9245,7 @@ impl EntityType { }), dimension: [0.6f32, 1.99f32], eye_height: 1.74f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8754,7 +9284,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 3u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -8764,6 +9294,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/strider"), @@ -8807,6 +9340,7 @@ impl EntityType { }), dimension: [0.9f32, 1.7f32], eye_height: 1.445f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InLava, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8845,7 +9379,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -8855,6 +9389,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/sulfur_cube"), @@ -8862,6 +9399,7 @@ impl EntityType { }), dimension: [0.49f32, 0.49f32], eye_height: 0.175f32, + spawn_dimensions_scale: 2f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8910,6 +9448,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/tadpole"), @@ -8917,6 +9458,7 @@ impl EntityType { }), dimension: [0.4f32, 0.3f32], eye_height: 0.19500001f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8936,9 +9478,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 1u32, + track_deltas: true, loot_table: None, dimension: [0f32, 0f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8958,9 +9504,13 @@ impl EntityType { fire_immune: true, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.98f32], eye_height: 0.15f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -8980,9 +9530,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: None, dimension: [0.98f32, 0.7f32], eye_height: 0.595f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9031,6 +9585,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/trader_llama"), @@ -9074,6 +9631,7 @@ impl EntityType { }), dimension: [0.9f32, 1.87f32], eye_height: 1.7765f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9093,9 +9651,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 20u32, + track_deltas: true, loot_table: None, dimension: [0.5f32, 0.5f32], eye_height: 0.13f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9143,6 +9705,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::WATER_AMBIENT, can_spawn_far_from_player: false, + client_tracking_range: 4u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/tropical_fish"), @@ -9187,6 +9752,7 @@ impl EntityType { }), dimension: [0.5f32, 0.4f32], eye_height: 0.26f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::InWater, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9235,6 +9801,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/turtle"), @@ -9298,6 +9867,7 @@ impl EntityType { }), dimension: [1.2f32, 0.4f32], eye_height: 0.34f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9346,6 +9916,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/vex"), @@ -9353,6 +9926,7 @@ impl EntityType { }), dimension: [0.4f32, 0.8f32], eye_height: 0.51875f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9400,6 +9974,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/villager"), @@ -9407,6 +9984,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.62f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9455,6 +10033,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/vindicator"), @@ -9498,6 +10079,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.6575f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9545,6 +10127,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/wandering_trader"), @@ -9552,6 +10137,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.62f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9600,6 +10186,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 16u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/warden"), @@ -9621,6 +10210,7 @@ impl EntityType { }), dimension: [0.9f32, 2.9f32], eye_height: 2.4650002f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9640,9 +10230,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.3125f32, 0.3125f32], eye_height: 0f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9691,6 +10285,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/witch"), @@ -9935,6 +10532,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.62f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -9984,6 +10582,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: false, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/wither"), @@ -9991,6 +10592,7 @@ impl EntityType { }), dimension: [0.9f32, 3.5f32], eye_height: 2.9750001f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10039,6 +10641,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/wither_skeleton"), @@ -10142,6 +10747,7 @@ impl EntityType { }), dimension: [0.7f32, 2.4f32], eye_height: 2.1f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10161,9 +10767,13 @@ impl EntityType { fire_immune: false, category: &MobCategory::MISC, can_spawn_far_from_player: true, + client_tracking_range: 4u32, + update_interval: 10u32, + track_deltas: true, loot_table: None, dimension: [0.3125f32, 0.3125f32], eye_height: 0.265625f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10203,7 +10813,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 1u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -10213,6 +10823,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::CREATURE, can_spawn_far_from_player: true, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/wolf"), @@ -10220,6 +10833,7 @@ impl EntityType { }), dimension: [0.6f32, 0.85f32], eye_height: 0.68f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10268,6 +10882,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/zoglin"), @@ -10311,6 +10928,7 @@ impl EntityType { }), dimension: [1.3964844f32, 1.4f32], eye_height: 1.19f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10360,6 +10978,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/zombie"), @@ -10527,6 +11148,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.74f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10575,6 +11197,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/zombie_horse"), @@ -10618,6 +11243,7 @@ impl EntityType { }), dimension: [1.3964844f32, 1.6f32], eye_height: 1.52f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10657,7 +11283,7 @@ impl EntityType { (Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64), (Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64), ], - experience_reward: 2u32, + experience_reward: 3u32, hurt_sound: None, attackable: Some(true), mob: true, @@ -10667,6 +11293,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 10u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/zombie_nautilus"), @@ -10710,6 +11339,7 @@ impl EntityType { }), dimension: [0.875f32, 0.95f32], eye_height: 0.2751f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::Unrestricted, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10759,6 +11389,9 @@ impl EntityType { fire_immune: false, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/zombie_villager"), @@ -10861,6 +11494,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.74f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -10910,6 +11544,9 @@ impl EntityType { fire_immune: true, category: &MobCategory::MONSTER, can_spawn_far_from_player: false, + client_tracking_range: 8u32, + update_interval: 3u32, + track_deltas: true, loot_table: Some(LootTable { r#type: LootTableType::Entity, random_sequence: Some("minecraft:entities/zombified_piglin"), @@ -11013,6 +11650,7 @@ impl EntityType { }), dimension: [0.6f32, 1.95f32], eye_height: 1.79f32, + spawn_dimensions_scale: 1f32, spawn_restriction: SpawnRestriction { location: SpawnLocation::OnGround, heightmap: HeightMap::MotionBlockingNoLeaves, @@ -11506,6 +12144,27 @@ impl EntityType { _ => None, } } + #[must_use] + pub const fn width(&self) -> f32 { + self.dimension[0] + } + #[must_use] + pub const fn height(&self) -> f32 { + self.dimension[1] + } + #[must_use] + pub fn get_spawn_bounding_box(&self, x: f64, y: f64, z: f64) -> BoundingBox { + let half_width = f64::from(self.spawn_dimensions_scale * self.dimension[0] / 2.0); + let height = f64::from(self.spawn_dimensions_scale * self.dimension[1]); + BoundingBox::new( + Vector3::new(x - half_width, y, z - half_width), + Vector3::new(x + half_width, y + height, z + half_width), + ) + } + #[must_use] + pub fn get_spawn_aabb(&self, x: f64, y: f64, z: f64) -> BoundingBox { + self.get_spawn_bounding_box(x, y, z) + } } impl IDSetContent for EntityType { fn registry_id(&self) -> u16 { diff --git a/crates/pumpkin-inventory/Cargo.toml b/crates/pumpkin-inventory/Cargo.toml index df39b40b2..20423c6f9 100644 --- a/crates/pumpkin-inventory/Cargo.toml +++ b/crates/pumpkin-inventory/Cargo.toml @@ -25,6 +25,7 @@ pumpkin-util.workspace = true rand.workspace = true tracing.workspace = true thiserror.workspace = true +rustc-hash.workspace = true [lints] workspace = true diff --git a/crates/pumpkin-inventory/src/lib.rs b/crates/pumpkin-inventory/src/lib.rs index 25ca979bd..50a37b994 100644 --- a/crates/pumpkin-inventory/src/lib.rs +++ b/crates/pumpkin-inventory/src/lib.rs @@ -58,7 +58,7 @@ pub mod stonecutter_screen_handler; pub mod sync_handler; pub mod window_property; -use std::collections::HashMap; +use rustc_hash::FxHashMap; pub use error::InventoryError; use pumpkin_data::data_component_impl::EquipmentSlot; @@ -71,10 +71,10 @@ use crate::player::player_inventory::PlayerInventory; /// (head, chest, legs, feet, off-hand) used by the player screen handler. /// /// # Returns -/// A `HashMap` where keys are slot indices and values are the corresponding [`EquipmentSlot`]s. +/// A `FxHashMap` where keys are slot indices and values are the corresponding [`EquipmentSlot`]s. #[must_use] -pub fn build_equipment_slots() -> HashMap { - let mut equipment_slots = HashMap::new(); +pub fn build_equipment_slots() -> FxHashMap { + let mut equipment_slots = FxHashMap::default(); equipment_slots.insert( EquipmentSlot::FEET.get_offset_entity_slot_id(PlayerInventory::MAIN_SIZE as i32) as usize, EquipmentSlot::FEET, @@ -92,7 +92,6 @@ pub fn build_equipment_slots() -> HashMap { EquipmentSlot::HEAD, ); - equipment_slots.insert(PlayerInventory::OFF_HAND_SLOT, EquipmentSlot::OFF_HAND); equipment_slots.insert(PlayerInventory::OFF_HAND_SLOT, EquipmentSlot::OFF_HAND); equipment_slots } diff --git a/crates/pumpkin-inventory/src/merchant/merchant_screen_handler.rs b/crates/pumpkin-inventory/src/merchant/merchant_screen_handler.rs index 317069155..3fc052a5a 100644 --- a/crates/pumpkin-inventory/src/merchant/merchant_screen_handler.rs +++ b/crates/pumpkin-inventory/src/merchant/merchant_screen_handler.rs @@ -492,7 +492,6 @@ impl Slot for MerchantResultSlot { mod tests { use std::{ borrow::Cow, - collections::HashMap, sync::atomic::{AtomicI32, AtomicUsize, Ordering}, }; @@ -627,7 +626,7 @@ mod tests { ( Arc::new(PlayerInventory::new( Arc::new(Mutex::new(EntityEquipment::new())), - Arc::new(HashMap::new()), + Arc::new(rustc_hash::FxHashMap::default()), )), Arc::new(SimpleInventory::new(3)), ) diff --git a/crates/pumpkin-inventory/src/player/player_inventory.rs b/crates/pumpkin-inventory/src/player/player_inventory.rs index 4b648c0fe..61b96909e 100644 --- a/crates/pumpkin-inventory/src/player/player_inventory.rs +++ b/crates/pumpkin-inventory/src/player/player_inventory.rs @@ -16,8 +16,8 @@ use pumpkin_data::item_stack::ItemStack; use pumpkin_protocol::java::client::play::CSetPlayerInventory; use pumpkin_util::Hand; use pumpkin_world::inventory::{Clearable, Inventory}; +use rustc_hash::FxHashMap; use std::any::Any; -use std::collections::HashMap; use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::{Arc, Mutex, RwLock}; @@ -35,7 +35,7 @@ pub struct PlayerInventory { /// Mapping of slot indices to equipment slot types. /// /// Used to identify which slots correspond to armor and off-hand equipment. - pub equipment_slots: Arc>, + pub equipment_slots: Arc>, /// The currently selected hotbar slot index (0-8). pub selected_slot: AtomicU8, /// The entity equipment storage for armor and off-hand items. @@ -60,7 +60,7 @@ impl PlayerInventory { // TODO: Add inventory load from nbt pub fn new( entity_equipment: Arc>, - equipment_slots: Arc>, + equipment_slots: Arc>, ) -> Self { Self { main_inventory: RwLock::new(std::array::from_fn(|_| ItemStack::EMPTY.clone())), diff --git a/crates/pumpkin-plugin-utils/Cargo.toml b/crates/pumpkin-plugin-utils/Cargo.toml index a5ce2e140..ba9b152d8 100644 --- a/crates/pumpkin-plugin-utils/Cargo.toml +++ b/crates/pumpkin-plugin-utils/Cargo.toml @@ -11,7 +11,7 @@ serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } tracing = { workspace = true } thiserror = { workspace = true } -ureq = { workspace = true, features = ["json"] } +reqwest = { workspace = true, features = ["blocking", "json"] } [dev-dependencies] tempfile = { workspace = true } diff --git a/crates/pumpkin-plugin-utils/src/http.rs b/crates/pumpkin-plugin-utils/src/http.rs index 3273e7912..2918b8298 100644 --- a/crates/pumpkin-plugin-utils/src/http.rs +++ b/crates/pumpkin-plugin-utils/src/http.rs @@ -18,7 +18,7 @@ pub enum HttpError { /// Helper client for querying Pumpkin marketplace REST APIs. pub struct HttpClient { - user_agent: String, + client: reqwest::blocking::Client, } impl Default for HttpClient { @@ -31,9 +31,11 @@ impl HttpClient { /// Creates a new HTTP client with the specified User-Agent header. #[must_use] pub fn new(user_agent: &str) -> Self { - Self { - user_agent: user_agent.to_string(), - } + let client = reqwest::blocking::Client::builder() + .user_agent(user_agent) + .build() + .unwrap_or_default(); + Self { client } } /// Performs an HTTP GET request and returns the response body as a string. @@ -42,24 +44,23 @@ impl HttpClient { /// /// Returns `HttpError` if the request fails or returns a non-2xx status code. pub fn get(&self, url: &str) -> Result { - let mut response = ureq::get(url) - .header("User-Agent", &self.user_agent) + let response = self + .client + .get(url) .header("Accept", "application/json") - .call() + .send() .map_err(|e| HttpError::RequestFailed(e.to_string()))?; let status = response.status().as_u16(); if status < 200 || status >= 300 { let body = response - .body_mut() - .read_to_string() + .text() .unwrap_or_else(|_| "Unknown error".to_string()); return Err(HttpError::BadStatus(status, body)); } response - .body_mut() - .read_to_string() + .text() .map_err(|e| HttpError::BodyRead(e.to_string())) } @@ -69,25 +70,25 @@ impl HttpClient { /// /// Returns `HttpError` if the request fails or returns a non-2xx status code. pub fn post_json(&self, url: &str, json_payload: &str) -> Result { - let mut response = ureq::post(url) - .header("User-Agent", &self.user_agent) + let response = self + .client + .post(url) .header("Content-Type", "application/json") .header("Accept", "application/json") - .send(json_payload) + .body(json_payload.to_string()) + .send() .map_err(|e| HttpError::RequestFailed(e.to_string()))?; let status = response.status().as_u16(); if status < 200 || status >= 300 { let body = response - .body_mut() - .read_to_string() + .text() .unwrap_or_else(|_| "Unknown error".to_string()); return Err(HttpError::BadStatus(status, body)); } response - .body_mut() - .read_to_string() + .text() .map_err(|e| HttpError::BodyRead(e.to_string())) } } diff --git a/crates/pumpkin-util/Cargo.toml b/crates/pumpkin-util/Cargo.toml index ed055ca3f..c4da0657a 100644 --- a/crates/pumpkin-util/Cargo.toml +++ b/crates/pumpkin-util/Cargo.toml @@ -30,7 +30,7 @@ ecdsa.workspace = true rsa.workspace = true sha2.workspace = true crypto-bigint.workspace = true -ureq.workspace = true +reqwest.workspace = true [dev-dependencies] criterion = { workspace = true, features = ["html_reports"] } diff --git a/crates/pumpkin-util/src/jwt/mod.rs b/crates/pumpkin-util/src/jwt/mod.rs index 639b26964..adb588233 100644 --- a/crates/pumpkin-util/src/jwt/mod.rs +++ b/crates/pumpkin-util/src/jwt/mod.rs @@ -244,32 +244,26 @@ pub const OIDC_DISCOVERY_URL: &str = "https://client.discovery.minecraft-services.net/api/v1.0/discovery/MinecraftPE/builds/1.0.0.0"; /// Fetches the OIDC JSON Web Key Set (JWKS) from the discovery endpoint. -pub fn fetch_oidc_jwks( +pub async fn fetch_oidc_jwks( discovery_url: Option<&str>, connect_timeout_ms: u32, read_timeout_ms: u32, ) -> Result<(String, Jwks), AuthError> { let url = discovery_url.unwrap_or(OIDC_DISCOVERY_URL); - let config = ureq::Agent::config_builder() - .timeout_connect(Some(std::time::Duration::from_millis( - connect_timeout_ms as u64, - ))) - .timeout_recv_response(Some(std::time::Duration::from_millis( - read_timeout_ms as u64, - ))) - .build(); - let agent: ureq::Agent = config.into(); + let client = reqwest::Client::builder() + .connect_timeout(std::time::Duration::from_millis(connect_timeout_ms as u64)) + .timeout(std::time::Duration::from_millis(read_timeout_ms as u64)) + .build() + .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))?; - let discovery: Value = agent + let discovery: Value = client .get(url) - .call() + .send() + .await .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))? - .body_mut() - .read_to_string() - .map_err(|e| AuthError::PublicKeyBuild(format!("Failed to read response: {e}"))) - .and_then(|s| { - serde_json::from_str(&s).map_err(|e| AuthError::PublicKeyBuild(e.to_string())) - })?; + .json() + .await + .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))?; let service_uri = discovery .get("result") @@ -281,16 +275,14 @@ pub fn fetch_oidc_jwks( .ok_or_else(|| AuthError::PublicKeyBuild("Discovery missing serviceUri".into()))?; let openid_config_url = format!("{service_uri}/.well-known/openid-configuration"); - let openid_config: Value = agent + let openid_config: Value = client .get(&openid_config_url) - .call() + .send() + .await .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))? - .body_mut() - .read_to_string() - .map_err(|e| AuthError::PublicKeyBuild(format!("Failed to read response: {e}"))) - .and_then(|s| { - serde_json::from_str(&s).map_err(|e| AuthError::PublicKeyBuild(e.to_string())) - })?; + .json() + .await + .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))?; let jwks_uri = openid_config .get("jwks_uri") @@ -303,16 +295,14 @@ pub fn fetch_oidc_jwks( .ok_or_else(|| AuthError::PublicKeyBuild("OpenID config missing issuer".into()))? .to_string(); - let jwks: Jwks = agent + let jwks: Jwks = client .get(jwks_uri) - .call() + .send() + .await .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))? - .body_mut() - .read_to_string() - .map_err(|e| AuthError::PublicKeyBuild(format!("Failed to read response: {e}"))) - .and_then(|s| { - serde_json::from_str(&s).map_err(|e| AuthError::PublicKeyBuild(e.to_string())) - })?; + .json() + .await + .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))?; Ok((issuer, jwks)) } diff --git a/crates/pumpkin-world/src/chunk/format/linear.rs b/crates/pumpkin-world/src/chunk/format/linear.rs index 53a902fc7..a328acaa7 100644 --- a/crates/pumpkin-world/src/chunk/format/linear.rs +++ b/crates/pumpkin-world/src/chunk/format/linear.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use std::io::{ErrorKind, Read}; use std::marker::PhantomData; use std::path::PathBuf; @@ -141,15 +141,15 @@ impl ChunkBitmap { // Repeated: u8 key_len, key bytes, u32 value // Terminated by a single 0x00 byte. -struct NbtFeatures(HashMap); +struct NbtFeatures(FxHashMap); impl NbtFeatures { fn empty() -> Self { - Self(HashMap::new()) + Self(FxHashMap::default()) } fn from_bytes(buf: &mut impl Buf) -> Result { - let mut map = HashMap::new(); + let mut map = FxHashMap::default(); loop { if !buf.has_remaining() { return Err(ChunkReadingError::IoError(std::io::Error::from( diff --git a/crates/pumpkin-world/src/chunk/format/mod.rs b/crates/pumpkin-world/src/chunk/format/mod.rs index 87e09abe3..68432e193 100644 --- a/crates/pumpkin-world/src/chunk/format/mod.rs +++ b/crates/pumpkin-world/src/chunk/format/mod.rs @@ -845,28 +845,31 @@ impl LightContainer { matches!(self, Self::Empty(_)) } + #[inline] const fn index(x: usize, y: usize, z: usize) -> usize { y * 16 * 16 + z * 16 + x } + #[inline] #[must_use] pub fn get(&self, x: usize, y: usize, z: usize) -> u8 { match self { Self::Full(data) => { let index = Self::index(x, y, z); - data[index >> 1] >> (4 * (index & 1)) & 0x0F + (data[index >> 1] >> (4 * (index & 1))) & 0x0F } Self::Empty(default) => *default, } } + #[inline] pub fn set(&mut self, x: usize, y: usize, z: usize, value: u8) { match self { Self::Full(data) => { let index = Self::index(x, y, z); - let mask = 0x0F << (4 * (index & 1)); - data[index >> 1] &= !mask; - data[index >> 1] |= value << (4 * (index & 1)); + let shift = 4 * (index & 1); + let mask = 0x0F << shift; + data[index >> 1] = (data[index >> 1] & !mask) | (value << shift); } Self::Empty(default) => { if value != *default { @@ -877,6 +880,39 @@ impl LightContainer { } } + #[inline] + pub fn set_column_y_range( + &mut self, + x: usize, + z: usize, + y_start: usize, + y_end: usize, + value: u8, + ) { + if y_start >= y_end { + return; + } + match self { + Self::Full(data) => { + let shift = 4 * (x & 1); + let mask = 0x0F << shift; + let val = (value & 0x0F) << shift; + let mut byte_idx = (y_start * 256 + z * 16 + x) >> 1; + for _ in y_start..y_end { + data[byte_idx] = (data[byte_idx] & !mask) | val; + byte_idx += 128; + } + } + Self::Empty(default) => { + if value != *default { + *self = Self::new_filled(*default); + self.set_column_y_range(x, z, y_start, y_end, value); + } + } + } + } + + #[inline] pub fn fill(&mut self, value: u8) { *self = Self::new_filled(value); } diff --git a/crates/pumpkin-world/src/chunk_system/schedule.rs b/crates/pumpkin-world/src/chunk_system/schedule.rs index 0b417809c..97ab889c4 100644 --- a/crates/pumpkin-world/src/chunk_system/schedule.rs +++ b/crates/pumpkin-world/src/chunk_system/schedule.rs @@ -242,41 +242,82 @@ impl GenerationSchedule { chunk_map: &HashMap, last_level: &ChunkLevel, last_high_priority: &[ChunkPos], - waiting_for_chunks: &HashSetType, + _waiting_for_chunks: &HashSetType, ) -> usize { debug_assert!(queue.is_empty()); + let mut to_drop = Vec::new(); let mut ready = Vec::new(); - for (key, node) in &mut graph.nodes { - if node.stage == StagedChunkEnum::None - || node.in_degree != 0 - || node.in_queue - || node.in_flight - || waiting_for_chunks.contains(&key) - { + + for (key, node) in &graph.nodes { + if node.stage == StagedChunkEnum::None || node.in_flight { continue; } + let Some(holder) = chunk_map.get(&node.pos) else { + to_drop.push(key); continue; }; - if holder.current_stage >= node.stage || holder.tasks[node.stage as usize] != key { + + let effective_target = holder.target_stage.max(holder.dependency_stage); + if holder.current_stage >= node.stage + || holder.tasks[node.stage as usize] != key + || node.stage > effective_target + { + to_drop.push(key); continue; } - ready.push((key, node.pos, node.stage)); + + if node.in_degree == 0 && !node.in_queue { + ready.push((key, node.pos, node.stage)); + } } - for (key, pos, stage) in &ready { - let Some(node) = graph.nodes.get_mut(*key) else { + for key in to_drop { + let Some(old) = graph.nodes.remove(key) else { continue; }; - node.in_queue = true; - queue.push(TaskHeapNode( - Self::calc_priority(last_level, last_high_priority, *pos, *stage), - *key, - )); + let mut edge = old.edge; + while !edge.is_null() { + let Some(cur) = graph.edges.remove(edge) else { + break; + }; + if let Some(target_node) = graph.nodes.get_mut(cur.to) + && target_node.in_degree > 0 + { + target_node.in_degree -= 1; + if target_node.in_degree == 0 && !target_node.in_queue && !target_node.in_flight + { + target_node.in_queue = true; + queue.push(TaskHeapNode( + Self::calc_priority( + last_level, + last_high_priority, + target_node.pos, + target_node.stage, + ), + cur.to, + )); + } + } + edge = cur.next; + } } - ready.len() + for (key, pos, stage) in ready { + if let Some(node) = graph.nodes.get_mut(key) + && node.in_degree == 0 + && !node.in_queue + { + node.in_queue = true; + queue.push(TaskHeapNode( + Self::calc_priority(last_level, last_high_priority, pos, stage), + key, + )); + } + } + + queue.len() } /// Ensure that the dependency chain for `req_stage` exists on `holder` (for chunk at @@ -296,7 +337,7 @@ impl GenerationSchedule { chunk_pos: ChunkPos, holder: &mut ChunkHolder, req_stage: StagedChunkEnum, - ) { + ) -> [bool; StagedChunkEnum::COUNT] { // Insert occupied_by edge head holder.occupied_by = graph.edges.insert(crate::chunk_system::dag::Edge::new( dependency_task, @@ -317,6 +358,7 @@ impl GenerationSchedule { // Effective target is the max of what the player wants and what dependencies need. let effective_target = holder.target_stage.max(holder.dependency_stage); + let mut newly_created = [false; StagedChunkEnum::COUNT]; // Create any missing tasks from current_stage+1 up to effective_target. // We do this even when current_stage >= req_stage, because dependency_stage may @@ -325,7 +367,6 @@ impl GenerationSchedule { let empty = StagedChunkEnum::Empty as usize; let start = (holder.current_stage as usize + 1).max(empty); let end = effective_target as u8 as usize; - let mut newly_created = [false; StagedChunkEnum::COUNT]; for (i, flag) in newly_created[start..=end].iter_mut().enumerate() { let stage_i = start + i; @@ -385,7 +426,7 @@ impl GenerationSchedule { // it was only blocked on `occupied` (handled above) and the stage itself is done. // Do NOT add an edge here: tasks[req_stage] is null (completed and dropped). if holder.current_stage >= req_stage { - return; + return newly_created; } // Wire req_stage task → dependency_task so dependency_task can't run until @@ -400,6 +441,8 @@ impl GenerationSchedule { "holder.tasks[req_stage] must not be null before adding edge" ); graph.add_edge(ano_task, dependency_task); + + newly_created } /// Check if any tasks parked in `waiting_for_chunks` now have all their neighbor @@ -411,11 +454,27 @@ impl GenerationSchedule { } let mut now_ready: Vec = Vec::new(); + let mut stale: Vec = Vec::new(); self.waiting_for_chunks.retain(|&node_key| { let Some(node) = self.graph.nodes.get(node_key) else { return false; // node was dropped, discard silently }; + + let Some(holder) = self.chunk_map.get(&node.pos) else { + stale.push(node_key); + return false; + }; + + let effective_target = holder.target_stage.max(holder.dependency_stage); + if holder.current_stage >= node.stage + || holder.tasks[node.stage as usize] != node_key + || node.stage > effective_target + { + stale.push(node_key); + return false; + } + let read_radius = node.stage.get_read_radius(); let pos = node.pos; let all_ready = (-read_radius..=read_radius).all(|dx| { @@ -437,6 +496,10 @@ impl GenerationSchedule { } }); + for node_key in stale { + self.drop_node(node_key); + } + for node_key in now_ready { if let Some(n) = self.graph.nodes.get_mut(node_key) && n.in_degree == 0 @@ -462,6 +525,9 @@ impl GenerationSchedule { let Some(new_level) = new_data.0 else { return true; }; + let mut worklist: std::collections::VecDeque<(ChunkPos, StagedChunkEnum, NodeKey)> = + std::collections::VecDeque::new(); + for (pos, (old_stage, new_stage)) in new_level.0 { debug_assert_ne!(old_stage, new_stage); debug_assert_eq!( @@ -537,7 +603,7 @@ impl GenerationSchedule { let new_pos = pos.add_raw(dx, dz); let req_stage = dependency[dx.abs().max(dz.abs()) as usize]; if new_pos == pos { - Self::ensure_dependency_chain( + let newly_created = Self::ensure_dependency_chain( &mut self.graph, &mut self.queue, &self.last_level, @@ -547,20 +613,33 @@ impl GenerationSchedule { &mut holder, req_stage, ); + for (stage_i, &created) in newly_created.iter().enumerate() { + if created && stage_i > 1 { + let stage = StagedChunkEnum::from(stage_i as u8); + let dependency = stage.get_direct_dependencies(); + let radius = stage.get_direct_radius(); + let cur_task = holder.tasks[stage_i]; + for ndx in -radius..=radius { + for ndz in -radius..=radius { + if ndx == 0 && ndz == 0 { + continue; + } + let neighbor_pos = new_pos.add_raw(ndx, ndz); + let neighbor_req = dependency + [ndx.abs().max(ndz.abs()) as usize]; + worklist.push_back(( + neighbor_pos, + neighbor_req, + cur_task, + )); + } + } + } + } continue; } - let ano_chunk = self.chunk_map.entry(new_pos).or_default(); - Self::ensure_dependency_chain( - &mut self.graph, - &mut self.queue, - &self.last_level, - &self.last_high_priority, - task, - new_pos, - ano_chunk, - req_stage, - ); + worklist.push_back((new_pos, req_stage, task)); } } } @@ -573,6 +652,40 @@ impl GenerationSchedule { } self.chunk_map.insert(pos, holder); } + + while let Some((pos, req_stage, dep_task)) = worklist.pop_front() { + let mut holder = self.chunk_map.remove(&pos).unwrap_or_default(); + let newly_created = Self::ensure_dependency_chain( + &mut self.graph, + &mut self.queue, + &new_level.1, + &self.last_high_priority, + dep_task, + pos, + &mut holder, + req_stage, + ); + for (stage_i, &created) in newly_created.iter().enumerate() { + if created && stage_i > 1 { + let stage = StagedChunkEnum::from(stage_i as u8); + let dependency = stage.get_direct_dependencies(); + let radius = stage.get_direct_radius(); + let cur_task = holder.tasks[stage_i]; + for dx in -radius..=radius { + for dz in -radius..=radius { + if dx == 0 && dz == 0 { + continue; + } + let neighbor_pos = pos.add_raw(dx, dz); + let neighbor_req = dependency[dx.abs().max(dz.abs()) as usize]; + worklist.push_back((neighbor_pos, neighbor_req, cur_task)); + } + } + } + } + self.chunk_map.insert(pos, holder); + } + self.last_level = new_level.1; self.queue_dirty = true; true @@ -852,20 +965,16 @@ impl GenerationSchedule { debug_assert!(node.in_degree >= 1); node.in_degree -= 1; if node.in_degree == 0 && !node.in_queue { - // Don't queue if parked in waiting_for_chunks — check_waiting_tasks() - // will re-queue it once chunk data arrives. - if !self.waiting_for_chunks.contains(&cur.to) { - self.queue.push(TaskHeapNode( - Self::calc_priority( - &self.last_level, - &self.last_high_priority, - node.pos, - node.stage, - ), - cur.to, - )); - node.in_queue = true; - } + self.queue.push(TaskHeapNode( + Self::calc_priority( + &self.last_level, + &self.last_high_priority, + node.pos, + node.stage, + ), + cur.to, + )); + node.in_queue = true; } } edge = cur.next; @@ -933,15 +1042,6 @@ impl GenerationSchedule { } } } - // If this chunk was only loaded for a dependency or cancelled - // and is no longer needed, clear dependency_stage and queue unload. - if holder.target_stage == StagedChunkEnum::None - && holder.current_stage >= holder.dependency_stage - { - holder.dependency_stage = StagedChunkEnum::None; - self.unload_chunks.insert(pos); - } - holder.chunk = Some(chunk); self.chunk_map.insert(pos, holder); @@ -1021,15 +1121,6 @@ impl GenerationSchedule { } holder.occupied = NodeKey::null(); - // If this chunk was only loaded for a dependency or cancelled - // and is no longer needed, clear dependency_stage and queue unload. - if holder.target_stage == StagedChunkEnum::None - && holder.current_stage >= holder.dependency_stage - { - holder.dependency_stage = StagedChunkEnum::None; - self.unload_chunks.insert(new_pos); - } - self.chunk_map.insert(new_pos, holder); } Chunk::Proto(chunk) => { @@ -1056,14 +1147,6 @@ impl GenerationSchedule { } } - // Clear dependency_stage and queue unload if no longer needed - if holder.target_stage == StagedChunkEnum::None - && holder.current_stage >= holder.dependency_stage - { - holder.dependency_stage = StagedChunkEnum::None; - self.unload_chunks.insert(new_pos); - } - holder.occupied = NodeKey::null(); holder.chunk = Some(Chunk::Proto(chunk)); self.chunk_map.insert(new_pos, holder); diff --git a/crates/pumpkin-world/src/lighting/engine.rs b/crates/pumpkin-world/src/lighting/engine.rs index 021c95fd0..d43598af9 100644 --- a/crates/pumpkin-world/src/lighting/engine.rs +++ b/crates/pumpkin-world/src/lighting/engine.rs @@ -4,34 +4,73 @@ use crate::generation::height_limit::HeightLimitView; use crate::generation::proto_chunk::GenerationCache; use crate::lighting::storage::{get_block_light, get_sky_light, set_block_light, set_sky_light}; use pumpkin_config::lighting::LightingEngineConfig; -use pumpkin_data::BlockDirection; +use pumpkin_data::{BlockDirection, BlockStateId}; use pumpkin_util::HeightMap; use pumpkin_util::math::position::BlockPos; use pumpkin_util::math::vector3::Vector3; use std::collections::VecDeque; -//use std::time::Instant; -// These are hit on every neighbour of every propagated block, so the hash -// function dominates. Use rustc-hash's fast hasher instead of the std default -// (SipHash), which is what "Fast" was meant to imply. -type FastHashSet = rustc_hash::FxHashSet; -type FastHashMap = rustc_hash::FxHashMap; +use crate::ProtoChunk; -/// Trait to unify Block and Sky light logic pub trait LightProvider { fn get_light(cache: &Cache, pos: BlockPos) -> u8; fn set_light(cache: &mut Cache, pos: BlockPos, level: u8); + fn get_light_proto( + chunk: &ProtoChunk, + section_idx: usize, + lx: usize, + ly: usize, + lz: usize, + ) -> u8; + fn set_light_proto( + chunk: &mut ProtoChunk, + section_idx: usize, + lx: usize, + ly: usize, + lz: usize, + level: u8, + ); fn propagate_level(current_level: u8, opacity: u8, dir: BlockDirection) -> u8; } pub struct BlockLightProvider; impl LightProvider for BlockLightProvider { + #[inline] fn get_light(cache: &Cache, pos: BlockPos) -> u8 { get_block_light(cache, pos) } + #[inline] fn set_light(cache: &mut Cache, pos: BlockPos, level: u8) { set_block_light(cache, pos, level); } + #[inline] + fn get_light_proto( + chunk: &ProtoChunk, + section_idx: usize, + lx: usize, + ly: usize, + lz: usize, + ) -> u8 { + chunk + .light + .block_light + .get(section_idx) + .map_or(0, |c| c.get(lx, ly, lz)) + } + #[inline] + fn set_light_proto( + chunk: &mut ProtoChunk, + section_idx: usize, + lx: usize, + ly: usize, + lz: usize, + level: u8, + ) { + if let Some(c) = chunk.light.block_light.get_mut(section_idx) { + c.set(lx, ly, lz, level); + } + } + #[inline] fn propagate_level(current_level: u8, opacity: u8, _dir: BlockDirection) -> u8 { current_level.saturating_sub(opacity.max(1)) } @@ -39,12 +78,42 @@ impl LightProvider for BlockLightProvider { pub struct SkyLightProvider; impl LightProvider for SkyLightProvider { + #[inline] fn get_light(cache: &Cache, pos: BlockPos) -> u8 { get_sky_light(cache, pos) } + #[inline] fn set_light(cache: &mut Cache, pos: BlockPos, level: u8) { set_sky_light(cache, pos, level); } + #[inline] + fn get_light_proto( + chunk: &ProtoChunk, + section_idx: usize, + lx: usize, + ly: usize, + lz: usize, + ) -> u8 { + chunk + .light + .sky_light + .get(section_idx) + .map_or(15, |c| c.get(lx, ly, lz)) + } + #[inline] + fn set_light_proto( + chunk: &mut ProtoChunk, + section_idx: usize, + lx: usize, + ly: usize, + lz: usize, + level: u8, + ) { + if let Some(c) = chunk.light.sky_light.get_mut(section_idx) { + c.set(lx, ly, lz, level); + } + } + #[inline] fn propagate_level(current_level: u8, opacity: u8, dir: BlockDirection) -> u8 { if current_level == 15 && dir == BlockDirection::Down && opacity == 0 { return 15; @@ -57,12 +126,114 @@ impl LightProvider for SkyLightProvider { #[derive(Clone, Copy)] pub struct PropagationEntry { pos: BlockPos, - skip_direction: Option, // direction from which the light came, used to prevent back-propagation + skip_direction: Option, +} + +pub struct VisitedBitSet { + bits: Vec, + min_x: i32, + min_y: i32, + min_z: i32, + size_x: usize, + size_y: usize, + size_z: usize, +} + +impl Default for VisitedBitSet { + fn default() -> Self { + Self::new() + } +} + +impl VisitedBitSet { + #[must_use] + pub const fn new() -> Self { + Self { + bits: Vec::new(), + min_x: 0, + min_y: 0, + min_z: 0, + size_x: 0, + size_y: 0, + size_z: 0, + } + } + + pub fn ensure_capacity( + &mut self, + min_x: i32, + min_y: i32, + min_z: i32, + size_x: usize, + size_y: usize, + size_z: usize, + ) { + self.min_x = min_x; + self.min_y = min_y; + self.min_z = min_z; + self.size_x = size_x; + self.size_y = size_y; + self.size_z = size_z; + let total = size_x * size_y * size_z; + let words = total.div_ceil(64); + if self.bits.len() == words { + self.bits.fill(0); + } else { + self.bits.resize(words, 0); + } + } + + #[inline] + pub fn clear(&mut self) { + self.bits.fill(0); + } + + #[inline] + pub fn test_and_set(&mut self, x: i32, y: i32, z: i32) -> bool { + let lx = (x - self.min_x) as usize; + let ly = (y - self.min_y) as usize; + let lz = (z - self.min_z) as usize; + if lx >= self.size_x || ly >= self.size_y || lz >= self.size_z { + return false; + } + let idx = (ly * self.size_z + lz) * self.size_x + lx; + let word = idx >> 6; + let mask = 1u64 << (idx & 63); + if let Some(w) = self.bits.get_mut(word) { + let prev = *w; + if prev & mask != 0 { + return false; + } + *w = prev | mask; + true + } else { + false + } + } + + #[inline] + #[must_use] + pub fn is_visited(&self, x: i32, y: i32, z: i32) -> bool { + let lx = (x - self.min_x) as usize; + let ly = (y - self.min_y) as usize; + let lz = (z - self.min_z) as usize; + if lx >= self.size_x || ly >= self.size_y || lz >= self.size_z { + return true; + } + let idx = (ly * self.size_z + lz) * self.size_x + lx; + let word = idx >> 6; + let mask = 1u64 << (idx & 63); + if let Some(&w) = self.bits.get(word) { + (w & mask) != 0 + } else { + true + } + } } pub struct LightPropagator { pub(crate) queue: VecDeque, - pub(crate) visited: FastHashSet, + pub(crate) visited: VisitedBitSet, pub(crate) decrease_queue: VecDeque<(BlockPos, u8)>, _marker: std::marker::PhantomData

, } @@ -71,8 +242,8 @@ impl LightPropagator

{ #[must_use] pub fn new() -> Self { Self { - queue: VecDeque::with_capacity(4096), - visited: FastHashSet::default(), + queue: VecDeque::with_capacity(8192), + visited: VisitedBitSet::new(), decrease_queue: VecDeque::new(), _marker: std::marker::PhantomData, } @@ -84,19 +255,21 @@ impl LightPropagator

{ self.decrease_queue.clear(); } - /// Core Propagation Logic (BFS). - /// - /// Reads and writes light directly through the light storage (a fast array - /// lookup) instead of maintaining a separate hashed shadow cache and batched - /// write buffer; the storage is the single source of truth. pub fn propagate(&mut self, cache: &mut Cache) { - // Cache metadata for bounds checking let cache_x = cache.x; let cache_z = cache.z; let cache_size = cache.size; let min_y = cache.bottom_y() as i32; let max_y = min_y + cache.height() as i32; + let min_x = cache_x * 16; + let min_z = cache_z * 16; + let size_x = (cache_size * 16) as usize; + let size_z = (cache_size * 16) as usize; + let size_y = (max_y - min_y) as usize; + self.visited + .ensure_capacity(min_x, min_y, min_z, size_x, size_y, size_z); + while let Some(entry) = self.queue.pop_front() { let pos = entry.pos; @@ -106,7 +279,6 @@ impl LightPropagator

{ } for dir in BlockDirection::all() { - // Skip the direction we came from (if specified) if let Some(skip_dir) = entry.skip_direction && dir == skip_dir { @@ -114,36 +286,78 @@ impl LightPropagator

{ } let neighbor_pos = pos.offset(dir.to_offset()); + let nx = neighbor_pos.0.x; + let ny = neighbor_pos.0.y; + let nz = neighbor_pos.0.z; - // Skip if already visited (critical early-exit optimization) - if self.visited.contains(&neighbor_pos) { + if self.visited.is_visited(nx, ny, nz) { continue; } - // Skip neighbor if it's outside world bounds - if neighbor_pos.0.y < min_y || neighbor_pos.0.y >= max_y { + if ny < min_y || ny >= max_y { continue; } - let (cx, _rel) = neighbor_pos.chunk_and_chunk_relative_position(); - let rel_x = cx.x - cache_x; - let rel_z = cx.y - cache_z; + let rel_x = (nx >> 4) - cache_x; + let rel_z = (nz >> 4) - cache_z; if rel_x < 0 || rel_x >= cache_size || rel_z < 0 || rel_z >= cache_size { continue; } - // Get block opacity - let state = cache.get_block_state(&neighbor_pos.0); - let opacity = state.to_state().opacity; + let chunk_idx = (rel_x * cache_size + rel_z) as usize; + let local_x = (nx & 15) as usize; + let local_z = (nz & 15) as usize; + + let section_idx = ((ny - min_y) >> 4) as usize; + let local_y = (ny & 15) as usize; + + let (opacity, neighbor_light) = match &cache.chunks[chunk_idx] { + Chunk::Proto(c) => { + let local_y_proto = ny - min_y; + let state_id = + c.get_block_state_raw(local_x as i32, local_y_proto, local_z as i32); + let op = if state_id == BlockStateId::AIR { + 0 + } else { + state_id.to_state().opacity + }; + let light = P::get_light_proto(c, section_idx, local_x, local_y, local_z); + (op, light) + } + Chunk::Level(lvl) => { + let state_id = lvl + .section + .get_block_absolute_y(local_x, ny, local_z) + .unwrap_or(BlockStateId::AIR); + let op = if state_id == BlockStateId::AIR { + 0 + } else { + state_id.to_state().opacity + }; + (op, P::get_light(cache, neighbor_pos)) + } + }; let new_level = P::propagate_level(current_light, opacity, dir); - let neighbor_light = P::get_light(cache, neighbor_pos); if new_level > neighbor_light { - P::set_light(cache, neighbor_pos, new_level); + match &mut cache.chunks[chunk_idx] { + Chunk::Proto(c) => { + P::set_light_proto( + c, + section_idx, + local_x, + local_y, + local_z, + new_level, + ); + } + Chunk::Level(_) => { + P::set_light(cache, neighbor_pos, new_level); + } + } - // Add to propagation queue if bright enough - if new_level > 1 && self.visited.insert(neighbor_pos) { + if new_level > 1 && self.visited.test_and_set(nx, ny, nz) { self.queue.push_back(PropagationEntry { pos: neighbor_pos, skip_direction: Some(dir.opposite()), @@ -154,55 +368,51 @@ impl LightPropagator

{ } } - /// Handle light removal pub fn process_decrease_queue(&mut self, cache: &mut Cache) { - { - // Cache metadata for bounds checking - let cache_x = cache.x; - let cache_z = cache.z; - let cache_size = cache.size; + let cache_x = cache.x; + let cache_z = cache.z; + let cache_size = cache.size; - while let Some((pos, old_val)) = self.decrease_queue.pop_front() { - for dir in BlockDirection::all() { - let neighbor_pos = pos.offset(dir.to_offset()); + while let Some((pos, old_val)) = self.decrease_queue.pop_front() { + for dir in BlockDirection::all() { + let neighbor_pos = pos.offset(dir.to_offset()); - // Bounds check - let (cx, _rel) = neighbor_pos.chunk_and_chunk_relative_position(); - let rel_x = cx.x - cache_x; - let rel_z = cx.y - cache_z; + let (cx, _rel) = neighbor_pos.chunk_and_chunk_relative_position(); + let rel_x = cx.x - cache_x; + let rel_z = cx.y - cache_z; - if rel_x < 0 || rel_x >= cache_size || rel_z < 0 || rel_z >= cache_size { - continue; - } + if rel_x < 0 || rel_x >= cache_size || rel_z < 0 || rel_z >= cache_size { + continue; + } - let neighbor_light = P::get_light(cache, neighbor_pos); - if neighbor_light == 0 { - continue; - } + let neighbor_light = P::get_light(cache, neighbor_pos); + if neighbor_light == 0 { + continue; + } - let state = cache.get_block_state(&neighbor_pos.0); - let opacity = state.to_state().opacity; + let state = cache.get_block_state(&neighbor_pos.0); + let opacity = state.to_state().opacity; - let predicted = P::propagate_level(old_val, opacity, dir); + let predicted = P::propagate_level(old_val, opacity, dir); - if neighbor_light == predicted || neighbor_light < old_val { - // Darken - P::set_light(cache, neighbor_pos, 0); - self.decrease_queue - .push_back((neighbor_pos, neighbor_light)); - } else if neighbor_light >= old_val { - // Re-illuminate from this bright neighbor - self.queue.push_back(PropagationEntry { - pos: neighbor_pos, - skip_direction: None, - }); - self.visited.insert(neighbor_pos); - } + if neighbor_light == predicted || neighbor_light < old_val { + P::set_light(cache, neighbor_pos, 0); + self.decrease_queue + .push_back((neighbor_pos, neighbor_light)); + } else if neighbor_light >= old_val { + let nx = neighbor_pos.0.x; + let ny = neighbor_pos.0.y; + let nz = neighbor_pos.0.z; + self.queue.push_back(PropagationEntry { + pos: neighbor_pos, + skip_direction: None, + }); + self.visited.test_and_set(nx, ny, nz); } } } - self.propagate(cache); // Re-propagate from survivors + self.propagate(cache); } } @@ -219,8 +429,6 @@ impl BlockLightPropagator { pub fn propagate_light(&mut self, cache: &mut Cache) { self.clear(); - //let scan_start = Instant::now(); - let min_y = cache.bottom_y() as i32; let max_y = min_y + cache.height() as i32; let center_x = cache.x + (cache.size / 2); @@ -231,33 +439,92 @@ impl BlockLightPropagator { let end_x = start_x + 18; let end_z = start_z + 18; - for y in min_y..max_y { - for z in start_z..end_z { - for x in start_x..end_x { - let pos_vec = Vector3::new(x, y, z); - let state = cache.get_block_state(&pos_vec); - let emission = state.to_state().luminance; - if emission > 0 { - let pos = BlockPos(pos_vec); - set_block_light(cache, pos, emission); - if self.visited.insert(pos) { - // Block light propagates in all directions - self.queue.push_back(PropagationEntry { - pos, - skip_direction: None, - }); + let min_x = cache.x * 16; + let min_z = cache.z * 16; + let size_x = (cache.size * 16) as usize; + let size_z = (cache.size * 16) as usize; + let size_y = (max_y - min_y) as usize; + self.visited + .ensure_capacity(min_x, min_y, min_z, size_x, size_y, size_z); + + for z in start_z..end_z { + let rel_z = (z >> 4) - cache.z; + let local_z = (z & 15) as usize; + + for x in start_x..end_x { + let rel_x = (x >> 4) - cache.x; + if rel_x < 0 || rel_x >= cache.size || rel_z < 0 || rel_z >= cache.size { + continue; + } + let chunk_idx = (rel_x * cache.size + rel_z) as usize; + let local_x = (x & 15) as usize; + + match &mut cache.chunks[chunk_idx] { + Chunk::Proto(c) => { + for y in min_y..max_y { + let local_y_proto = y - min_y; + let state_id = c.get_block_state_raw( + local_x as i32, + local_y_proto, + local_z as i32, + ); + if state_id == BlockStateId::AIR { + continue; + } + let emission = state_id.to_state().luminance; + if emission > 0 { + let section_idx = (local_y_proto >> 4) as usize; + let local_y = (y & 15) as usize; + if section_idx < c.light.block_light.len() { + c.light.block_light[section_idx] + .set(local_x, local_y, local_z, emission); + } + if self.visited.test_and_set(x, y, z) { + let pos = BlockPos(Vector3::new(x, y, z)); + self.queue.push_back(PropagationEntry { + pos, + skip_direction: None, + }); + } + } + } + } + Chunk::Level(lvl) => { + let mut light_engine = lvl + .light_engine + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner); + for y in min_y..max_y { + let state_id = lvl + .section + .get_block_absolute_y(local_x, y, local_z) + .unwrap_or(BlockStateId::AIR); + if state_id == BlockStateId::AIR { + continue; + } + let emission = state_id.to_state().luminance; + if emission > 0 { + let section_idx = ((y - min_y) >> 4) as usize; + let local_y = (y & 15) as usize; + if section_idx < light_engine.block_light.len() { + light_engine.block_light[section_idx] + .set(local_x, local_y, local_z, emission); + } + if self.visited.test_and_set(x, y, z) { + let pos = BlockPos(Vector3::new(x, y, z)); + self.queue.push_back(PropagationEntry { + pos, + skip_direction: None, + }); + } + } } } } } } - //let scan_elapsed = scan_start.elapsed(); - //let propagate_start = Instant::now(); self.propagate(cache); - - //let propagate_elapsed = propagate_start.elapsed(); - //log::info!("Block light timing - Scan: {:?}, Propagate: {:?}", scan_elapsed, propagate_elapsed); } } @@ -266,8 +533,6 @@ impl SkyLightPropagator { pub fn convert_light(&mut self, cache: &mut Cache) { self.clear(); - //let scan_start = Instant::now(); - let center_x = cache.x + (cache.size / 2); let center_z = cache.z + (cache.size / 2); let start_x = center_x * 16 - 1; @@ -278,25 +543,29 @@ impl SkyLightPropagator { let bottom_y = cache.bottom_y() as i32; let max_y = bottom_y + cache.height() as i32; - // Pre-allocate with exact size needed - let capacity = ((end_x - start_x) * (end_z - start_z)) as usize; - let mut surface_heights = - FastHashMap::with_capacity_and_hasher(capacity, rustc_hash::FxBuildHasher); + let min_x = cache.x * 16; + let min_z = cache.z * 16; + let size_x = (cache.size * 16) as usize; + let size_z = (cache.size * 16) as usize; + let size_y = (max_y - bottom_y) as usize; + self.visited + .ensure_capacity(min_x, bottom_y, min_z, size_x, size_y, size_z); + + let mut surface_heights = [0i32; 18 * 18]; - // Process in Z-outer, X-inner order for better cache locality for z in start_z..end_z { let chunk_z = z >> 4; let local_z = (z & 15) as usize; + let lz = (z - start_z) as usize; for x in start_x..end_x { let chunk_x = x >> 4; let local_x = (x & 15) as usize; + let lx = (x - start_x) as usize; - // Get heightmap (top solid blocks) let top_y = cache.get_top_y(&HeightMap::WorldSurface, x, z); - surface_heights.insert((x, z), top_y); + surface_heights[lx * 18 + lz] = top_y; - // Get chunk index once per column let rel_x = chunk_x - cache.x; let rel_z = chunk_z - cache.z; @@ -306,89 +575,123 @@ impl SkyLightPropagator { let chunk_idx = (rel_x * cache.size + rel_z) as usize; - // Fill everything above heightmap with 15 immediately - for y in (top_y + 1)..max_y { - let section_idx = ((y - bottom_y) >> 4) as usize; - let local_y = (y & 15) as usize; - - // Direct array access - skip all function call overhead - match &mut cache.chunks[chunk_idx] { - Chunk::Proto(c) => { - if section_idx < c.light.sky_light.len() { - c.light.sky_light[section_idx].set(local_x, local_y, local_z, 15); + match &mut cache.chunks[chunk_idx] { + Chunk::Proto(c) => { + let top_local_y = (top_y + 1 - bottom_y).max(0) as usize; + let top_sec = top_local_y >> 4; + let top_rem = top_local_y & 15; + if top_sec < c.light.sky_light.len() { + c.light.sky_light[top_sec] + .set_column_y_range(local_x, local_z, top_rem, 16, 15); + for sec in (top_sec + 1)..c.light.sky_light.len() { + c.light.sky_light[sec] + .set_column_y_range(local_x, local_z, 0, 16, 15); } } - Chunk::Level(c) => { - let mut light_engine = c - .light_engine - .lock() - .unwrap_or_else(std::sync::PoisonError::into_inner); + + let mut light: i32 = 15; + for y in (bottom_y..=top_y).rev() { + let local_y_proto = y - bottom_y; + let state_id = c.get_block_state_raw( + local_x as i32, + local_y_proto, + local_z as i32, + ); + let opacity = if state_id == BlockStateId::AIR { + 0 + } else { + state_id.to_state().opacity as i32 + }; + + light = light.saturating_sub(opacity); + let light_val = if light <= 0 { 0 } else { light as u8 }; + let section_idx = (local_y_proto >> 4) as usize; + let local_y = (y & 15) as usize; + + if section_idx < c.light.sky_light.len() { + c.light.sky_light[section_idx] + .set(local_x, local_y, local_z, light_val); + } + + if light <= 0 { + break; + } + } + } + Chunk::Level(c) => { + let mut light_engine = c + .light_engine + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner); + + for y in (top_y + 1)..max_y { + let section_idx = ((y - bottom_y) >> 4) as usize; + let local_y = (y & 15) as usize; if section_idx < light_engine.sky_light.len() { light_engine.sky_light[section_idx] .set(local_x, local_y, local_z, 15); } } - } - } - // Only iterate from top_y DOWN - not from max_y - let mut light: i32 = 15; + let mut light: i32 = 15; + for y in (bottom_y..=top_y).rev() { + let section_idx = ((y - bottom_y) >> 4) as usize; + let local_y = (y & 15) as usize; - for y in (bottom_y..=top_y).rev() { - let section_idx = ((y - bottom_y) >> 4) as usize; - let local_y = (y & 15) as usize; + let state_id = c + .section + .get_block_absolute_y(local_x, y, local_z) + .unwrap_or(BlockStateId::AIR); + let opacity = if state_id == BlockStateId::AIR { + 0 + } else { + state_id.to_state().opacity as i32 + }; - // Get block opacity - let opacity = { - let pos_vec = Vector3::new(x, y, z); - let state = cache.get_block_state(&pos_vec); - state.to_state().opacity - } as i32; + light = light.saturating_sub(opacity); + let light_val = if light <= 0 { 0 } else { light as u8 }; - // Reduce light by opacity - light = light.saturating_sub(opacity); - - // Set the light value directly - let light_val = if light <= 0 { 0 } else { light as u8 }; - - match &mut cache.chunks[chunk_idx] { - Chunk::Proto(c) => { - if section_idx < c.light.sky_light.len() { - c.light.sky_light[section_idx] - .set(local_x, local_y, local_z, light_val); - } - } - Chunk::Level(c) => { - let mut light_engine = c - .light_engine - .lock() - .unwrap_or_else(std::sync::PoisonError::into_inner); if section_idx < light_engine.sky_light.len() { light_engine.sky_light[section_idx] .set(local_x, local_y, local_z, light_val); } - } - } - // Early exit when light hits 0 - if light <= 0 { - break; + if light <= 0 { + break; + } + } } } } } - // Enqueue horizontal propagation for z in start_z..end_z { + let lz = (z - start_z) as usize; for x in start_x..end_x { - let top_y = surface_heights[&(x, z)]; + let lx = (x - start_x) as usize; + let top_y = surface_heights[lx * 18 + lz]; - let north_top = surface_heights.get(&(x, z - 1)).copied().unwrap_or(top_y); - let south_top = surface_heights.get(&(x, z + 1)).copied().unwrap_or(top_y); - let west_top = surface_heights.get(&(x - 1, z)).copied().unwrap_or(top_y); - let east_top = surface_heights.get(&(x + 1, z)).copied().unwrap_or(top_y); + let north_top = if lz > 0 { + surface_heights[lx * 18 + (lz - 1)] + } else { + top_y + }; + let south_top = if lz + 1 < 18 { + surface_heights[lx * 18 + (lz + 1)] + } else { + top_y + }; + let west_top = if lx > 0 { + surface_heights[(lx - 1) * 18 + lz] + } else { + top_y + }; + let east_top = if lx + 1 < 18 { + surface_heights[(lx + 1) * 18 + lz] + } else { + top_y + }; - // We must check up to the highest neighbor to catch the "air sources" let max_check_y = top_y .max(north_top) .max(south_top) @@ -399,7 +702,6 @@ impl SkyLightPropagator { let pos = BlockPos(Vector3::new(x, y, z)); let light = get_sky_light(cache, pos); - // Use continue, or only break if we are safely below all possible side-light if light == 0 { if y <= top_y { break; @@ -411,7 +713,7 @@ impl SkyLightPropagator { let below_neighbor = y < north_top || y < south_top || y < west_top || y < east_top; - if (is_at_surface || below_neighbor) && self.visited.insert(pos) { + if (is_at_surface || below_neighbor) && self.visited.test_and_set(x, y, z) { let skip_dir = (y >= top_y).then_some(BlockDirection::Up); self.queue.push_back(PropagationEntry { @@ -423,13 +725,7 @@ impl SkyLightPropagator { } } - //let propagate_start = Instant::now(); - self.propagate(cache); - - //let propagate_elapsed = propagate_start.elapsed(); - //let scan_elapsed = scan_start.elapsed(); - //log::info!("Sky light timing - Scan: {:?}, Propagate: {:?}", scan_elapsed, propagate_elapsed); } } @@ -474,7 +770,6 @@ impl LightEngine { old_luminance: u8, new_luminance: u8, ) { - // Decrease Logic if old_luminance > new_luminance { let current_light = get_block_light(cache, pos); if current_light > 0 { @@ -485,10 +780,13 @@ impl LightEngine { } } - // Increase Logic if new_luminance > 0 { set_block_light(cache, pos, new_luminance); - if self.block_light.visited.insert(pos) { + if self + .block_light + .visited + .test_and_set(pos.0.x, pos.0.y, pos.0.z) + { self.block_light.queue.push_back(PropagationEntry { pos, skip_direction: None, diff --git a/crates/pumpkin-world/src/lighting/storage.rs b/crates/pumpkin-world/src/lighting/storage.rs index 2c74fed36..436ace885 100644 --- a/crates/pumpkin-world/src/lighting/storage.rs +++ b/crates/pumpkin-world/src/lighting/storage.rs @@ -3,6 +3,7 @@ use crate::chunk_system::generation_cache::Cache; use crate::generation::height_limit::HeightLimitView; use pumpkin_util::math::position::BlockPos; +#[inline] const fn get_chunk_index(cache: &Cache, chunk_x: i32, chunk_z: i32) -> Option { let rel_x = chunk_x - cache.x; let rel_z = chunk_z - cache.z; @@ -12,6 +13,7 @@ const fn get_chunk_index(cache: &Cache, chunk_x: i32, chunk_z: i32) -> Option Option { let bottom = cache.bottom_y() as i32; if pos_y < bottom { @@ -21,6 +23,7 @@ fn get_section_y(cache: &Cache, pos_y: i32) -> Option { Some(section) } +#[inline] #[must_use] pub fn get_block_light(cache: &Cache, pos: BlockPos) -> u8 { let chunk_x = pos.0.x >> 4; @@ -58,6 +61,7 @@ pub fn get_block_light(cache: &Cache, pos: BlockPos) -> u8 { } } +#[inline] pub fn set_block_light(cache: &mut Cache, pos: BlockPos, level: u8) { let chunk_x = pos.0.x >> 4; let chunk_z = pos.0.z >> 4; @@ -99,6 +103,7 @@ pub fn set_block_light(cache: &mut Cache, pos: BlockPos, level: u8) { } } +#[inline] #[must_use] pub fn get_sky_light(cache: &Cache, pos: BlockPos) -> u8 { let chunk_x = pos.0.x >> 4; @@ -136,6 +141,7 @@ pub fn get_sky_light(cache: &Cache, pos: BlockPos) -> u8 { } } +#[inline] pub fn set_sky_light(cache: &mut Cache, pos: BlockPos, level: u8) { let chunk_x = pos.0.x >> 4; let chunk_z = pos.0.z >> 4; diff --git a/crates/pumpkin-world/src/poi/mod.rs b/crates/pumpkin-world/src/poi/mod.rs index 5ddc71f0f..3761ab360 100644 --- a/crates/pumpkin-world/src/poi/mod.rs +++ b/crates/pumpkin-world/src/poi/mod.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use std::io::{Cursor, Read, Write}; use std::path::{Path, PathBuf}; use tracing::{info, warn}; @@ -70,16 +70,16 @@ pub struct PoiSectionData { pub struct PoiChunkData { pub data_version: i32, /// Sections keyed by Y section coordinate (e.g., "-1", "0", "1", "4") - pub sections: HashMap, + pub sections: FxHashMap, } /// POI data for a single region (32x32 chunks) using MCA format #[derive(Debug, Default)] pub struct PoiRegion { /// Entries indexed by position - entries: HashMap<(i32, i32, i32), PoiEntry>, + entries: FxHashMap<(i32, i32, i32), PoiEntry>, /// Track which chunks are dirty - dirty_chunks: std::collections::HashSet<(i32, i32)>, + dirty_chunks: rustc_hash::FxHashSet<(i32, i32)>, dirty: bool, } @@ -144,7 +144,7 @@ impl PoiRegion { /// Group entries by chunk, then create chunk NBT data fn get_chunk_data(&self, chunk_x: i32, chunk_z: i32) -> Option { - let mut sections: HashMap = HashMap::new(); + let mut sections: FxHashMap = FxHashMap::default(); for entry in self.entries.values() { let entry_chunk_x = entry.x >> 4; @@ -218,7 +218,7 @@ impl PoiRegion { .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()))?; let data_version = nbt.get_int("DataVersion").unwrap_or(DATA_VERSION); - let mut sections = HashMap::new(); + let mut sections = FxHashMap::default(); if let Some(sec_tag) = nbt.get_compound("Sections") { for (sec_key, tag) in &sec_tag.child_tags { @@ -269,11 +269,11 @@ impl PoiRegion { } // Build all chunk data - let mut chunk_data_map: HashMap> = HashMap::new(); + let mut chunk_data_map: FxHashMap> = FxHashMap::default(); // Collect all unique chunks that have entries - let mut chunks_with_data: std::collections::HashSet<(i32, i32)> = - std::collections::HashSet::new(); + let mut chunks_with_data: rustc_hash::FxHashSet<(i32, i32)> = + rustc_hash::FxHashSet::default(); for entry in self.entries.values() { chunks_with_data.insert((entry.x >> 4, entry.z >> 4)); } @@ -429,7 +429,7 @@ pub struct PoiStorage { /// Path to the poi folder folder: PathBuf, /// Loaded regions, keyed by (`region_x`, `region_z`) - regions: HashMap<(i32, i32), PoiRegion>, + regions: FxHashMap<(i32, i32), PoiRegion>, } impl PoiStorage { @@ -437,7 +437,7 @@ impl PoiStorage { pub fn new(poi_folder: PathBuf) -> Self { Self { folder: poi_folder, - regions: HashMap::new(), + regions: FxHashMap::default(), } } diff --git a/crates/pumpkin/Cargo.toml b/crates/pumpkin/Cargo.toml index cacc7cc91..fe4a3ed2b 100644 --- a/crates/pumpkin/Cargo.toml +++ b/crates/pumpkin/Cargo.toml @@ -76,7 +76,7 @@ wasmparser.workspace = true wasm-encoder = "0.257" # authentication -ureq = { workspace = true, features = ["json"] } +reqwest = { workspace = true, features = ["json"] } sha1.workspace = true diff --git a/crates/pumpkin/src/block/blocks/sculk/sculk_vein.rs b/crates/pumpkin/src/block/blocks/sculk/sculk_vein.rs index 945e4b602..b3dd6c1cd 100644 --- a/crates/pumpkin/src/block/blocks/sculk/sculk_vein.rs +++ b/crates/pumpkin/src/block/blocks/sculk/sculk_vein.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use rustc_hash::FxHashSet; use crate::block::{ BlockBehaviour, BlockIsReplacing, BlockMetadata, CanPlaceAtArgs, CanUpdateAtArgs, @@ -154,7 +154,7 @@ fn get_attach_direction( replacing_block, )) } else { - HashSet::new() + FxHashSet::default() }; if let Some(player) = player_wrapper { @@ -183,8 +183,8 @@ const fn is_solid_face(block: &Block) -> bool { block.default_state.is_full_cube() } -fn active_directions(props: GlowLichenLikeProperties) -> HashSet { - let mut set = HashSet::new(); +fn active_directions(props: GlowLichenLikeProperties) -> FxHashSet { + let mut set = FxHashSet::default(); if props.down { set.insert(BlockDirection::Down); } diff --git a/crates/pumpkin/src/block/blocks/trial_spawner.rs b/crates/pumpkin/src/block/blocks/trial_spawner.rs index 89e288a3c..4ce2aa228 100644 --- a/crates/pumpkin/src/block/blocks/trial_spawner.rs +++ b/crates/pumpkin/src/block/blocks/trial_spawner.rs @@ -1,17 +1,9 @@ use std::sync::Arc; -use pumpkin_data::block_properties::{ - BlockProperties, TrialSpawnerLikeProperties, TrialSpawnerState, -}; -use pumpkin_data::item::Item; -use pumpkin_data::item_stack::ItemStack; -use pumpkin_data::sound::{Sound, SoundCategory}; use pumpkin_macros::pumpkin_block; -use pumpkin_world::world::BlockFlags; use crate::block::entities::trial_spawner::TrialSpawnerBlockEntity; -use crate::block::registry::BlockActionResult; -use crate::block::{BlockBehaviour, NormalUseArgs, PlacedArgs, UseWithItemArgs}; +use crate::block::{BlockBehaviour, PlacedArgs}; #[pumpkin_block("minecraft:trial_spawner")] pub struct TrialSpawnerBlock; @@ -21,95 +13,4 @@ impl BlockBehaviour for TrialSpawnerBlock { let entity = TrialSpawnerBlockEntity::new(*args.position); args.world.add_block_entity(Arc::new(entity)); } - - fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult { - let state_id = args.world.get_block_state_id(args.position); - let mut props = TrialSpawnerLikeProperties::from_state_id(state_id, args.block); - - match props.trial_spawner_state { - TrialSpawnerState::Inactive | TrialSpawnerState::WaitingForPlayers => { - props.trial_spawner_state = TrialSpawnerState::Active; - args.world.set_block_state( - args.position, - props.to_state_id(args.block), - BlockFlags::NOTIFY_ALL, - ); - - args.world.play_sound( - Sound::BlockTrialSpawnerDetectPlayer, - SoundCategory::Blocks, - &args.position.to_f64(), - ); - args.world.play_sound( - Sound::BlockTrialSpawnerOpenShutter, - SoundCategory::Blocks, - &args.position.to_f64(), - ); - } - TrialSpawnerState::Active => { - // Eject trial rewards & key drop upon trial wave completion - props.trial_spawner_state = TrialSpawnerState::WaitingForRewardEjection; - args.world.set_block_state( - args.position, - props.to_state_id(args.block), - BlockFlags::NOTIFY_ALL, - ); - - args.world.play_sound( - Sound::BlockTrialSpawnerSpawnItemBegin, - SoundCategory::Blocks, - &args.position.to_f64(), - ); - args.world.play_sound( - Sound::BlockTrialSpawnerEjectItem, - SoundCategory::Blocks, - &args.position.to_f64(), - ); - - let key_stack = ItemStack::new(1, &Item::TRIAL_KEY); - args.world.drop_stack(args.position, key_stack); - - props.trial_spawner_state = TrialSpawnerState::Cooldown; - args.world.set_block_state( - args.position, - props.to_state_id(args.block), - BlockFlags::NOTIFY_ALL, - ); - - args.world.play_sound( - Sound::BlockTrialSpawnerCloseShutter, - SoundCategory::Blocks, - &args.position.to_f64(), - ); - } - TrialSpawnerState::Cooldown => { - args.world.play_sound( - Sound::BlockTrialSpawnerAmbient, - SoundCategory::Blocks, - &args.position.to_f64(), - ); - } - TrialSpawnerState::WaitingForRewardEjection | TrialSpawnerState::EjectingReward => { - props.trial_spawner_state = TrialSpawnerState::Cooldown; - args.world.set_block_state( - args.position, - props.to_state_id(args.block), - BlockFlags::NOTIFY_ALL, - ); - } - } - - BlockActionResult::Success - } - - fn use_with_item(&self, args: UseWithItemArgs<'_>) -> BlockActionResult { - self.normal_use(NormalUseArgs { - server: args.server, - world: args.world, - block: args.block, - position: args.position, - player: args.player, - hit: args.hit, - }) - } } diff --git a/crates/pumpkin/src/block/entities/mob_spawner.rs b/crates/pumpkin/src/block/entities/mob_spawner.rs index 380ca4522..d515ca416 100644 --- a/crates/pumpkin/src/block/entities/mob_spawner.rs +++ b/crates/pumpkin/src/block/entities/mob_spawner.rs @@ -6,11 +6,7 @@ use std::sync::{ use crossbeam::atomic::AtomicCell; use pumpkin_data::{entity::EntityType, world::WorldEvent}; use pumpkin_nbt::compound::NbtCompound; -use pumpkin_util::math::{ - boundingbox::{BoundingBox, EntityDimensions}, - position::BlockPos, - vector3::Vector3, -}; +use pumpkin_util::math::{position::BlockPos, vector3::Vector3}; use crate::{block::entities::BlockEntity, entity::EntityBase, world::World}; @@ -161,16 +157,10 @@ impl BlockEntity for MobSpawnerBlockEntity { + (rand::random::() - rand::random::()) * spawn_range as f64 + 0.5, ); - // TODO: we should use getSpawnBox, but this is only modified for slimes and magma slimes - if !world.is_space_empty(BoundingBox::new_from_pos( + if !world.is_space_empty(entity_type.get_spawn_bounding_box( spawn_pos.x, spawn_pos.y, spawn_pos.z, - &EntityDimensions { - width: entity_type.dimension[0], - height: entity_type.dimension[1], - eye_height: entity_type.eye_height, - }, )) { continue; } diff --git a/crates/pumpkin/src/block/entities/trial_spawner.rs b/crates/pumpkin/src/block/entities/trial_spawner.rs index fa60fdde8..3d49d8882 100644 --- a/crates/pumpkin/src/block/entities/trial_spawner.rs +++ b/crates/pumpkin/src/block/entities/trial_spawner.rs @@ -1,13 +1,1128 @@ -use super::BlockEntity; +use rustc_hash::FxHashSet; +use std::sync::{Arc, Mutex}; + +use pumpkin_data::block_properties::{ + BlockProperties, TrialSpawnerLikeProperties, TrialSpawnerState, +}; +use pumpkin_data::entity::EntityType; +use pumpkin_data::item::Item; +use pumpkin_data::item_stack::ItemStack; +use pumpkin_data::sound::{Sound, SoundCategory}; +use pumpkin_data::world::WorldEvent; use pumpkin_nbt::compound::NbtCompound; +use pumpkin_nbt::tag::NbtTag; +use pumpkin_util::Difficulty; use pumpkin_util::math::position::BlockPos; -use std::sync::Mutex; +use pumpkin_util::math::vector3::Vector3; +use rand::RngExt; +use uuid::Uuid; + +use super::BlockEntity; +use crate::entity::EntityBase; +use crate::world::World; + +/// Flame particle type used by trial spawners for world events. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum TrialSpawnerFlameParticle { + Normal = 0, + Ominous = 1, +} + +impl TrialSpawnerFlameParticle { + #[must_use] + pub const fn encode(self) -> i32 { + self as i32 + } + + #[must_use] + pub const fn decode(data: i32) -> Self { + if data == 1 { + Self::Ominous + } else { + Self::Normal + } + } +} + +/// Player detector strategies for the trial spawner. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +pub enum PlayerDetector { + #[default] + NoCreativePlayers, + Sheep, +} + +impl PlayerDetector { + #[must_use] + pub fn detect(&self, world: &World, spawner_pos: BlockPos, range: i32) -> Vec { + let center = spawner_pos.to_centered_f64(); + let max_dist_sq = f64::from(range * range); + + match self { + Self::NoCreativePlayers => { + let players = world.players.load(); + players + .iter() + .filter_map(|player| { + let mode = player.gamemode.load(); + if mode == pumpkin_util::GameMode::Creative + || mode == pumpkin_util::GameMode::Spectator + { + return None; + } + let ent = player.get_entity(); + if !ent.is_alive() { + return None; + } + let pos = ent.pos.load(); + (pos.squared_distance_to_vec(¢er) <= max_dist_sq) + .then_some(player.gameprofile.id) + }) + .collect() + } + Self::Sheep => { + let entities = world.entities.load(); + entities + .iter() + .filter_map(|e| { + let ent = e.get_entity(); + (ent.entity_type.id == EntityType::SHEEP.id + && ent.is_alive() + && ent.pos.load().squared_distance_to_vec(¢er) <= max_dist_sq) + .then_some(ent.entity_uuid) + }) + .collect() + } + } + } +} + +/// Spawn data configuration for an entity to spawn. +#[derive(Clone, Debug)] +pub struct SpawnData { + pub entity_type: Option<&'static EntityType>, + pub custom_spawn_rules: Option, + pub equipment: Option, + pub raw_entity_nbt: Option, +} + +impl Default for SpawnData { + fn default() -> Self { + Self { + entity_type: Some(&EntityType::ZOMBIE), + custom_spawn_rules: None, + equipment: None, + raw_entity_nbt: None, + } + } +} + +impl SpawnData { + #[must_use] + pub const fn from_entity_type(entity_type: &'static EntityType) -> Self { + Self { + entity_type: Some(entity_type), + custom_spawn_rules: None, + equipment: None, + raw_entity_nbt: None, + } + } + + #[must_use] + pub fn from_nbt(nbt: &NbtCompound) -> Self { + let entity_compound = nbt.get_compound("entity").cloned(); + let entity_type = entity_compound + .as_ref() + .and_then(|e| e.get_string("id")) + .or_else(|| nbt.get_string("id")) + .and_then(|id| EntityType::from_name(id.strip_prefix("minecraft:").unwrap_or(id))); + + Self { + entity_type, + custom_spawn_rules: nbt.get_compound("custom_spawn_rules").cloned(), + equipment: nbt.get_compound("equipment").cloned(), + raw_entity_nbt: entity_compound, + } + } + + pub fn write_nbt(&self, nbt: &mut NbtCompound) { + if let Some(entity_type) = self.entity_type { + let mut entity_compound = self.raw_entity_nbt.clone().unwrap_or_default(); + entity_compound.put_string("id", format!("minecraft:{}", entity_type.resource_name)); + nbt.put_compound("entity", entity_compound); + } + if let Some(rules) = &self.custom_spawn_rules { + nbt.put_compound("custom_spawn_rules", rules.clone()); + } + if let Some(equipment) = &self.equipment { + nbt.put_compound("equipment", equipment.clone()); + } + } +} + +#[derive(Clone, Debug)] +pub struct WeightedSpawnData { + pub data: SpawnData, + pub weight: i32, +} + +#[derive(Clone, Debug)] +pub struct WeightedLootTable { + pub data: String, + pub weight: i32, +} + +/// Trial spawner configuration for a mode (normal or ominous). +#[derive(Clone, Debug)] +pub struct TrialSpawnerConfig { + pub spawn_range: i32, + pub total_mobs: f32, + pub simultaneous_mobs: f32, + pub total_mobs_added_per_player: f32, + pub simultaneous_mobs_added_per_player: f32, + pub ticks_between_spawn: i32, + pub spawn_potentials: Vec, + pub loot_tables_to_eject: Vec, + pub items_to_drop_when_ominous: Option, +} + +impl Default for TrialSpawnerConfig { + fn default() -> Self { + Self { + spawn_range: 4, + total_mobs: 6.0, + simultaneous_mobs: 2.0, + total_mobs_added_per_player: 2.0, + simultaneous_mobs_added_per_player: 1.0, + ticks_between_spawn: 40, + spawn_potentials: vec![WeightedSpawnData { + data: SpawnData::default(), + weight: 1, + }], + loot_tables_to_eject: Vec::new(), + items_to_drop_when_ominous: None, + } + } +} + +impl TrialSpawnerConfig { + #[must_use] + pub fn calculate_target_total_mobs(&self, player_count: usize) -> i32 { + let additional = player_count.saturating_sub(1) as f32 * self.total_mobs_added_per_player; + (self.total_mobs + additional).floor() as i32 + } + + #[must_use] + pub fn calculate_target_simultaneous_mobs(&self, player_count: usize) -> i32 { + let additional = + player_count.saturating_sub(1) as f32 * self.simultaneous_mobs_added_per_player; + (self.simultaneous_mobs + additional).floor() as i32 + } + + #[must_use] + pub fn with_spawning(&self, entity_type: &'static EntityType) -> Self { + let mut clone = self.clone(); + clone.spawn_potentials = vec![WeightedSpawnData { + data: SpawnData::from_entity_type(entity_type), + weight: 1, + }]; + clone + } + + #[must_use] + pub fn pick_spawn_data(&self) -> Option { + if self.spawn_potentials.is_empty() { + return Some(SpawnData::default()); + } + let total_weight: i32 = self.spawn_potentials.iter().map(|p| p.weight.max(1)).sum(); + if total_weight <= 0 { + return self.spawn_potentials.first().map(|p| p.data.clone()); + } + let mut roll = rand::rng().random_range(0..total_weight); + for potential in &self.spawn_potentials { + let weight = potential.weight.max(1); + if roll < weight { + return Some(potential.data.clone()); + } + roll -= weight; + } + self.spawn_potentials.first().map(|p| p.data.clone()) + } + + #[must_use] + pub fn pick_loot_table(&self) -> Option { + if self.loot_tables_to_eject.is_empty() { + return None; + } + let total_weight: i32 = self + .loot_tables_to_eject + .iter() + .map(|p| p.weight.max(1)) + .sum(); + if total_weight <= 0 { + return self.loot_tables_to_eject.first().map(|p| p.data.clone()); + } + let mut roll = rand::rng().random_range(0..total_weight); + for loot in &self.loot_tables_to_eject { + let weight = loot.weight.max(1); + if roll < weight { + return Some(loot.data.clone()); + } + roll -= weight; + } + self.loot_tables_to_eject.first().map(|p| p.data.clone()) + } + + #[must_use] + pub fn from_nbt(nbt: &NbtCompound) -> Self { + let mut cfg = Self::default(); + + if let Some(v) = nbt.get_int("spawn_range") { + cfg.spawn_range = v; + } + if let Some(v) = nbt + .get_float("total_mobs") + .or_else(|| nbt.get_double("total_mobs").map(|d| d as f32)) + .or_else(|| nbt.get_int("total_mobs").map(|i| i as f32)) + { + cfg.total_mobs = v; + } + if let Some(v) = nbt + .get_float("simultaneous_mobs") + .or_else(|| nbt.get_double("simultaneous_mobs").map(|d| d as f32)) + .or_else(|| nbt.get_int("simultaneous_mobs").map(|i| i as f32)) + { + cfg.simultaneous_mobs = v; + } + if let Some(v) = nbt + .get_float("total_mobs_added_per_player") + .or_else(|| { + nbt.get_double("total_mobs_added_per_player") + .map(|d| d as f32) + }) + .or_else(|| nbt.get_int("total_mobs_added_per_player").map(|i| i as f32)) + { + cfg.total_mobs_added_per_player = v; + } + if let Some(v) = nbt + .get_float("simultaneous_mobs_added_per_player") + .or_else(|| { + nbt.get_double("simultaneous_mobs_added_per_player") + .map(|d| d as f32) + }) + .or_else(|| { + nbt.get_int("simultaneous_mobs_added_per_player") + .map(|i| i as f32) + }) + { + cfg.simultaneous_mobs_added_per_player = v; + } + if let Some(v) = nbt.get_int("ticks_between_spawn") { + cfg.ticks_between_spawn = v; + } + + if let Some(list) = nbt.get_list("spawn_potentials") { + let potentials: Vec = list + .iter() + .filter_map(|tag| { + let compound = tag.extract_compound()?; + let data_compound = compound.get_compound("data")?; + let weight = compound.get_int("weight").unwrap_or(1); + Some(WeightedSpawnData { + data: SpawnData::from_nbt(data_compound), + weight, + }) + }) + .collect(); + if !potentials.is_empty() { + cfg.spawn_potentials = potentials; + } + } + + if let Some(list) = nbt.get_list("loot_tables_to_eject") { + cfg.loot_tables_to_eject = list + .iter() + .filter_map(|tag| { + let compound = tag.extract_compound()?; + let data = compound.get_string("data")?.to_string(); + let weight = compound.get_int("weight").unwrap_or(1); + Some(WeightedLootTable { data, weight }) + }) + .collect(); + } + + if let Some(drop) = nbt.get_string("items_to_drop_when_ominous") { + cfg.items_to_drop_when_ominous = Some(drop.to_string()); + } + + cfg + } + + pub fn write_nbt(&self, nbt: &mut NbtCompound) { + nbt.put_int("spawn_range", self.spawn_range); + nbt.put_float("total_mobs", self.total_mobs); + nbt.put_float("simultaneous_mobs", self.simultaneous_mobs); + nbt.put_float( + "total_mobs_added_per_player", + self.total_mobs_added_per_player, + ); + nbt.put_float( + "simultaneous_mobs_added_per_player", + self.simultaneous_mobs_added_per_player, + ); + nbt.put_int("ticks_between_spawn", self.ticks_between_spawn); + + let mut potentials_list = Vec::new(); + for pot in &self.spawn_potentials { + let mut pot_cmp = NbtCompound::new(); + pot_cmp.put_int("weight", pot.weight); + let mut data_cmp = NbtCompound::new(); + pot.data.write_nbt(&mut data_cmp); + pot_cmp.put_compound("data", data_cmp); + potentials_list.push(NbtTag::Compound(pot_cmp)); + } + nbt.put("spawn_potentials", NbtTag::List(potentials_list)); + + if !self.loot_tables_to_eject.is_empty() { + let mut loot_list = Vec::new(); + for loot in &self.loot_tables_to_eject { + let mut loot_cmp = NbtCompound::new(); + loot_cmp.put_string("data", loot.data.clone()); + loot_cmp.put_int("weight", loot.weight); + loot_list.push(NbtTag::Compound(loot_cmp)); + } + nbt.put("loot_tables_to_eject", NbtTag::List(loot_list)); + } + + if let Some(drop) = &self.items_to_drop_when_ominous { + nbt.put_string("items_to_drop_when_ominous", drop.clone()); + } + } +} + +/// Combined normal and ominous configuration with shared range and cooldown parameters. +#[derive(Clone, Debug)] +pub struct TrialSpawnerFullConfig { + pub normal: TrialSpawnerConfig, + pub ominous: TrialSpawnerConfig, + pub target_cooldown_length: i64, + pub required_player_range: i32, +} + +impl Default for TrialSpawnerFullConfig { + fn default() -> Self { + Self { + normal: TrialSpawnerConfig::default(), + ominous: TrialSpawnerConfig::default(), + target_cooldown_length: 36000, + required_player_range: 14, + } + } +} + +impl TrialSpawnerFullConfig { + #[must_use] + pub fn override_entity(&self, entity_type: &'static EntityType) -> Self { + Self { + normal: self.normal.with_spawning(entity_type), + ominous: self.ominous.with_spawning(entity_type), + target_cooldown_length: self.target_cooldown_length, + required_player_range: self.required_player_range, + } + } + + #[must_use] + pub fn from_nbt(nbt: &NbtCompound) -> Self { + let normal = nbt + .get_compound("normal_config") + .map(TrialSpawnerConfig::from_nbt) + .unwrap_or_default(); + let ominous = nbt + .get_compound("ominous_config") + .map(TrialSpawnerConfig::from_nbt) + .unwrap_or_default(); + + let target_cooldown_length = nbt + .get_long("target_cooldown_length") + .or_else(|| nbt.get_int("target_cooldown_length").map(i64::from)) + .unwrap_or(36000); + + let required_player_range = nbt.get_int("required_player_range").unwrap_or(14); + + Self { + normal, + ominous, + target_cooldown_length, + required_player_range, + } + } + + pub fn write_nbt(&self, nbt: &mut NbtCompound) { + let mut normal_cmp = NbtCompound::new(); + self.normal.write_nbt(&mut normal_cmp); + nbt.put_compound("normal_config", normal_cmp); + + let mut ominous_cmp = NbtCompound::new(); + self.ominous.write_nbt(&mut ominous_cmp); + nbt.put_compound("ominous_config", ominous_cmp); + + nbt.put_long("target_cooldown_length", self.target_cooldown_length); + nbt.put_int("required_player_range", self.required_player_range); + } +} + +/// Dynamic state data tracking current progress of a trial spawner. +#[derive(Clone, Debug, Default)] +pub struct TrialSpawnerStateData { + pub registered_players: FxHashSet, + pub current_mobs: FxHashSet, + pub cooldown_ends_at: i64, + pub next_mob_spawns_at: i64, + pub total_mobs_spawned: i32, + pub next_spawn_data: Option, + pub ejecting_loot_table: Option, +} + +impl TrialSpawnerStateData { + pub fn reset(&mut self) { + self.registered_players.clear(); + self.current_mobs.clear(); + self.total_mobs_spawned = 0; + self.next_mob_spawns_at = 0; + self.cooldown_ends_at = 0; + self.next_spawn_data = None; + self.ejecting_loot_table = None; + } + + pub fn reset_after_becoming_ominous(&mut self, game_time: i64) { + self.current_mobs.clear(); + self.next_mob_spawns_at = game_time + TrialSpawner::DETECT_PLAYER_SPAWN_BUFFER; + self.total_mobs_spawned = 0; + self.next_spawn_data = None; + } + + #[must_use] + pub fn has_mob_to_spawn(&self, config: &TrialSpawnerConfig) -> bool { + if self + .next_spawn_data + .as_ref() + .and_then(|d| d.entity_type) + .is_some() + { + return true; + } + !config.spawn_potentials.is_empty() + } + + pub fn get_or_create_next_spawn_data( + &mut self, + config: &TrialSpawnerConfig, + ) -> Option<&SpawnData> { + if self.next_spawn_data.is_none() { + self.next_spawn_data = config.pick_spawn_data(); + } + self.next_spawn_data.as_ref() + } + + pub fn try_detect_players( + &mut self, + world: &World, + spawner_pos: BlockPos, + range: i32, + detector: &PlayerDetector, + ) -> bool { + let detected = detector.detect(world, spawner_pos, range); + let mut newly_detected = false; + for uuid in detected { + if self.registered_players.insert(uuid) { + newly_detected = true; + } + } + newly_detected + } + + #[must_use] + pub fn from_nbt(nbt: &NbtCompound) -> Self { + let mut data = Self::default(); + + let read_uuid_list = |name: &str| -> FxHashSet { + let mut set = FxHashSet::default(); + if let Some(list) = nbt.get_list(name) { + for tag in list { + match tag { + NbtTag::IntArray(arr) if arr.len() == 4 => { + let value = ((arr[0] as u128) << 96) + | (((arr[1] as u32) as u128) << 64) + | (((arr[2] as u32) as u128) << 32) + | ((arr[3] as u32) as u128); + set.insert(Uuid::from_u128(value)); + } + NbtTag::String(s) => { + if let Ok(uuid) = Uuid::parse_str(s) { + set.insert(uuid); + } + } + _ => {} + } + } + } + set + }; + + data.registered_players = read_uuid_list("registered_players"); + data.current_mobs = read_uuid_list("current_mobs"); + + if let Some(v) = nbt + .get_long("cooldown_ends_at") + .or_else(|| nbt.get_int("cooldown_ends_at").map(i64::from)) + { + data.cooldown_ends_at = v; + } + + if let Some(v) = nbt + .get_long("next_mob_spawns_at") + .or_else(|| nbt.get_int("next_mob_spawns_at").map(i64::from)) + { + data.next_mob_spawns_at = v; + } + + if let Some(v) = nbt.get_int("total_mobs_spawned") { + data.total_mobs_spawned = v; + } + + if let Some(spawn_data_cmp) = nbt.get_compound("spawn_data") { + data.next_spawn_data = Some(SpawnData::from_nbt(spawn_data_cmp)); + } + + if let Some(loot) = nbt.get_string("ejecting_loot_table") { + data.ejecting_loot_table = Some(loot.to_string()); + } + + data + } + + pub fn write_nbt(&self, nbt: &mut NbtCompound) { + let write_uuid_list = |set: &FxHashSet| -> Vec { + set.iter() + .map(|u| { + let value = u.as_u128(); + NbtTag::IntArray(vec![ + (value >> 96) as i32, + ((value >> 64) & 0xFFFF_FFFF) as i32, + ((value >> 32) & 0xFFFF_FFFF) as i32, + (value & 0xFFFF_FFFF) as i32, + ]) + }) + .collect() + }; + + nbt.put( + "registered_players", + NbtTag::List(write_uuid_list(&self.registered_players)), + ); + nbt.put( + "current_mobs", + NbtTag::List(write_uuid_list(&self.current_mobs)), + ); + nbt.put_long("cooldown_ends_at", self.cooldown_ends_at); + nbt.put_long("next_mob_spawns_at", self.next_mob_spawns_at); + nbt.put_int("total_mobs_spawned", self.total_mobs_spawned); + + if let Some(spawn_data) = &self.next_spawn_data { + let mut spawn_cmp = NbtCompound::new(); + spawn_data.write_nbt(&mut spawn_cmp); + nbt.put_compound("spawn_data", spawn_cmp); + } + + if let Some(loot) = &self.ejecting_loot_table { + nbt.put_string("ejecting_loot_table", loot.clone()); + } + } +} + +/// Core Trial Spawner engine and state machine logic. +#[derive(Default)] +pub struct TrialSpawner { + pub data: TrialSpawnerStateData, + pub config: TrialSpawnerFullConfig, + pub player_detector: PlayerDetector, + pub override_peaceful_and_mob_spawn_rule: bool, + pub is_ominous: bool, +} + +impl TrialSpawner { + pub const DETECT_PLAYER_SPAWN_BUFFER: i64 = 40; + pub const DEFAULT_TARGET_COOLDOWN_LENGTH: i64 = 36000; + pub const DEFAULT_PLAYER_SCAN_RANGE: i32 = 14; + pub const MAX_MOB_TRACKING_DISTANCE: f64 = 47.0; + pub const MAX_MOB_TRACKING_DISTANCE_SQR: f64 = 47.0 * 47.0; + pub const SPAWNING_AMBIENT_SOUND_CHANCE: f32 = 0.02; + + #[must_use] + pub fn new(config: TrialSpawnerFullConfig, player_detector: PlayerDetector) -> Self { + Self { + data: TrialSpawnerStateData::default(), + config, + player_detector, + override_peaceful_and_mob_spawn_rule: false, + is_ominous: false, + } + } + + #[must_use] + pub const fn active_config(&self) -> &TrialSpawnerConfig { + if self.is_ominous { + &self.config.ominous + } else { + &self.config.normal + } + } + + #[must_use] + pub const fn normal_config(&self) -> &TrialSpawnerConfig { + &self.config.normal + } + + #[must_use] + pub const fn ominous_config(&self) -> &TrialSpawnerConfig { + &self.config.ominous + } + + pub fn load(&mut self, nbt: &NbtCompound) { + if let Some(spawner_data_cmp) = nbt.get_compound("spawner_data") { + self.data = TrialSpawnerStateData::from_nbt(spawner_data_cmp); + } else { + self.data = TrialSpawnerStateData::from_nbt(nbt); + } + self.config = TrialSpawnerFullConfig::from_nbt(nbt); + } + + pub fn store(&self, nbt: &mut NbtCompound) { + self.config.write_nbt(nbt); + self.data.write_nbt(nbt); + } + + pub fn apply_ominous(&mut self, world: &Arc, spawner_pos: BlockPos) { + self.set_ominous(world, spawner_pos, true); + world.sync_world_event( + WorldEvent::ParticlesTrialSpawnerBecomeOminous, + spawner_pos, + 1, + ); + self.is_ominous = true; + let game_time = world + .level_time + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner) + .query_gametime(); + self.data.reset_after_becoming_ominous(game_time); + } + + pub fn remove_ominous(&mut self, world: &Arc, spawner_pos: BlockPos) { + self.set_ominous(world, spawner_pos, false); + self.is_ominous = false; + } + + #[must_use] + pub const fn is_ominous(&self) -> bool { + self.is_ominous + } + + #[must_use] + pub const fn target_cooldown_length(&self) -> i64 { + self.config.target_cooldown_length + } + + #[must_use] + pub const fn required_player_range(&self) -> i32 { + self.config.required_player_range + } + + pub fn get_state(&self, world: &World, spawner_pos: BlockPos) -> TrialSpawnerState { + let block_id = world.get_block_state_id(&spawner_pos); + let block = world.get_block(&spawner_pos); + if block.id == pumpkin_data::BlockId::TRIAL_SPAWNER { + TrialSpawnerLikeProperties::from_state_id(block_id, block).trial_spawner_state + } else { + TrialSpawnerState::Inactive + } + } + + pub fn set_state(&self, world: &Arc, spawner_pos: BlockPos, state: TrialSpawnerState) { + let block_id = world.get_block_state_id(&spawner_pos); + let block = world.get_block(&spawner_pos); + if block.id == pumpkin_data::BlockId::TRIAL_SPAWNER { + let mut props = TrialSpawnerLikeProperties::from_state_id(block_id, block); + if props.trial_spawner_state != state { + props.trial_spawner_state = state; + world.set_block_state( + &spawner_pos, + props.to_state_id(block), + pumpkin_world::world::BlockFlags::NOTIFY_ALL, + ); + } + } + } + + pub fn set_ominous(&self, world: &Arc, spawner_pos: BlockPos, ominous: bool) { + let block_id = world.get_block_state_id(&spawner_pos); + let block = world.get_block(&spawner_pos); + if block.id == pumpkin_data::BlockId::TRIAL_SPAWNER { + let mut props = TrialSpawnerLikeProperties::from_state_id(block_id, block); + if props.ominous != ominous { + props.ominous = ominous; + world.set_block_state( + &spawner_pos, + props.to_state_id(block), + pumpkin_world::world::BlockFlags::NOTIFY_ALL, + ); + } + } + } + + #[must_use] + pub fn can_spawn_in_level(&self, world: &World) -> bool { + let level_info = world.level_info.load(); + if !level_info.game_rules.spawner_blocks_work { + return false; + } + if self.override_peaceful_and_mob_spawn_rule { + return true; + } + if level_info.difficulty == Difficulty::Peaceful { + return false; + } + level_info.game_rules.spawn_mobs + } + + pub fn spawn_mob(&mut self, world: &Arc, spawner_pos: BlockPos) -> Option { + let (entity_type, spawn_range) = { + let active_cfg = if self.is_ominous { + &self.config.ominous + } else { + &self.config.normal + }; + let spawn_data = self.data.get_or_create_next_spawn_data(active_cfg); + let ent_type = spawn_data.and_then(|sd| sd.entity_type)?; + (ent_type, active_cfg.spawn_range) + }; + + let mut rng = rand::rng(); + + let mut chosen_pos = None; + for _ in 0..20 { + let spawn_pos = Vector3::new( + f64::from(spawner_pos.0.x) + + (rng.random::() - rng.random::()) * f64::from(spawn_range) + + 0.5, + f64::from(spawner_pos.0.y + rng.random_range(0..3) - 1), + f64::from(spawner_pos.0.z) + + (rng.random::() - rng.random::()) * f64::from(spawn_range) + + 0.5, + ); + + let bb = entity_type.get_spawn_bounding_box(spawn_pos.x, spawn_pos.y, spawn_pos.z); + if !world.is_space_empty(bb) { + continue; + } + + let center = spawner_pos.to_centered_f64(); + if !Self::in_line_of_sight(world, center, spawn_pos) { + continue; + } + + chosen_pos = Some(spawn_pos); + break; + } + + let spawn_pos = chosen_pos?; + let entity_uuid = Uuid::new_v4(); + let entity = crate::entity::r#type::from_type(entity_type, spawn_pos, world, entity_uuid); + + let yaw = rng.random::() * 360.0; + entity.get_entity().set_rotation(yaw, 0.0); + + let mut event = + crate::plugin::api::events::entity::trial_spawner_spawn::TrialSpawnerSpawnEvent::new( + entity.get_entity().entity_id, + spawner_pos, + ); + if let Some(server) = world.server.upgrade() { + server.plugin_manager.fire_blocking(&server, &mut event); + } + if event.cancelled { + return None; + } + + world.spawn_entity(entity); + + let flame_data = i32::from(self.is_ominous); + world.sync_world_event( + WorldEvent::ParticlesTrialSpawnerSpawn, + spawner_pos, + flame_data, + ); + let spawn_block_pos = BlockPos::floored(spawn_pos.x, spawn_pos.y, spawn_pos.z); + world.sync_world_event( + WorldEvent::ParticlesTrialSpawnerSpawnMobAt, + spawn_block_pos, + flame_data, + ); + + Some(entity_uuid) + } + + fn in_line_of_sight(world: &Arc, origin: Vector3, dest: Vector3) -> bool { + let origin_block = BlockPos::floored(origin.x, origin.y, origin.z); + let hit = world.raycast(dest, origin, |pos, w| { + let state = w.get_block_state(pos); + !state.is_air() && !state.sided_transparency() + }); + match hit { + None => true, + Some((hit_pos, _)) => hit_pos == origin_block, + } + } + + pub fn eject_reward( + &self, + world: &Arc, + spawner_pos: BlockPos, + ejecting_loot_table: Option<&str>, + ) { + let mut dropped_any = false; + if let Some(key) = ejecting_loot_table + && let Some(loot_table) = pumpkin_data::chest_loot_table::get_chest_loot_table(key) + { + let seed = rand::random::(); + let items = crate::world::loot::generate_chest_loot(loot_table, seed); + for stack in items { + world.drop_stack(&spawner_pos, stack); + dropped_any = true; + } + } + + if !dropped_any { + let key_item = if self.is_ominous { + &Item::OMINOUS_TRIAL_KEY + } else { + &Item::TRIAL_KEY + }; + world.drop_stack(&spawner_pos, ItemStack::new(1, key_item)); + } + + world.sync_world_event(WorldEvent::AnimationTrialSpawnerEjectItem, spawner_pos, 0); + } + + pub fn tick_server(&mut self, world: &Arc, spawner_pos: BlockPos, is_ominous: bool) { + self.is_ominous = is_ominous; + let current_state = self.get_state(world, spawner_pos); + + let max_dist_sq = Self::MAX_MOB_TRACKING_DISTANCE_SQR; + let center = spawner_pos.to_centered_f64(); + let mut removed = false; + self.data.current_mobs.retain(|id| { + if let Some(entity) = world.get_entity_by_uuid(*id) { + let ent = entity.get_entity(); + if ent.is_alive() && ent.pos.load().squared_distance_to_vec(¢er) <= max_dist_sq + { + return true; + } + } + removed = true; + false + }); + + if removed { + let game_time = world + .level_time + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner) + .query_gametime(); + self.data.next_mob_spawns_at = + game_time + i64::from(self.active_config().ticks_between_spawn); + } + + let next_state = self.tick_and_get_next(world, spawner_pos, current_state); + if next_state != current_state { + self.set_state(world, spawner_pos, next_state); + } + } + + #[allow(clippy::too_many_lines)] + fn tick_and_get_next( + &mut self, + world: &Arc, + spawner_pos: BlockPos, + current_state: TrialSpawnerState, + ) -> TrialSpawnerState { + let game_time = world + .level_time + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner) + .query_gametime(); + let can_spawn = self.can_spawn_in_level(world); + let has_mob = self.data.has_mob_to_spawn(self.active_config()); + + match current_state { + TrialSpawnerState::Inactive => { + if can_spawn && has_mob { + TrialSpawnerState::WaitingForPlayers + } else { + TrialSpawnerState::Inactive + } + } + TrialSpawnerState::WaitingForPlayers => { + if !can_spawn || !has_mob { + return TrialSpawnerState::Inactive; + } + + let newly_detected = self.data.try_detect_players( + world, + spawner_pos, + self.config.required_player_range, + &self.player_detector, + ); + + if self.data.registered_players.is_empty() { + TrialSpawnerState::WaitingForPlayers + } else { + if newly_detected { + let player_count = self.data.registered_players.len() as i32; + let event = if self.is_ominous { + WorldEvent::ParticlesTrialSpawnerDetectPlayerOminous + } else { + WorldEvent::ParticlesTrialSpawnerDetectPlayer + }; + world.sync_world_event(event, spawner_pos, player_count); + world.play_sound( + Sound::BlockTrialSpawnerDetectPlayer, + SoundCategory::Blocks, + &spawner_pos.to_f64(), + ); + world.play_sound( + Sound::BlockTrialSpawnerOpenShutter, + SoundCategory::Blocks, + &spawner_pos.to_f64(), + ); + self.data.next_mob_spawns_at = game_time + Self::DETECT_PLAYER_SPAWN_BUFFER; + } + TrialSpawnerState::Active + } + } + TrialSpawnerState::Active => { + if !can_spawn || !has_mob { + return TrialSpawnerState::Inactive; + } + + self.data.try_detect_players( + world, + spawner_pos, + self.config.required_player_range, + &self.player_detector, + ); + + let (total_mobs_needed, max_simultaneous, ticks_between_spawn) = { + let active_config = self.active_config(); + ( + active_config + .calculate_target_total_mobs(self.data.registered_players.len()), + active_config + .calculate_target_simultaneous_mobs(self.data.registered_players.len()), + active_config.ticks_between_spawn, + ) + }; + + if self.data.total_mobs_spawned >= total_mobs_needed + && self.data.current_mobs.is_empty() + { + self.data.cooldown_ends_at = game_time + self.config.target_cooldown_length; + self.data.total_mobs_spawned = 0; + self.data.ejecting_loot_table = self.active_config().pick_loot_table(); + self.data.next_mob_spawns_at = game_time + 40; + TrialSpawnerState::WaitingForRewardEjection + } else { + if self.data.total_mobs_spawned < total_mobs_needed + && (self.data.current_mobs.len() as i32) < max_simultaneous + && game_time >= self.data.next_mob_spawns_at + && let Some(uuid) = self.spawn_mob(world, spawner_pos) + { + self.data.current_mobs.insert(uuid); + self.data.total_mobs_spawned += 1; + self.data.next_mob_spawns_at = game_time + i64::from(ticks_between_spawn); + } + TrialSpawnerState::Active + } + } + TrialSpawnerState::WaitingForRewardEjection => { + if game_time >= self.data.next_mob_spawns_at { + world.play_sound( + Sound::BlockTrialSpawnerSpawnItemBegin, + SoundCategory::Blocks, + &spawner_pos.to_f64(), + ); + self.data.next_mob_spawns_at = game_time + 20; + TrialSpawnerState::EjectingReward + } else { + TrialSpawnerState::WaitingForRewardEjection + } + } + TrialSpawnerState::EjectingReward => { + if game_time >= self.data.next_mob_spawns_at { + self.eject_reward(world, spawner_pos, self.data.ejecting_loot_table.as_deref()); + world.play_sound( + Sound::BlockTrialSpawnerEjectItem, + SoundCategory::Blocks, + &spawner_pos.to_f64(), + ); + world.play_sound( + Sound::BlockTrialSpawnerCloseShutter, + SoundCategory::Blocks, + &spawner_pos.to_f64(), + ); + self.data.next_mob_spawns_at = game_time + 20; + TrialSpawnerState::Cooldown + } else { + TrialSpawnerState::EjectingReward + } + } + TrialSpawnerState::Cooldown => { + if game_time >= self.data.cooldown_ends_at { + self.data.reset(); + if self.is_ominous { + self.remove_ominous(world, spawner_pos); + } + TrialSpawnerState::WaitingForPlayers + } else { + TrialSpawnerState::Cooldown + } + } + } + } + + pub fn override_entity_to_spawn( + &mut self, + entity_type: &'static EntityType, + world: &Arc, + spawner_pos: BlockPos, + ) { + self.data.reset(); + self.config = self.config.override_entity(entity_type); + self.set_state(world, spawner_pos, TrialSpawnerState::Inactive); + } + + pub const fn set_player_detector(&mut self, player_detector: PlayerDetector) { + self.player_detector = player_detector; + } + + pub const fn override_peaceful_and_mob_spawn_rule(&mut self) { + self.override_peaceful_and_mob_spawn_rule = true; + } +} pub struct TrialSpawnerBlockEntity { pub position: BlockPos, - pub normal_config: Mutex>, - pub ominous_config: Mutex>, - pub spawner_data: Mutex>, + pub trial_spawner: Mutex, } impl BlockEntity for TrialSpawnerBlockEntity { @@ -19,54 +1134,44 @@ impl BlockEntity for TrialSpawnerBlockEntity { self.position } - fn from_nbt(nbt: &pumpkin_nbt::compound::NbtCompound, position: BlockPos) -> Self + fn tick(&self, world: &Arc) { + let block_id = world.get_block_state_id(&self.position); + let block = world.get_block(&self.position); + let is_ominous = if block.id == pumpkin_data::BlockId::TRIAL_SPAWNER { + TrialSpawnerLikeProperties::from_state_id(block_id, block).ominous + } else { + false + }; + + if let Ok(mut spawner) = self.trial_spawner.lock() { + spawner.tick_server(world, self.position, is_ominous); + } + } + + fn from_nbt(nbt: &NbtCompound, position: BlockPos) -> Self where Self: Sized, { + let mut spawner = TrialSpawner::default(); + spawner.load(nbt); Self { position, - normal_config: Mutex::new(nbt.get_compound("normal_config").cloned()), - ominous_config: Mutex::new(nbt.get_compound("ominous_config").cloned()), - spawner_data: Mutex::new(nbt.get_compound("spawner_data").cloned()), + trial_spawner: Mutex::new(spawner), } } fn write_nbt(&self, nbt: &mut NbtCompound) { - if let Ok(cfg) = self.normal_config.lock() - && let Some(cfg) = cfg.as_ref() - { - nbt.put_compound("normal_config", cfg.clone()); - } - if let Ok(cfg) = self.ominous_config.lock() - && let Some(cfg) = cfg.as_ref() - { - nbt.put_compound("ominous_config", cfg.clone()); - } - if let Ok(data) = self.spawner_data.lock() - && let Some(data) = data.as_ref() - { - nbt.put_compound("spawner_data", data.clone()); + if let Ok(spawner) = self.trial_spawner.lock() { + spawner.store(nbt); } } fn chunk_data_nbt(&self) -> Option { - let mut nbt = NbtCompound::new(); - if let Ok(cfg) = self.normal_config.try_lock() - && let Some(ref cfg) = *cfg - { - nbt.put_compound("normal_config", cfg.clone()); - } - if let Ok(cfg) = self.ominous_config.try_lock() - && let Some(ref cfg) = *cfg - { - nbt.put_compound("ominous_config", cfg.clone()); - } - if let Ok(data) = self.spawner_data.try_lock() - && let Some(ref data) = *data - { - nbt.put_compound("spawner_data", data.clone()); - } - Some(nbt) + self.trial_spawner.try_lock().ok().map(|spawner| { + let mut nbt = NbtCompound::new(); + spawner.store(&mut nbt); + nbt + }) } fn as_any(&self) -> &dyn std::any::Any { @@ -76,13 +1181,63 @@ impl BlockEntity for TrialSpawnerBlockEntity { impl TrialSpawnerBlockEntity { pub const ID: &'static str = "minecraft:trial_spawner"; + #[must_use] - pub const fn new(position: BlockPos) -> Self { + pub fn new(position: BlockPos) -> Self { Self { position, - normal_config: Mutex::new(None), - ominous_config: Mutex::new(None), - spawner_data: Mutex::new(None), + trial_spawner: Mutex::new(TrialSpawner::default()), } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn trial_spawner_config_scaling() { + let config = TrialSpawnerConfig { + total_mobs: 6.0, + simultaneous_mobs: 2.0, + total_mobs_added_per_player: 2.0, + simultaneous_mobs_added_per_player: 1.0, + ..Default::default() + }; + + // 1 player + assert_eq!(config.calculate_target_total_mobs(1), 6); + assert_eq!(config.calculate_target_simultaneous_mobs(1), 2); + + // 2 players + assert_eq!(config.calculate_target_total_mobs(2), 8); + assert_eq!(config.calculate_target_simultaneous_mobs(2), 3); + + // 3 players + assert_eq!(config.calculate_target_total_mobs(3), 10); + assert_eq!(config.calculate_target_simultaneous_mobs(3), 4); + } + + #[test] + fn trial_spawner_nbt_roundtrip() { + let mut original = TrialSpawner::default(); + let test_uuid = Uuid::new_v4(); + original.data.registered_players.insert(test_uuid); + original.data.total_mobs_spawned = 3; + original.data.cooldown_ends_at = 12345; + original.config.target_cooldown_length = 36000; + original.config.required_player_range = 14; + + let mut nbt = NbtCompound::new(); + original.store(&mut nbt); + + let mut loaded = TrialSpawner::default(); + loaded.load(&nbt); + + assert_eq!(loaded.data.total_mobs_spawned, 3); + assert_eq!(loaded.data.cooldown_ends_at, 12345); + assert_eq!(loaded.config.target_cooldown_length, 36000); + assert_eq!(loaded.config.required_player_range, 14); + assert!(loaded.data.registered_players.contains(&test_uuid)); + } +} diff --git a/crates/pumpkin/src/block/entities/vault.rs b/crates/pumpkin/src/block/entities/vault.rs index 40465389b..b407c7942 100644 --- a/crates/pumpkin/src/block/entities/vault.rs +++ b/crates/pumpkin/src/block/entities/vault.rs @@ -1,7 +1,7 @@ use super::BlockEntity; use pumpkin_nbt::compound::NbtCompound; use pumpkin_util::math::position::BlockPos; -use std::collections::HashSet; +use rustc_hash::FxHashSet; use std::sync::Mutex; use uuid::Uuid; @@ -9,7 +9,7 @@ pub struct VaultBlockEntity { pub position: BlockPos, pub config: Mutex>, pub server_data: Mutex>, - pub rewarded_players: Mutex>, + pub rewarded_players: Mutex>, } impl BlockEntity for VaultBlockEntity { @@ -29,7 +29,7 @@ impl BlockEntity for VaultBlockEntity { position, config: Mutex::new(nbt.get_compound("config").cloned()), server_data: Mutex::new(nbt.get_compound("server_data").cloned()), - rewarded_players: Mutex::new(HashSet::new()), + rewarded_players: Mutex::new(FxHashSet::default()), } } @@ -75,7 +75,7 @@ impl VaultBlockEntity { position, config: Mutex::new(None), server_data: Mutex::new(None), - rewarded_players: Mutex::new(HashSet::new()), + rewarded_players: Mutex::new(FxHashSet::default()), } } diff --git a/crates/pumpkin/src/command/args/gameprofile.rs b/crates/pumpkin/src/command/args/gameprofile.rs index 5733b7552..27d8e7aea 100644 --- a/crates/pumpkin/src/command/args/gameprofile.rs +++ b/crates/pumpkin/src/command/args/gameprofile.rs @@ -14,7 +14,7 @@ use crate::{ dispatcher::CommandError, tree::{RawArg, RawArgs}, }, - net::authentication::lookup_profile_by_name, + net::authentication::lookup_profile_by_name_blocking, net::{GameProfile, offline_uuid}, server::Server, }; @@ -254,7 +254,7 @@ fn resolve_profiles_from_token( } if server.advanced_config.networking.java.online_mode { - match lookup_profile_by_name( + match lookup_profile_by_name_blocking( raw_arg.value, &server.advanced_config.networking.java.authentication, ) { diff --git a/crates/pumpkin/src/command/argument_types/game_profile.rs b/crates/pumpkin/src/command/argument_types/game_profile.rs index d1634a466..31da71fbd 100644 --- a/crates/pumpkin/src/command/argument_types/game_profile.rs +++ b/crates/pumpkin/src/command/argument_types/game_profile.rs @@ -10,7 +10,7 @@ use crate::command::errors::command_syntax_error::CommandSyntaxError; use crate::command::errors::error_types::CommandErrorType; use crate::command::string_reader::StringReader; use crate::command::suggestion::suggestions::{Suggestions, SuggestionsBuilder}; -use crate::net::authentication::lookup_profile_by_name; +use crate::net::authentication::lookup_profile_by_name_blocking; use crate::net::{GameProfile, offline_uuid}; use crate::server::Server; use arc_swap::ArcSwap; @@ -72,7 +72,7 @@ impl GameProfileResult { } if server.advanced_config.networking.java.online_mode { - return match lookup_profile_by_name( + return match lookup_profile_by_name_blocking( name, &server.advanced_config.networking.java.authentication, ) { diff --git a/crates/pumpkin/src/command/commands/fetchprofile.rs b/crates/pumpkin/src/command/commands/fetchprofile.rs index c69a9fac2..e46a04a30 100644 --- a/crates/pumpkin/src/command/commands/fetchprofile.rs +++ b/crates/pumpkin/src/command/commands/fetchprofile.rs @@ -142,7 +142,7 @@ fn report_resolved_profile( source.send_feedback(msg, false); } -fn fetch_profile_by_name_helper(server: &Server, name: &str) -> Option { +async fn fetch_profile_by_name_helper(server: &Server, name: &str) -> Option { if let Some(player) = server.get_player_by_name(name) { return Some(player.gameprofile.clone()); } @@ -155,7 +155,10 @@ fn fetch_profile_by_name_helper(server: &Server, name: &str) -> Option Option Option Option { +async fn fetch_profile_by_id_helper(server: &Server, id: Uuid) -> Option { if let Some(player) = server.get_player_by_uuid(id) { return Some(player.gameprofile.clone()); } @@ -223,7 +227,7 @@ fn fetch_profile_by_id_helper(server: &Server, id: Uuid) -> Option .java .authentication .clone(); - let mojang_res = fetch_profile_by_uuid(id, &auth_config).ok().flatten(); + let mojang_res = fetch_profile_by_uuid(id, &auth_config).await.ok().flatten(); if let Some(profile) = mojang_res { server @@ -258,8 +262,8 @@ impl CommandExecutor for ResolveNameExecutor { let name_owned = name.to_string(); let name_component = TextComponent::text(name_owned.clone()); - rayon::spawn(move || { - let result = fetch_profile_by_name_helper(&server, &name_owned); + tokio::spawn(async move { + let result = fetch_profile_by_name_helper(&server, &name_owned).await; match result { Some(profile) => { report_resolved_profile( @@ -292,8 +296,8 @@ impl CommandExecutor for ResolveIdExecutor { let source = context.source.clone(); let id_component = TextComponent::text(id.to_string()); - rayon::spawn(move || { - let result = fetch_profile_by_id_helper(&server, id); + tokio::spawn(async move { + let result = fetch_profile_by_id_helper(&server, id).await; match result { Some(profile) => { report_resolved_profile( diff --git a/crates/pumpkin/src/command/commands/fillbiome.rs b/crates/pumpkin/src/command/commands/fillbiome.rs index a55742604..edc5cb176 100644 --- a/crates/pumpkin/src/command/commands/fillbiome.rs +++ b/crates/pumpkin/src/command/commands/fillbiome.rs @@ -13,7 +13,7 @@ use pumpkin_util::PermissionLvl; use pumpkin_util::math::vector2::Vector2; use pumpkin_util::permission::{Permission, PermissionDefault, PermissionRegistry}; use pumpkin_util::text::TextComponent; -use std::collections::HashMap; +use rustc_hash::FxHashMap; const DESCRIPTION: &str = "Changes biomes of an area."; const PERMISSION: &str = "minecraft:command.fillbiome"; @@ -72,8 +72,8 @@ impl CommandExecutor for FillBiomeExecutor { None }; - let mut chunk_modifications: HashMap, Vec<(usize, usize, usize)>> = - HashMap::new(); + let mut chunk_modifications: FxHashMap, Vec<(usize, usize, usize)>> = + FxHashMap::default(); for y in biome_min_y..=biome_max_y { for z in biome_min_z..=biome_max_z { for x in biome_min_x..=biome_max_x { diff --git a/crates/pumpkin/src/command/commands/pumpkin.rs b/crates/pumpkin/src/command/commands/pumpkin.rs index 8a303713e..a071d89ec 100644 --- a/crates/pumpkin/src/command/commands/pumpkin.rs +++ b/crates/pumpkin/src/command/commands/pumpkin.rs @@ -51,7 +51,14 @@ fn fetch_all_contributors_cached() -> Vec { return cache.data.clone(); } - let contributors = fetch_all_contributors(); + let contributors = tokio::runtime::Handle::try_current().map_or_else( + |_| { + tokio::runtime::Runtime::new() + .map_or_else(|_| Vec::new(), |rt| rt.block_on(fetch_all_contributors())) + }, + |handle| tokio::task::block_in_place(|| handle.block_on(fetch_all_contributors())), + ); + if !contributors.is_empty() { if let Ok(mut guard) = CONTRIBUTORS_CACHE.lock() { *guard = Some(ContributorCache { @@ -68,25 +75,35 @@ fn fetch_all_contributors_cached() -> Vec { contributors } -fn fetch_all_contributors() -> Vec { +async fn fetch_all_contributors() -> Vec { + let client = reqwest::Client::builder() + .user_agent("Pumpkin-MC") + .build() + .unwrap_or_default(); + let mut all_contributors = Vec::new(); let mut next_url = Some( "https://api.github.com/repos/Pumpkin-MC/Pumpkin/contributors?per_page=100".to_string(), ); while let Some(url) = next_url { - let response = ureq::get(&url).header("User-Agent", "Pumpkin-MC").call(); + let response = client.get(&url).send().await; match response { - Ok(mut res) => { - if let Ok(contributors) = res.body_mut().read_json::>() { + Ok(res) => { + let link_header = res + .headers() + .get("link") + .and_then(|s| s.to_str().ok()) + .map(String::from); + + if let Ok(contributors) = res.json::>().await { all_contributors.extend(contributors); } else { break; } - let link_header = res.headers().get("link").map(|s| s.to_str().unwrap_or("")); - next_url = link_header.and_then(extract_next_url); + next_url = link_header.as_deref().and_then(extract_next_url); } Err(_) => break, } @@ -172,14 +189,18 @@ fn tier_color(tier_slug: &str, tier_name: &str) -> NamedColor { } } -fn fetch_donators_hover() -> TextComponent { +async fn fetch_donators_hover() -> TextComponent { let url = "https://market.pumpkinmc.org/api/v1/rest/donators"; - let response = ureq::get(url).header("User-Agent", "Pumpkin-MC").call(); + let client = reqwest::Client::builder() + .user_agent("Pumpkin-MC") + .build() + .unwrap_or_default(); + let response = client.get(url).send().await; let mut donators_text = TextComponent::text("Click to open Donate\n\nDonators:\n"); - if let Ok(mut res) = response - && let Ok(data) = res.body_mut().read_json::() + if let Ok(res) = response + && let Ok(data) = res.json::().await { let mut current = data.current; current.sort_by(|a, b| { @@ -225,7 +246,16 @@ fn fetch_donators_hover_cached() -> TextComponent { return cache.data.clone(); } - let donators = fetch_donators_hover(); + let donators = tokio::runtime::Handle::try_current().map_or_else( + |_| { + tokio::runtime::Runtime::new().map_or_else( + |_| TextComponent::text("Unable to load donators"), + |rt| rt.block_on(fetch_donators_hover()), + ) + }, + |handle| tokio::task::block_in_place(|| handle.block_on(fetch_donators_hover())), + ); + if let Ok(mut guard) = DONATORS_CACHE.lock() { *guard = Some(DonatorCache { fetched_at: Instant::now(), diff --git a/crates/pumpkin/src/data/usercache.rs b/crates/pumpkin/src/data/usercache.rs index ac5f3879e..78b93e3d2 100644 --- a/crates/pumpkin/src/data/usercache.rs +++ b/crates/pumpkin/src/data/usercache.rs @@ -1,5 +1,5 @@ +use rustc_hash::FxHashMap; use std::cmp::Reverse; -use std::collections::HashMap; use std::{env, fs}; use serde::{Deserialize, Serialize}; @@ -29,8 +29,8 @@ struct UserCacheEntryDisk { #[derive(Default)] pub struct UserCache { - profiles_by_name: HashMap, - profiles_by_uuid: HashMap, + profiles_by_name: FxHashMap, + profiles_by_uuid: FxHashMap, operation_count: u64, } diff --git a/crates/pumpkin/src/entity/attributes.rs b/crates/pumpkin/src/entity/attributes.rs index 87856dfd4..664530c86 100644 --- a/crates/pumpkin/src/entity/attributes.rs +++ b/crates/pumpkin/src/entity/attributes.rs @@ -1,6 +1,6 @@ use pumpkin_data::attributes::Attributes; use pumpkin_data::entity::EntityType; -use std::collections::HashMap; +use rustc_hash::FxHashMap; use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicU64; use std::sync::atomic::Ordering; @@ -193,10 +193,10 @@ impl Clone for AttributeInstance { } /// Registry storing per-entity-type base attribute overrides. -/// Internally stores a map from `entity_type.id` -> `HashMap` for O(1) lookup. +/// Internally stores a map from `entity_type.id` -> `FxHashMap` for O(1) lookup. #[derive(Default)] pub struct AttributeRegistry { - map: HashMap>, + map: FxHashMap>, } impl AttributeRegistry { @@ -278,7 +278,7 @@ mod tests { .find(|(attr, _)| attr.id == Attributes::MOVEMENT_SPEED.id); assert!(speed_attr.is_some()); let (_, base_speed) = speed_attr.unwrap(); - assert!((base_speed - 0.1).abs() < f64::EPSILON); + assert!((base_speed - 0.1).abs() < 1e-4); } #[test] diff --git a/crates/pumpkin/src/entity/effect/weaving.rs b/crates/pumpkin/src/entity/effect/weaving.rs index 2ae803a5f..57defe847 100644 --- a/crates/pumpkin/src/entity/effect/weaving.rs +++ b/crates/pumpkin/src/entity/effect/weaving.rs @@ -1,11 +1,10 @@ -use std::collections::HashSet; - use pumpkin_data::Block; use pumpkin_data::damage::DamageType; use pumpkin_data::world::WorldEvent; use pumpkin_util::math::position::BlockPos; use pumpkin_util::math::vector3::Vector3; use pumpkin_world::world::BlockFlags; +use rustc_hash::FxHashSet; use crate::entity::effect::MobEffect; use crate::entity::living::LivingEntity; @@ -25,7 +24,7 @@ impl MobEffect for WeavingMobEffect { let center_pos = living.entity.block_pos.load(); let cobweb_count = (rand::random::() % 2 + 2) as usize; // 2 to 3 cobwebs - let mut positions_to_transform = HashSet::new(); + let mut positions_to_transform = FxHashSet::default(); // Sample up to 15 random positions in a cube of radius 1 for _ in 0..15 { diff --git a/crates/pumpkin/src/entity/lightning.rs b/crates/pumpkin/src/entity/lightning.rs index 6b144268b..bd8fd2162 100644 --- a/crates/pumpkin/src/entity/lightning.rs +++ b/crates/pumpkin/src/entity/lightning.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use rustc_hash::FxHashSet; use std::sync::{ Arc, Mutex, atomic::{AtomicBool, AtomicI32, AtomicI64, Ordering}, @@ -27,7 +27,7 @@ pub struct LightningBoltEntity { flashes: AtomicI32, visual_only: AtomicBool, cause: Mutex>>, - hit_entities: Mutex>, + hit_entities: Mutex>, blocks_set_on_fire: AtomicI32, } @@ -43,7 +43,7 @@ impl LightningBoltEntity { flashes: AtomicI32::new(flashes), visual_only: AtomicBool::new(false), cause: Mutex::new(None), - hit_entities: Mutex::new(HashSet::new()), + hit_entities: Mutex::new(FxHashSet::default()), blocks_set_on_fire: AtomicI32::new(0), } } diff --git a/crates/pumpkin/src/entity/living.rs b/crates/pumpkin/src/entity/living.rs index 1113b60e0..3ff2bb58c 100644 --- a/crates/pumpkin/src/entity/living.rs +++ b/crates/pumpkin/src/entity/living.rs @@ -12,13 +12,14 @@ use pumpkin_protocol::codec::var_ulong::VarULong; use pumpkin_util::GameMode; use pumpkin_util::Hand; use pumpkin_util::math::position::BlockPos; +use rustc_hash::FxHashMap; use std::sync::Arc; +use std::sync::atomic::AtomicI32; use std::sync::atomic::Ordering; use std::sync::atomic::{ AtomicBool, AtomicU8, Ordering::{Relaxed, SeqCst}, }; -use std::{collections::HashMap, sync::atomic::AtomicI32}; use tracing::warn; use super::experience_orb::ExperienceOrbEntity; @@ -59,7 +60,7 @@ use pumpkin_protocol::java::client::play::{ }; use pumpkin_protocol::{ codec::item_stack_seralizer::ItemStackSerializer, - java::client::play::{CDamageEvent, CSetEquipment, Metadata, MetadataSerializer}, + java::client::play::{CSetEquipment, Metadata, MetadataSerializer}, ser::{NetworkWriteExt, WritingError}, }; use pumpkin_util::math::boundingbox::BoundingBox; @@ -90,11 +91,11 @@ pub struct LivingEntity { pub dead: AtomicBool, /// The distance the entity has been falling. pub fall_distance: AtomicCell, - pub active_effects: std::sync::Mutex>, + pub active_effects: std::sync::Mutex>, pub entity_equipment: Arc>, - pub equipment_drop_chances: Arc>>, + pub equipment_drop_chances: Arc>>, pub movement_input: AtomicCell>, - pub equipment_slots: Arc>, + pub equipment_slots: Arc>, pub jumping: AtomicBool, @@ -119,7 +120,7 @@ pub struct LivingEntity { livings_flags: AtomicU8, /// The attributes of the entity - pub attributes: RwLock>, + pub attributes: RwLock>, } struct EffectParticle { @@ -186,7 +187,7 @@ impl LivingEntity { Self { // Populate local attribute instances from the default registry and get initial vars attributes: { - let mut m = std::collections::HashMap::new(); + let mut m = FxHashMap::default(); for (attr, base) in entity.entity_type.attributes { if attr.id == Attributes::MAX_HEALTH.id { @@ -208,9 +209,9 @@ impl LivingEntity { item_in_use: std::sync::Mutex::new(None), active_hand: std::sync::Mutex::new(None), livings_flags: AtomicU8::new(0), - active_effects: std::sync::Mutex::new(HashMap::new()), + active_effects: std::sync::Mutex::new(FxHashMap::default()), entity_equipment: Arc::new(std::sync::Mutex::new(EntityEquipment::new())), - equipment_drop_chances: Arc::new(std::sync::Mutex::new(HashMap::new())), + equipment_drop_chances: Arc::new(std::sync::Mutex::new(FxHashMap::default())), equipment_slots: Arc::new(build_equipment_slots()), jumping: AtomicBool::new(false), jumping_cooldown: AtomicU8::new(0), @@ -258,8 +259,8 @@ impl LivingEntity { selected_slot: 0, container_id: window_id, }; - self.entity.world.load().broadcast_packet_except_editioned( - &[self.entity.entity_uuid], + self.entity.world.load().send_to_tracking_players_editioned( + &self.entity, &je_packet, &be_packet, ); @@ -271,7 +272,7 @@ impl LivingEntity { self.entity .world .load() - .broadcast_packet_except(&[self.entity.entity_uuid], &je_packet); + .send_to_tracking_players(&self.entity, &je_packet); } } @@ -2485,20 +2486,21 @@ impl LivingEntity { data: VarInt(0), fire_at_position: None, }; - world.broadcast_to_chunk( - self.entity.chunk_pos.load(), - &CHurtAnimation::new(entity_id.into(), hurt_yaw), + let hurt_animation = CHurtAnimation::new(entity_id.into(), hurt_yaw); + world.send_to_tracking_players_and_self_editioned( + &self.entity, + &hurt_animation, + &hurt_event, ); - world.broadcast_to_chunk_bedrock(self.entity.chunk_pos.load(), &hurt_event); } - world.broadcast_packet_all(&CDamageEvent::new( - self.entity.entity_id.into(), - damage_type.id.into(), - source.map(|e| e.get_entity().entity_id.into()), - cause.map(|e| e.get_entity().entity_id.into()), + world.broadcast_damage_event( + &self.entity, + i32::from(damage_type.id), + source.map(|e| e.get_entity().entity_id), + cause.map(|e| e.get_entity().entity_id), position, - )); + ); if play_sound { world.play_sound( diff --git a/crates/pumpkin/src/entity/mod.rs b/crates/pumpkin/src/entity/mod.rs index 672b15584..02e89d6d7 100644 --- a/crates/pumpkin/src/entity/mod.rs +++ b/crates/pumpkin/src/entity/mod.rs @@ -2989,20 +2989,33 @@ impl Entity { bedrock_meta: Option<&SyncedActorDataList>, ) { let world = self.world.load(); - let chunk_pos = self.chunk_pos.load(); let players = world.players.load(); let mut java_recipients = Vec::new(); let mut bedrock_recipients = Vec::new(); - for player in players.iter() { - let center = player.get_entity().chunk_pos.load(); - let view_distance = crate::world::chunker::get_view_distance(player).get() as i32; + if let Some(tracked) = world.entity_tracker.get_tracked_entity(self.entity_id) { + for player in players.iter() { + if tracked.seen_by.contains(&player.gameprofile.id) + || player.entity_id() == self.entity_id + { + match player.client.as_ref() { + ClientPlatform::Java(_) => java_recipients.push(player), + ClientPlatform::Bedrock(client) => bedrock_recipients.push(client), + } + } + } + } else { + let chunk_pos = self.chunk_pos.load(); + for player in players.iter() { + let center = player.get_entity().chunk_pos.load(); + let view_distance = crate::world::chunker::get_view_distance(player).get() as i32; - if is_within_view_distance(chunk_pos, center, view_distance) { - match player.client.as_ref() { - ClientPlatform::Java(_) => java_recipients.push(player), - ClientPlatform::Bedrock(client) => bedrock_recipients.push(client), + if is_within_view_distance(chunk_pos, center, view_distance) { + match player.client.as_ref() { + ClientPlatform::Java(_) => java_recipients.push(player), + ClientPlatform::Bedrock(client) => bedrock_recipients.push(client), + } } } } diff --git a/crates/pumpkin/src/entity/passive/villager/mod.rs b/crates/pumpkin/src/entity/passive/villager/mod.rs index 6f1894cab..7461252dd 100644 --- a/crates/pumpkin/src/entity/passive/villager/mod.rs +++ b/crates/pumpkin/src/entity/passive/villager/mod.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use std::sync::atomic::{AtomicBool, AtomicI32, AtomicI64, Ordering}; use std::sync::{Arc, Weak}; use uuid::Uuid; @@ -264,7 +264,7 @@ pub struct VillagerEntity { pub restocks_today: AtomicI32, pub last_gossip_decay_time: AtomicI64, pub last_gossip_share_time: AtomicI64, - pub gossips: std::sync::Mutex>>, + pub gossips: std::sync::Mutex>>, pub inventory: std::sync::Mutex>, pub merchant_inventory: Arc, pub offers: std::sync::Mutex>, @@ -333,7 +333,7 @@ impl VillagerEntity { restocks_today: AtomicI32::new(0), last_gossip_decay_time: AtomicI64::new(0), last_gossip_share_time: AtomicI64::new(0), - gossips: std::sync::Mutex::new(HashMap::new()), + gossips: std::sync::Mutex::new(FxHashMap::default()), inventory, merchant_inventory: Arc::new(SimpleInventory::new(3)), offers: std::sync::Mutex::new(Vec::new()), diff --git a/crates/pumpkin/src/entity/player.rs b/crates/pumpkin/src/entity/player.rs index 1baa45540..eb8085a12 100644 --- a/crates/pumpkin/src/entity/player.rs +++ b/crates/pumpkin/src/entity/player.rs @@ -2,7 +2,7 @@ pub mod advancement; pub mod statistics; use core::f32; -use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; +use std::collections::{HashMap, VecDeque}; use std::f64::consts::TAU; use std::num::NonZero; use std::str::FromStr; @@ -41,7 +41,7 @@ use pumpkin_protocol::bedrock::server::{ use pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer; use pumpkin_util::translation::Locale; use pumpkin_util::version::JavaMinecraftVersion; -use pumpkin_world::chunk::{ChunkData, ChunkEntityData}; +use pumpkin_world::chunk::ChunkData; use pumpkin_world::inventory::Inventory; use tokio::task::JoinHandle; use tracing::{debug, warn}; @@ -284,7 +284,6 @@ use pumpkin_util::text::hover::HoverEvent; use pumpkin_util::{GameMode, Hand}; use pumpkin_world::biome; use pumpkin_world::cylindrical_chunk_iterator::Cylindrical; -use pumpkin_world::level::{Level, SyncChunk, SyncEntityChunk}; use crate::block; use crate::block::blocks::bed::BedBlock; @@ -312,7 +311,6 @@ use super::item::ItemEntity; use super::living::LivingEntity; use super::{Entity, EntityBase, NBTStorage, NBTStorageInit}; use pumpkin_data::potion::Effect; -use pumpkin_world::chunk_system::ChunkLoading; const MAX_CACHED_SIGNATURES: u8 = 128; // Vanilla: 128 const MAX_PREVIOUS_MESSAGES: u8 = 20; // Vanilla: 20 @@ -373,324 +371,6 @@ const fn bedrock_inventory_slot(player_screen_slot: i16) -> Option { } } -struct HeapNode(i32, Vector2, Weak); - -impl Eq for HeapNode {} - -impl PartialEq for HeapNode { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl PartialOrd for HeapNode { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for HeapNode { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.0.cmp(&other.0).reverse() - } -} - -pub struct ChunkManager { - chunks_per_tick: usize, - center: Vector2, - view_distance: u8, - chunk_listener: Receiver<(Vector2, Weak)>, - chunk_sent: HashMap, Weak>, - chunk_queue: BinaryHeap, - entity_chunk_queue: VecDeque<(Vector2, Weak)>, - batches_sent_since_ack: u8, - last_chunk_batch_sent_at: Instant, - /// The (view, simulation) chunk loading ticket levels currently held at `center`. - held_tickets: Option<(i8, i8)>, - /// The current world for chunk loading. Updated on dimension change. - world: Arc, -} - -impl ChunkManager { - pub const NOTCHIAN_BATCHES_WITHOUT_ACK_UNTIL_PAUSE: u8 = 16; - const ACK_STALL_FALLBACK_DELAY: Duration = Duration::from_millis(100); - - #[must_use] - pub fn new( - chunks_per_tick: usize, - chunk_listener: Receiver<(Vector2, Weak)>, - world: Arc, - ) -> Self { - Self { - chunks_per_tick, - center: Vector2::::new(0, 0), - view_distance: 0, - chunk_listener, - chunk_sent: HashMap::new(), - chunk_queue: BinaryHeap::new(), - entity_chunk_queue: VecDeque::new(), - batches_sent_since_ack: 0, - last_chunk_batch_sent_at: Instant::now(), - held_tickets: None, - world, - } - } - - /// Gets the current world for chunk loading. - #[must_use] - pub const fn world(&self) -> &Arc { - &self.world - } - - #[must_use] - pub fn sent_chunks_count(&self) -> usize { - self.chunk_sent.len() - } - - pub fn reset_sent_chunks(&mut self) { - self.chunk_sent.clear(); - } - - pub const fn set_view_distance(&mut self, view_distance: u8) { - self.view_distance = view_distance; - } - - pub fn clean(&mut self) { - let (_rx, tx) = crossbeam::channel::unbounded(); - // drop old channel - self.chunk_listener = tx; - - // Drop any held chunk references to allow chunks to be unloaded. - self.chunk_sent.clear(); - self.chunk_queue.clear(); - self.entity_chunk_queue.clear(); - } - - fn should_enqueue_chunk(&mut self, position: Vector2, chunk: &SyncChunk) -> bool { - self.chunk_sent - .insert(position, Arc::downgrade(chunk)) - .and_then(|old_chunk| old_chunk.upgrade()) - .is_none_or(|old_chunk| !Arc::ptr_eq(&old_chunk, chunk)) - } - - #[must_use] - const fn ack_window_open(&self) -> bool { - self.batches_sent_since_ack < Self::NOTCHIAN_BATCHES_WITHOUT_ACK_UNTIL_PAUSE - } - - #[must_use] - fn ack_fallback_ready(&self) -> bool { - !self.ack_window_open() - && self.last_chunk_batch_sent_at.elapsed() >= Self::ACK_STALL_FALLBACK_DELAY - } - - pub fn pull_new_chunks(&mut self) { - while let Ok((pos, chunk_weak)) = self.chunk_listener.try_recv() { - let dst = Self::chebyshev(pos, self.center); - if dst > i32::from(self.view_distance) { - continue; - } - if let Some(chunk) = chunk_weak.upgrade() - && self.should_enqueue_chunk(pos, &chunk) - { - self.chunk_queue.push(HeapNode(dst, pos, chunk_weak)); - } - } - } - - fn chebyshev(a: Vector2, b: Vector2) -> i32 { - (a.x - b.x).abs().max((a.y - b.y).abs()) - } - - pub fn update_center_and_view_distance( - &mut self, - center: Vector2, - mut view_distance: u8, - level: &Arc, - loading_chunks: &[Vector2], - unloading_chunks: &[Vector2], - ) { - view_distance += 1; // Margin for loading - let old_center = self.center; - - { - let mut lock = level - .chunk_loading - .lock() - .unwrap_or_else(std::sync::PoisonError::into_inner); - let new_level = ChunkLoading::get_level_from_view_distance(view_distance); - lock.add_ticket(center, new_level); - - let sim_dist = self.world.server.upgrade().map_or(10, |s| { - s.advanced_config.networking.java.simulation_distance.get() - }); - let sim_level = ChunkLoading::get_level_from_simulation_distance(sim_dist); - lock.add_ticket(center, sim_level); - - // Drop exactly the pair we last added rather than recomputing it. The - // simulation level is derived from live config and the view level from the - // previous view distance, so recomputing them can release a ticket we never - // took and strand the one we did. - if let Some((held_view, held_sim)) = self.held_tickets.replace((new_level, sim_level)) { - lock.remove_ticket(old_center, held_view); - lock.remove_ticket(old_center, held_sim); - } - lock.send_change(); - }; - - self.center = center; - self.view_distance = view_distance; - let view_distance_i32 = i32::from(view_distance); - let unloading_chunks: HashSet> = unloading_chunks.iter().copied().collect(); - - self.chunk_sent.retain(|pos, _| { - (pos.x - center.x).abs().max((pos.y - center.y).abs()) <= view_distance_i32 - && !unloading_chunks.contains(pos) - }); - - self.entity_chunk_queue.retain(|(pos, _)| { - (pos.x - center.x).abs().max((pos.y - center.y).abs()) <= view_distance_i32 - && !unloading_chunks.contains(pos) - }); - - let mut tasks: Vec<_> = self - .chunk_queue - .drain() - .filter_map(|node| { - let dst = Self::chebyshev(node.1, center); - (dst <= view_distance_i32 && !unloading_chunks.contains(&node.1)) - .then(|| HeapNode(dst, node.1, node.2)) - }) - .collect(); - - for pos in loading_chunks { - if !self.chunk_sent.contains_key(pos) - && let Some(chunk) = level.loaded_chunks.get(pos) - { - let chunk = chunk.value().clone(); - if self.should_enqueue_chunk(*pos, &chunk) { - let dst = (pos.x - center.x).abs().max((pos.y - center.y).abs()); - tasks.push(HeapNode(dst, *pos, Arc::downgrade(&chunk))); - } - } - } - self.chunk_queue = BinaryHeap::from(tasks); - } - - pub fn clean_up(&mut self, level: &Arc) { - let mut lock = level - .chunk_loading - .lock() - .unwrap_or_else(std::sync::PoisonError::into_inner); - if let Some((view_level, sim_level)) = self.held_tickets.take() { - lock.remove_ticket(self.center, view_level); - lock.remove_ticket(self.center, sim_level); - } - lock.send_change(); - level.should_unload.store(true, Ordering::Relaxed); - level.level_channel.notify(); - let (_rx, tx) = crossbeam::channel::unbounded(); - // drop old channel - self.chunk_listener = tx; - - // Drop any held chunk references to allow chunks to be unloaded. - self.chunk_sent.clear(); - self.chunk_queue.clear(); - self.entity_chunk_queue.clear(); - self.batches_sent_since_ack = 0; - self.last_chunk_batch_sent_at = Instant::now(); - self.view_distance = 0; - } - - pub fn change_world(&mut self, old_level: &Arc, new_world: Arc) { - let mut lock = old_level - .chunk_loading - .lock() - .unwrap_or_else(std::sync::PoisonError::into_inner); - if let Some((view_level, sim_level)) = self.held_tickets.take() { - lock.remove_ticket(self.center, view_level); - lock.remove_ticket(self.center, sim_level); - } - lock.send_change(); - old_level.should_unload.store(true, Ordering::Relaxed); - old_level.level_channel.notify(); - drop(lock); - self.chunk_listener = new_world.level.chunk_listener.add_global_chunk_listener(); - self.chunk_sent.clear(); - self.chunk_queue.clear(); - self.entity_chunk_queue.clear(); - self.view_distance = 0; - self.world = new_world; - // Reset batch state so chunks can be sent immediately in the new dimension - self.batches_sent_since_ack = 0; - self.last_chunk_batch_sent_at = Instant::now(); - } - - pub const fn handle_acknowledge(&mut self, chunks_per_tick: f32) { - self.batches_sent_since_ack = 0; - self.chunks_per_tick = chunks_per_tick.ceil() as usize; - } - - pub fn push_chunk(&mut self, position: Vector2, chunk: &SyncChunk) { - if self.should_enqueue_chunk(position, chunk) { - let dst = (position.x - self.center.x) - .abs() - .max((position.y - self.center.y).abs()); - self.chunk_queue - .push(HeapNode(dst, position, Arc::downgrade(chunk))); - } - } - - pub fn push_entity(&mut self, position: Vector2, chunk: &SyncEntityChunk) { - self.entity_chunk_queue - .push_back((position, Arc::downgrade(chunk))); - } - - #[must_use] - pub fn can_send_chunk(&self) -> bool { - let state_available = self.ack_window_open() || self.ack_fallback_ready(); - - state_available && !self.chunk_queue.is_empty() - } - - pub fn next_chunk(&mut self) -> Box<[SyncChunk]> { - let take = self.chunk_queue.len().min(self.chunks_per_tick.max(1)); - let mut chunks = Vec::with_capacity(take); - while chunks.len() < take - && let Some(node) = self.chunk_queue.pop() - { - if let Some(chunk) = node.2.upgrade() { - chunks.push(chunk); - } - } - self.batches_sent_since_ack = self.batches_sent_since_ack.saturating_add(1); - self.last_chunk_batch_sent_at = Instant::now(); - - chunks.into_boxed_slice() - } - - pub fn next_entity(&mut self) -> Box<[SyncEntityChunk]> { - let chunk_size = self - .entity_chunk_queue - .len() - .min(self.chunks_per_tick.max(1)); - - let mut chunks = Vec::with_capacity(chunk_size); - while chunks.len() < chunk_size - && let Some((_, weak_chunk)) = self.entity_chunk_queue.pop_front() - { - if let Some(chunk) = weak_chunk.upgrade() { - chunks.push(chunk); - } - } - - self.batches_sent_since_ack = self.batches_sent_since_ack.saturating_add(1); - self.last_chunk_batch_sent_at = Instant::now(); - - chunks.into_boxed_slice() - } -} - /// Represents a Minecraft player entity. /// /// A `Player` is a special type of entity that represents a human player connected to the server. @@ -798,7 +478,10 @@ pub struct Player { pub experience_points: AtomicI32, pub item_cooldowns: std::sync::Mutex>, pub experience_pick_up_delay: Mutex, - pub chunk_manager: Mutex, + pub chunk_sender: Mutex, + pub chunk_listener: Mutex, Weak)>>, + pub held_chunk_tickets: Mutex>, + pub chunk_send_epoch: AtomicU32, pub has_played_before: AtomicBool, root_vehicle_uuid: AtomicCell>, pub chat_session: Arc>, @@ -836,7 +519,6 @@ pub struct Player { use base64::prelude::*; use pumpkin_protocol::Property; use serde::Deserialize; -use std::io::Read; // Bit masks for the Java skin pixels that Bedrock requires to be opaque. // Adapted from Geyser's SkinProvider under the MIT License. @@ -883,10 +565,20 @@ impl Player { .and_then(|m| m.model.as_deref()) .is_some_and(|model| model == "slim"); - let resp = ureq::get(&url).call().ok()?; - let mut buf = Vec::new(); - resp.into_body().into_reader().read_to_end(&mut buf).ok()?; - let img = image::load_from_memory(&buf).ok()?; + let bytes = if let Ok(handle) = tokio::runtime::Handle::try_current() { + tokio::task::block_in_place(|| { + handle.block_on(async { + let client = reqwest::Client::new(); + client.get(&url).send().await.ok()?.bytes().await.ok() + }) + })? + } else { + tokio::runtime::Runtime::new().ok()?.block_on(async { + let client = reqwest::Client::new(); + client.get(&url).send().await.ok()?.bytes().await.ok() + })? + }; + let img = image::load_from_memory(&bytes).ok()?; let width = img.width(); let height = img.height(); @@ -1081,12 +773,10 @@ impl Player { experience_progress: AtomicCell::new(0.0), experience_points: AtomicI32::new(0), item_cooldowns: std::sync::Mutex::new(HashMap::new()), - // Default to sending 16 chunks per tick. - chunk_manager: Mutex::new(ChunkManager::new( - 16, - world.level.chunk_listener.add_global_chunk_listener(), - world.clone(), - )), + chunk_sender: Mutex::new(crate::net::ChunkSender::new()), + chunk_listener: Mutex::new(world.level.chunk_listener.add_global_chunk_listener()), + held_chunk_tickets: Mutex::new(None), + chunk_send_epoch: AtomicU32::new(0), last_sent_xp: AtomicI32::new(-1), last_sent_health: AtomicI32::new(-1), last_sent_food: AtomicU8::new(0), @@ -1341,10 +1031,10 @@ impl Player { world.remove_player(self, true).await; let cylindrical = self.watched_section.load(); - self.chunk_manager - .lock() - .unwrap_or_else(std::sync::PoisonError::into_inner) - .clean_up(&world.level); + self.clean_up_chunk_tickets(&world.level); + if let Ok(mut sender) = self.chunk_sender.lock() { + sender.reset(); + } // Radial chunks are all of the chunks the player is theoretically viewing. // Given enough time, all of these chunks will be in memory. @@ -1396,6 +1086,41 @@ impl Player { .add_passenger(vehicle.clone(), self.clone()); } + pub fn clean_up_chunk_tickets(&self, level: &Arc) { + let mut lock = level + .chunk_loading + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner); + let held = self + .held_chunk_tickets + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner) + .take(); + if let Some((view_level, sim_level)) = held { + let center = self.get_entity().chunk_pos.load(); + lock.remove_ticket(center, view_level); + lock.remove_ticket(center, sim_level); + } + lock.send_change(); + level.should_unload.store(true, Ordering::Relaxed); + level.level_channel.notify(); + } + + pub fn change_world_chunks( + &self, + old_level: &Arc, + new_world: &Arc, + ) { + self.clean_up_chunk_tickets(old_level); + if let Ok(mut listener) = self.chunk_listener.lock() { + *listener = new_world.level.chunk_listener.add_global_chunk_listener(); + } + self.chunk_send_epoch.fetch_add(1, Ordering::Relaxed); + if let Ok(mut sender) = self.chunk_sender.lock() { + sender.reset(); + } + } + #[expect(clippy::too_many_lines)] pub fn attack(&self, victim: &Arc) { let world = self.world(); @@ -2602,48 +2327,72 @@ impl Player { { *xp -= 1; } - let (chunk_of_chunks, total_sent_chunks) = self.chunk_manager.try_lock().map_or_else( - |_| (None, 0), - |mut chunk_manager| { - chunk_manager.pull_new_chunks(); - let chunks = if let ClientPlatform::Java(java_client) = self.client.as_ref() { - if java_client.version.load() >= JavaMinecraftVersion::V_1_20_2 { - // Java clients (1.20.2+) use the chunk batching protocol. - // If we have sent too many chunks without receiving an ack, we stop sending chunks. - chunk_manager - .can_send_chunk() - .then(|| chunk_manager.next_chunk()) - } else { - // Java clients < 1.20.2 do not have chunk batching/ack packets. - // Send chunks every tick directly based on chunks_per_tick. - (!chunk_manager.chunk_queue.is_empty()).then(|| chunk_manager.next_chunk()) - } - } else { - (!chunk_manager.chunk_queue.is_empty()).then(|| chunk_manager.next_chunk()) - }; - (chunks, chunk_manager.sent_chunks_count()) - }, - ); - if let Some(chunk_of_chunks) = chunk_of_chunks - && !chunk_of_chunks.is_empty() + if let Ok(listener) = self.chunk_listener.try_lock() + && let Ok(mut sender) = self.chunk_sender.try_lock() { - let client = self.client.clone(); - self.spawn_task(async move { - client.send_chunks(&chunk_of_chunks).await; - }); - if let ClientPlatform::Bedrock(bedrock_client) = self.client.as_ref() - && !self.bedrock_spawned.load(Ordering::Relaxed) - && total_sent_chunks > 4 - { - if let Ok(data) = bedrock_client.serialize_packet(&CPlayStatus::PlayerSpawn) { - bedrock_client.try_enqueue_packet(data); + let center = self.get_entity().chunk_pos.load(); + let view_dist = + std::num::NonZeroI32::from(self.watched_section.load().view_distance).get(); + while let Ok((pos, _)) = listener.try_recv() { + if (pos.x - center.x).abs().max((pos.y - center.y).abs()) <= view_dist { + sender.enqueue_chunk(pos); } - self.bedrock_spawned.store(true, Ordering::Relaxed); - self.set_client_loaded(true); - self.send_health(); - if self.living_entity.health.load() <= 0.0 { - self.send_bedrock_respawn_state(RespawnState::SearchingForSpawn); + } + } + + let world = self.world(); + let player_chunk = self.get_entity().chunk_pos.load(); + let epoch = self.chunk_send_epoch.load(Ordering::Relaxed); + let version = match self.client.as_ref() { + ClientPlatform::Java(java_client) => java_client.version.load(), + ClientPlatform::Bedrock(_) => JavaMinecraftVersion::V_1_20_2, + }; + + let prepared_batch = self.chunk_sender.try_lock().ok().and_then(|mut sender| { + sender.prepare_batch(&world.level, player_chunk, epoch, version) + }); + + let total_sent_chunks = if let Some(batch) = prepared_batch { + match self.client.as_ref() { + ClientPlatform::Java(_) => { + let mut per_player_cache = rustc_hash::FxHashMap::default(); + let encoded = + crate::net::ChunkSender::encode_batch(&batch, &mut per_player_cache); + let current_epoch = self.chunk_send_epoch.load(Ordering::Relaxed); + self.chunk_sender.try_lock().map_or(0, |mut sender| { + sender.commit_batch(&batch, &encoded, &self.client, current_epoch); + sender.sent_chunks_count() + }) } + ClientPlatform::Bedrock(_) => { + let chunks: Vec<_> = batch.chunks.into_iter().map(|c| c.chunk).collect(); + let client = self.client.clone(); + self.spawn_task(async move { + client.send_chunks(&chunks).await; + }); + self.chunk_sender + .try_lock() + .map_or(0, |s| s.sent_chunks_count()) + } + } + } else { + self.chunk_sender + .try_lock() + .map_or(0, |s| s.sent_chunks_count()) + }; + + if let ClientPlatform::Bedrock(bedrock_client) = self.client.as_ref() + && !self.bedrock_spawned.load(Ordering::Relaxed) + && total_sent_chunks > 4 + { + if let Ok(data) = bedrock_client.serialize_packet(&CPlayStatus::PlayerSpawn) { + bedrock_client.try_enqueue_packet(data); + } + self.bedrock_spawned.store(true, Ordering::Relaxed); + self.set_client_loaded(true); + self.send_health(); + if self.living_entity.health.load() <= 0.0 { + self.send_bedrock_respawn_state(RespawnState::SearchingForSpawn); } } self.tick_counter.fetch_add(1, Ordering::Relaxed); @@ -3656,10 +3405,7 @@ impl Player { }); self.unload_watched_chunks(¤t_world).await; - self.chunk_manager - .lock() - .unwrap_or_else(std::sync::PoisonError::into_inner) - .change_world(¤t_world.level, new_world.clone()); + self.change_world_chunks(¤t_world.level, &new_world); self.living_entity.entity.set_world(new_world.clone()); if new_world.dimension == pumpkin_data::dimension::Dimension::THE_NETHER { @@ -3779,6 +3525,7 @@ impl Player { } let i = self.teleport_id_count.fetch_add(1, Ordering::Relaxed); + self.chunk_send_epoch.fetch_add(1, Ordering::Relaxed); let teleport_id = i + 1; self.living_entity.entity.set_pos(position); let entity = &self.living_entity.entity; diff --git a/crates/pumpkin/src/entity/player/statistics.rs b/crates/pumpkin/src/entity/player/statistics.rs index 6d97233b5..73150305f 100644 --- a/crates/pumpkin/src/entity/player/statistics.rs +++ b/crates/pumpkin/src/entity/player/statistics.rs @@ -1,12 +1,12 @@ pub use pumpkin_data::statistic::{CustomStatistic, StatisticCategory}; use pumpkin_nbt::compound::NbtCompound; use pumpkin_nbt::tag::NbtTag; -use std::collections::HashMap; +use rustc_hash::FxHashMap; #[derive(Default)] pub struct Statistics { /// (Category ID, Statistic ID) -> Value - pub stats: HashMap<(i32, i32), i32>, + pub stats: FxHashMap<(i32, i32), i32>, } impl Statistics { diff --git a/crates/pumpkin/src/net/authentication.rs b/crates/pumpkin/src/net/authentication.rs index 4c10765d4..4bde8e071 100644 --- a/crates/pumpkin/src/net/authentication.rs +++ b/crates/pumpkin/src/net/authentication.rs @@ -3,11 +3,11 @@ use std::{collections::HashMap, net::IpAddr}; use base64::{Engine, engine::general_purpose}; use pumpkin_config::{AuthenticationConfig, networking::auth::TextureConfig}; use pumpkin_protocol::Property; +use reqwest::{StatusCode, Url}; use rsa::RsaPublicKey; use rsa::pkcs8::DecodePublicKey; use serde::Deserialize; use thiserror::Error; -use ureq::http::{StatusCode, Uri}; use uuid::Uuid; use super::GameProfile; @@ -54,16 +54,16 @@ const MOJANG_PROFILE_BY_NAME_URL: &str = const MOJANG_PROFILE_BY_UUID_URL: &str = "https://sessionserver.mojang.com/session/minecraft/profile/{uuid}?unsigned=false"; -fn create_agent(auth_config: &AuthenticationConfig) -> ureq::Agent { - let config = ureq::Agent::config_builder() - .timeout_connect(Some(std::time::Duration::from_millis( +fn create_client(auth_config: &AuthenticationConfig) -> reqwest::Client { + reqwest::Client::builder() + .connect_timeout(std::time::Duration::from_millis( auth_config.connect_timeout as u64, - ))) - .timeout_recv_response(Some(std::time::Duration::from_millis( + )) + .timeout(std::time::Duration::from_millis( auth_config.read_timeout as u64, - ))) - .build(); - config.into() + )) + .build() + .unwrap_or_default() } fn format_auth_url(url_template: &str, username: &str, server_hash: &str, ip: &IpAddr) -> String { @@ -87,7 +87,7 @@ fn format_auth_url(url_template: &str, username: &str, server_hash: &str, ip: &I /// 3. Pumpkin attempts to authenticate the player against the primary auth server, falling back to secondary auth servers if the primary is down. /// /// See -pub fn authenticate( +pub async fn authenticate( username: &str, server_hash: &str, ip: &IpAddr, @@ -111,7 +111,7 @@ pub fn authenticate( candidate_urls.push(fallback.as_str()); } - let agent = create_agent(auth_config); + let client = create_client(auth_config); let mut unverified_count = 0; let mut last_unknown_status = None; @@ -119,7 +119,7 @@ pub fn authenticate( for url_template in candidate_urls { let address = format_auth_url(url_template, username, server_hash, ip); - let mut response = match agent.get(&address).call() { + let response = match client.get(&address).send().await { Ok(resp) => resp, Err(err) => { tracing::warn!( @@ -136,7 +136,7 @@ pub fn authenticate( } match status { - StatusCode::OK => match response.body_mut().read_json::() { + StatusCode::OK => match response.json::().await { Ok(profile) => return Ok(profile), Err(err) => { tracing::warn!("Failed to parse GameProfile response from '{address}': {err}"); @@ -167,41 +167,35 @@ pub fn validate_textures(property: &Property, config: &TextureConfig) -> Result< let textures: ProfileTextures = serde_json::from_slice(&from64).map_err(|e| TextureError::JSONError(e.to_string()))?; for texture in textures.textures { - let url = texture - .1 - .url - .parse() - .map_err(|_| TextureError::InvalidURL)?; + let url = Url::parse(&texture.1.url).map_err(|_| TextureError::InvalidURL)?; is_texture_url_valid(&url, config)?; } Ok(()) } -pub fn is_texture_url_valid(url: &Uri, config: &TextureConfig) -> Result<(), TextureError> { - let Some(scheme) = url.scheme() else { - return Err(TextureError::InvalidURL); - }; +pub fn is_texture_url_valid(url: &Url, config: &TextureConfig) -> Result<(), TextureError> { + let scheme = url.scheme(); if !config .allowed_url_schemes .iter() - .any(|allowed_scheme| scheme.as_str().ends_with(allowed_scheme)) + .any(|allowed_scheme| scheme.ends_with(allowed_scheme)) { return Err(TextureError::DisallowedUrlScheme(scheme.to_string())); } - let Some(domain) = url.authority() else { + let Some(domain) = url.domain() else { return Err(TextureError::InvalidURL); }; if !config .allowed_url_domains .iter() - .any(|allowed_domain| domain.as_str().ends_with(allowed_domain)) + .any(|allowed_domain| domain.ends_with(allowed_domain)) { return Err(TextureError::DisallowedUrlDomain(domain.to_string())); } Ok(()) } -pub fn fetch_mojang_public_keys( +pub async fn fetch_mojang_public_keys( auth_config: &AuthenticationConfig, ) -> Result, AuthError> { let services_url = auth_config @@ -211,10 +205,11 @@ pub fn fetch_mojang_public_keys( let url = format!("{services_url}/publickeys"); - let agent = create_agent(auth_config); - let mut response = agent + let client = create_client(auth_config); + let response = client .get(&url) - .call() + .send() + .await .map_err(|_| AuthError::FailedResponse)?; match response.status() { @@ -223,10 +218,8 @@ pub fn fetch_mojang_public_keys( other => Err(AuthError::UnknownStatusCode(other))?, } - let public_keys: MojangPublicKeys = response - .body_mut() - .read_json() - .map_err(|_| AuthError::FailedParse)?; + let public_keys: MojangPublicKeys = + response.json().await.map_err(|_| AuthError::FailedParse)?; let as_rsa_keys = public_keys .player_certificate_keys @@ -248,7 +241,7 @@ struct MojangProfileByNameResponse { name: String, } -pub fn lookup_profile_by_name( +pub async fn lookup_profile_by_name( name: &str, auth_config: &AuthenticationConfig, ) -> Result, AuthError> { @@ -263,7 +256,7 @@ pub fn lookup_profile_by_name( candidate_urls.push(fallback.as_str()); } - let agent = create_agent(auth_config); + let client = create_client(auth_config); let mut not_found_count = 0; let mut last_unknown_status = None; @@ -271,7 +264,7 @@ pub fn lookup_profile_by_name( for url_template in candidate_urls { let address = url_template.replace("{username}", name); - let mut response = match agent.get(&address).call() { + let response = match client.get(&address).send().await { Ok(resp) => resp, Err(err) => { tracing::warn!( @@ -288,10 +281,7 @@ pub fn lookup_profile_by_name( } match status { - StatusCode::OK => match response - .body_mut() - .read_json::() - { + StatusCode::OK => match response.json::().await { Ok(profile) => { let parsed_uuid = Uuid::parse_str(&profile.id).map_err(|_| AuthError::FailedParse)?; @@ -321,7 +311,20 @@ pub fn lookup_profile_by_name( } } -pub fn fetch_profile_by_uuid( +pub fn lookup_profile_by_name_blocking( + name: &str, + auth_config: &AuthenticationConfig, +) -> Result, AuthError> { + if let Ok(handle) = tokio::runtime::Handle::try_current() { + tokio::task::block_in_place(|| handle.block_on(lookup_profile_by_name(name, auth_config))) + } else { + tokio::runtime::Runtime::new() + .map_err(|_e| AuthError::FailedParse)? + .block_on(lookup_profile_by_name(name, auth_config)) + } +} + +pub async fn fetch_profile_by_uuid( uuid: Uuid, auth_config: &AuthenticationConfig, ) -> Result, AuthError> { @@ -336,7 +339,7 @@ pub fn fetch_profile_by_uuid( candidate_urls.push(fallback.as_str()); } - let agent = create_agent(auth_config); + let client = create_client(auth_config); let mut not_found_count = 0; let mut last_unknown_status = None; @@ -348,7 +351,7 @@ pub fn fetch_profile_by_uuid( .replace("{uuid}", &uuid_simple) .replace("{uuid_hyphenated}", &uuid.to_string()); - let mut response = match agent.get(&address).call() { + let response = match client.get(&address).send().await { Ok(resp) => resp, Err(err) => { tracing::warn!("Profile fetch server at '{address}' is down or unreachable: {err}"); @@ -363,7 +366,7 @@ pub fn fetch_profile_by_uuid( } match status { - StatusCode::OK => match response.body_mut().read_json::() { + StatusCode::OK => match response.json::().await { Ok(profile) => return Ok(Some(profile)), Err(err) => { tracing::warn!("Failed to parse GameProfile response from '{address}': {err}"); diff --git a/crates/pumpkin/src/net/chunk_sender.rs b/crates/pumpkin/src/net/chunk_sender.rs new file mode 100644 index 000000000..8481f97a7 --- /dev/null +++ b/crates/pumpkin/src/net/chunk_sender.rs @@ -0,0 +1,311 @@ +use bytes::Bytes; +use rayon::prelude::*; +use rustc_hash::{FxHashMap, FxHashSet}; +use std::sync::{Arc, Weak}; + +use pumpkin_protocol::codec::var_int::VarInt; +use pumpkin_protocol::java::client::play::{ + CChunkBatchEnd, CChunkBatchStart, CChunkData, CLightUpdate, CUnloadChunk, +}; +use pumpkin_protocol::ser::NetworkWriteExt; +use pumpkin_protocol::{ClientPacket, MultiVersionJavaPacket}; +use pumpkin_util::math::vector2::Vector2; +use pumpkin_util::version::JavaMinecraftVersion; +use pumpkin_world::chunk::ChunkData; +use pumpkin_world::level::{Level, SyncChunk}; + +use crate::net::ClientPlatform; + +const MIN_CHUNKS_PER_TICK: f32 = 0.1; +const MAX_CHUNKS_PER_TICK: f32 = 500.0; +const INITIAL_CHUNKS_PER_TICK: f32 = 9.0; +const MAX_CONCURRENT_BATCHES: u16 = 10; + +pub struct PreparedChunk { + pub position: Vector2, + pub chunk: SyncChunk, +} + +pub struct PreparedBatch { + pub chunks: Vec, + pub epoch_snapshot: u32, + pub target_version: JavaMinecraftVersion, +} + +#[derive(Clone)] +pub struct EncodedChunk { + pub position: Vector2, + pub payload: Bytes, + pub light_payload: Option, + pub chunk_ref: Weak, +} + +impl EncodedChunk { + #[must_use] + pub fn is_fresh_for(&self, candidate: &PreparedChunk) -> bool { + let Some(held) = self.chunk_ref.upgrade() else { + return false; + }; + + self.position == candidate.position && Arc::ptr_eq(&held, &candidate.chunk) + } +} + +#[derive(Debug)] +pub struct ChunkSender { + pub pending_chunks: FxHashSet>, + sent_chunks: FxHashSet>, + pub in_flight_batches: u16, + pub desired_rate: f32, + pub send_quota: f32, + pub max_in_flight: u16, +} + +impl ChunkSender { + #[must_use] + pub fn new() -> Self { + Self { + pending_chunks: FxHashSet::default(), + sent_chunks: FxHashSet::default(), + in_flight_batches: 0, + desired_rate: INITIAL_CHUNKS_PER_TICK, + send_quota: 0.0, + max_in_flight: 1, + } + } + + pub fn reset(&mut self) { + self.pending_chunks.clear(); + self.sent_chunks.clear(); + self.in_flight_batches = 0; + self.send_quota = 0.0; + } + + #[must_use] + pub fn is_chunk_sent(&self, pos: &Vector2) -> bool { + self.sent_chunks.contains(pos) + } + + #[must_use] + pub fn sent_chunks_count(&self) -> usize { + self.sent_chunks.len() + } + + pub const fn on_batch_acknowledged(&mut self, client_requested_rate: f32) -> bool { + if self.in_flight_batches == 0 { + return false; + } + + self.in_flight_batches = self.in_flight_batches.saturating_sub(1); + self.desired_rate = if client_requested_rate.is_nan() { + MIN_CHUNKS_PER_TICK + } else { + client_requested_rate.clamp(MIN_CHUNKS_PER_TICK, MAX_CHUNKS_PER_TICK) + }; + + if self.in_flight_batches == 0 { + self.send_quota = 1.0; + } + + self.max_in_flight = MAX_CONCURRENT_BATCHES; + true + } + + pub fn enqueue_chunk(&mut self, pos: Vector2) { + self.sent_chunks.remove(&pos); + self.pending_chunks.insert(pos); + } + + pub fn unload_chunk(&mut self, client: &ClientPlatform, pos: Vector2) { + self.pending_chunks.remove(&pos); + if self.sent_chunks.remove(&pos) + && let ClientPlatform::Java(java_client) = client + && !java_client.is_closed() + { + java_client.try_send_packet(&CUnloadChunk::new(pos.x, pos.y)); + } + } + + fn collect_sorted_candidates(&self, level: &Level, center: Vector2) -> Vec { + let quota_limit = self.send_quota.floor() as usize; + let mut sorted: Vec> = self.pending_chunks.iter().copied().collect(); + + sorted.sort_by_key(|pos| { + let dx = (pos.x - center.x).unsigned_abs() as u64; + let dz = (pos.y - center.y).unsigned_abs() as u64; + dx * dx + dz * dz + }); + + let mut ready = Vec::with_capacity(quota_limit); + for pos in sorted { + if ready.len() >= quota_limit { + break; + } + + if let Some(chunk) = level.loaded_chunks.get(&pos) { + ready.push(PreparedChunk { + position: pos, + chunk: chunk.value().clone(), + }); + } + } + + ready + } + + pub fn prepare_batch( + &mut self, + level: &Level, + player_chunk: Vector2, + epoch: u32, + version: JavaMinecraftVersion, + ) -> Option { + if self.in_flight_batches >= self.max_in_flight { + return None; + } + + let max_batch = self.desired_rate.max(1.0); + self.send_quota = (self.send_quota + self.desired_rate).min(max_batch); + + if self.send_quota < 1.0 || self.pending_chunks.is_empty() { + return None; + } + + let candidates = self.collect_sorted_candidates(level, player_chunk); + if candidates.is_empty() { + return None; + } + + Some(PreparedBatch { + chunks: candidates, + epoch_snapshot: epoch, + target_version: version, + }) + } + + pub fn encode_batch( + batch: &PreparedBatch, + cache: &mut FxHashMap, EncodedChunk>, + ) -> Vec { + let version = batch.target_version; + let cached_map = &*cache; + + let encoded_results: Vec> = batch + .chunks + .par_iter() + .map(|candidate| { + let pos = candidate.position; + if let Some(cached) = cached_map.get(&pos) + && cached.is_fresh_for(candidate) + { + return Some(cached.clone()); + } + + let chunk = &candidate.chunk; + let mut chunk_buf = Vec::with_capacity(32 * 1024); + if chunk_buf + .write_var_int(&VarInt(CChunkData::to_id(version))) + .is_err() + { + return None; + } + if CChunkData(chunk) + .write_packet_data(&mut chunk_buf, &version) + .is_err() + { + return None; + } + + let light_payload = if version >= JavaMinecraftVersion::V_1_14 + && version < JavaMinecraftVersion::V_1_18 + { + CLightUpdate::from_chunk(chunk, version) + .ok() + .and_then(|light_packet| { + let mut light_buf = Vec::new(); + (light_buf + .write_var_int(&VarInt(CLightUpdate::to_id(version))) + .is_ok() + && light_packet + .write_packet_data(&mut light_buf, &version) + .is_ok()) + .then(|| Bytes::from(light_buf)) + }) + } else { + None + }; + + Some(EncodedChunk { + position: pos, + payload: Bytes::from(chunk_buf), + light_payload, + chunk_ref: Arc::downgrade(chunk), + }) + }) + .collect(); + + let mut output = Vec::with_capacity(encoded_results.len()); + for encoded in encoded_results.into_iter().flatten() { + cache.insert(encoded.position, encoded.clone()); + output.push(encoded); + } + + output + } + + pub fn commit_batch( + &mut self, + batch: &PreparedBatch, + encoded_chunks: &[EncodedChunk], + client: &ClientPlatform, + current_epoch: u32, + ) -> Vec> { + if current_epoch != batch.epoch_snapshot || encoded_chunks.is_empty() { + return Vec::new(); + } + + let mut dispatched_positions = Vec::with_capacity(encoded_chunks.len()); + let version = batch.target_version; + + if version >= JavaMinecraftVersion::V_1_20_2 + && let ClientPlatform::Java(java_client) = client + { + java_client.try_send_packet(&CChunkBatchStart); + } + + for chunk in encoded_chunks { + if !self.pending_chunks.contains(&chunk.position) { + continue; + } + + client.try_enqueue_packet(chunk.payload.clone()); + if let Some(ref light) = chunk.light_payload { + client.try_enqueue_packet(light.clone()); + } + + self.pending_chunks.remove(&chunk.position); + self.sent_chunks.insert(chunk.position); + dispatched_positions.push(chunk.position); + } + + let sent_count = dispatched_positions.len(); + if sent_count > 0 { + if version >= JavaMinecraftVersion::V_1_20_2 + && let ClientPlatform::Java(java_client) = client + { + java_client.try_send_packet(&CChunkBatchEnd::new(sent_count as u16)); + } + + self.in_flight_batches = self.in_flight_batches.saturating_add(1); + self.send_quota -= sent_count as f32; + } + + dispatched_positions + } +} + +impl Default for ChunkSender { + fn default() -> Self { + Self::new() + } +} diff --git a/crates/pumpkin/src/net/java/login/encryption_response.rs b/crates/pumpkin/src/net/java/login/encryption_response.rs index 18fbae44b..b87e30ab1 100644 --- a/crates/pumpkin/src/net/java/login/encryption_response.rs +++ b/crates/pumpkin/src/net/java/login/encryption_response.rs @@ -66,7 +66,10 @@ impl PendingConnection { }; if server.advanced_config.networking.java.online_mode { - match self.authenticate(server, &shared_secret, &profile_name) { + match self + .authenticate(server, &shared_secret, &profile_name) + .await + { Ok(new_profile) => self.gameprofile = Some(new_profile), Err(error) => { self.kick(match error { @@ -168,7 +171,7 @@ impl PendingConnection { Some(PacketHandlerResult::ReadyToPlay(profile.clone(), config)) } - fn authenticate( + async fn authenticate( &self, server: &Server, shared_secret: &[u8], @@ -181,7 +184,8 @@ impl PendingConnection { &hash, &ip, &server.advanced_config.networking.java.authentication, - )?; + ) + .await?; if let Some(actions) = &profile.profile_actions { if server diff --git a/crates/pumpkin/src/net/java/play/chunk_batch.rs b/crates/pumpkin/src/net/java/play/chunk_batch.rs index 5c6dd91f0..e21ae9861 100644 --- a/crates/pumpkin/src/net/java/play/chunk_batch.rs +++ b/crates/pumpkin/src/net/java/play/chunk_batch.rs @@ -4,10 +4,10 @@ use super::*; impl JavaClient { pub fn handle_chunk_batch(&self, player: &Player, packet: &SChunkBatch) { player - .chunk_manager + .chunk_sender .lock() .unwrap_or_else(std::sync::PoisonError::into_inner) - .handle_acknowledge(packet.chunks_per_tick); + .on_batch_acknowledged(packet.chunks_per_tick); trace!( "Client requested {} chunks per tick", packet.chunks_per_tick diff --git a/crates/pumpkin/src/net/mod.rs b/crates/pumpkin/src/net/mod.rs index a7804b1bc..f6e56eb45 100644 --- a/crates/pumpkin/src/net/mod.rs +++ b/crates/pumpkin/src/net/mod.rs @@ -28,6 +28,8 @@ use thiserror::Error; use uuid::Uuid; pub mod authentication; pub mod bedrock; +pub mod chunk_sender; +pub use chunk_sender::ChunkSender; pub mod java; pub mod lan_broadcast; pub mod packet_limiter; diff --git a/crates/pumpkin/src/plugin/loader/wasm/wasm_host/signature.rs b/crates/pumpkin/src/plugin/loader/wasm/wasm_host/signature.rs index 75fe28496..4421cdde4 100644 --- a/crates/pumpkin/src/plugin/loader/wasm/wasm_host/signature.rs +++ b/crates/pumpkin/src/plugin/loader/wasm/wasm_host/signature.rs @@ -182,15 +182,43 @@ pub fn fetch_market_public_key() -> Result { return Ok(cached_key.clone()); } - let mut response = ureq::get(PUMPKIN_MARKET_PUBLIC_KEY_URL) - .header("User-Agent", "Pumpkin-MC") - .call() - .map_err(|e| format!("Failed to fetch public key from market: {e}"))?; - - let body = response - .body_mut() - .read_to_string() - .map_err(|e| format!("Failed to read public key response: {e}"))?; + let body = if let Ok(handle) = tokio::runtime::Handle::try_current() { + tokio::task::block_in_place(|| { + handle.block_on(async { + let client = reqwest::Client::builder() + .user_agent("Pumpkin-MC") + .build() + .map_err(|e| format!("Failed to build HTTP client: {e}"))?; + let response = client + .get(PUMPKIN_MARKET_PUBLIC_KEY_URL) + .send() + .await + .map_err(|e| format!("Failed to fetch public key from market: {e}"))?; + response + .text() + .await + .map_err(|e| format!("Failed to read public key response: {e}")) + }) + })? + } else { + tokio::runtime::Runtime::new() + .map_err(|e| format!("Failed to create runtime: {e}"))? + .block_on(async { + let client = reqwest::Client::builder() + .user_agent("Pumpkin-MC") + .build() + .map_err(|e| format!("Failed to build HTTP client: {e}"))?; + let response = client + .get(PUMPKIN_MARKET_PUBLIC_KEY_URL) + .send() + .await + .map_err(|e| format!("Failed to fetch public key from market: {e}"))?; + response + .text() + .await + .map_err(|e| format!("Failed to read public key response: {e}")) + })? + }; let key = body.trim().trim_matches('"').to_string(); if key.is_empty() { diff --git a/crates/pumpkin/src/server/enchantment.rs b/crates/pumpkin/src/server/enchantment.rs index 06f93f4bd..feb83dc79 100644 --- a/crates/pumpkin/src/server/enchantment.rs +++ b/crates/pumpkin/src/server/enchantment.rs @@ -1,6 +1,6 @@ use pumpkin_data::enchantment::AttributeModifierSlot; use pumpkin_util::text::TextComponent; -use std::collections::HashMap; +use rustc_hash::FxHashMap; use tokio::sync::RwLock; #[derive(Clone, Debug)] @@ -16,7 +16,7 @@ pub struct CustomEnchantmentEntry { } pub struct EnchantmentManager { - custom_enchantments: RwLock>, + custom_enchantments: RwLock>, } impl Default for EnchantmentManager { @@ -29,7 +29,7 @@ impl EnchantmentManager { #[must_use] pub fn new() -> Self { Self { - custom_enchantments: RwLock::new(HashMap::new()), + custom_enchantments: RwLock::new(FxHashMap::default()), } } diff --git a/crates/pumpkin/src/server/mod.rs b/crates/pumpkin/src/server/mod.rs index 3394393d1..955aaff00 100644 --- a/crates/pumpkin/src/server/mod.rs +++ b/crates/pumpkin/src/server/mod.rs @@ -43,7 +43,7 @@ use pumpkin_world::world_info::{LevelData, WorldInfoError, WorldInfoReader, Worl use rand::seq::{IndexedRandom, SliceRandom}; use rayon::prelude::*; use rsa::RsaPublicKey; -use std::collections::HashSet; +use rustc_hash::FxHashSet; use std::fs; use std::net::IpAddr; use std::sync::Arc; @@ -330,10 +330,12 @@ impl Server { .java .authentication .clone(); - let keys = fetch_mojang_public_keys(&auth_config).unwrap_or_else(|e| { - error!("Failed to fetch Mojang keys: {e}"); - Vec::new() - }); + let keys = fetch_mojang_public_keys(&auth_config) + .await + .unwrap_or_else(|e| { + error!("Failed to fetch Mojang keys: {e}"); + Vec::new() + }); server_clone.mojang_public_keys.store(Arc::new(keys)); }); } @@ -358,7 +360,9 @@ impl Server { auth.url.as_deref(), auth.connect_timeout, auth.read_timeout, - ) { + ) + .await + { Ok(keys) => keys, Err(error) => { error!("Failed to fetch Bedrock OIDC keys: {error}"); @@ -1179,7 +1183,7 @@ impl Server { None } }) - .collect::>(); + .collect::>(); let type_excluded = target_selector .conditions .iter() @@ -1190,7 +1194,7 @@ impl Server { None } }) - .collect::>(); + .collect::>(); players.retain(|_| { (type_excluded.is_empty() || !type_excluded.contains(player_type)) @@ -1290,7 +1294,7 @@ impl Server { None } }) - .collect::>(); + .collect::>(); let type_excluded = target_selector .conditions .iter() @@ -1301,7 +1305,7 @@ impl Server { None } }) - .collect::>(); + .collect::>(); entities.retain(|entity| { // Filter by entity type (type_excluded.is_empty() || !type_excluded.contains(&entity.get_entity().entity_type)) diff --git a/crates/pumpkin/src/world/chunker.rs b/crates/pumpkin/src/world/chunker.rs index 3e68ab1eb..2499590c9 100644 --- a/crates/pumpkin/src/world/chunker.rs +++ b/crates/pumpkin/src/world/chunker.rs @@ -3,7 +3,7 @@ use std::{num::NonZero, sync::Arc}; use pumpkin_protocol::{ bedrock::client::network_chunk_publisher_update::CNetworkChunkPublisherUpdate, - java::client::play::{CCenterChunk, CUnloadChunk}, + java::client::play::CCenterChunk, }; use pumpkin_world::cylindrical_chunk_iterator::Cylindrical; @@ -78,30 +78,51 @@ pub fn update_position(player: &Arc) { let loading_chunks: Vec<_> = loading_iter.collect(); let unloading_chunks: Vec<_> = unloading_iter.collect(); - // Use the chunk_manager's world reference, which is updated on dimension change. - // This ensures we load chunks from the correct world after portal teleportation. - let world = { - let mut chunk_manager = player - .chunk_manager + let world = player.world(); + let level = &world.level; + let mut held_tickets = player + .held_chunk_tickets + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner); + + { + let mut lock = level + .chunk_loading .lock() .unwrap_or_else(std::sync::PoisonError::into_inner); - let world = chunk_manager.world().clone(); - chunk_manager.update_center_and_view_distance( - new_chunk_center, - view_distance.into(), - &world.level, - &loading_chunks, - &unloading_chunks, + let new_level = pumpkin_world::chunk_system::ChunkLoading::get_level_from_view_distance( + u8::from(view_distance) + 1, ); - world - }; - player.watched_section.store(new_cylindrical); + lock.add_ticket(new_chunk_center, new_level); - if let ClientPlatform::Java(client) = player.client.as_ref() { - for chunk in &unloading_chunks { - client.try_send_packet(&CUnloadChunk::new(chunk.x, chunk.y)); + let sim_dist = world.server.upgrade().map_or(10, |s| { + s.advanced_config.networking.java.simulation_distance.get() + }); + let sim_level = + pumpkin_world::chunk_system::ChunkLoading::get_level_from_simulation_distance(sim_dist); + lock.add_ticket(new_chunk_center, sim_level); + + if let Some((held_view, held_sim)) = held_tickets.replace((new_level, sim_level)) { + lock.remove_ticket(old_cylindrical.center, held_view); + lock.remove_ticket(old_cylindrical.center, held_sim); + } + lock.send_change(); + }; + drop(held_tickets); + + { + let mut sender = player + .chunk_sender + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner); + for pos in &unloading_chunks { + sender.unload_chunk(&player.client, *pos); + } + for pos in &loading_chunks { + sender.enqueue_chunk(*pos); } } + player.watched_section.store(new_cylindrical); // Make sure the watched section and the chunk watcher updates are async atomic. We want to // ensure what we unload when the player disconnects is correct. @@ -133,4 +154,5 @@ pub fn update_position(player: &Arc) { if !loading_chunks.is_empty() { world.spawn_world_entity_chunks(player.clone(), loading_chunks, new_chunk_center); } + world.entity_tracker.update_player_position(player, &world); } diff --git a/crates/pumpkin/src/world/custom_bossbar.rs b/crates/pumpkin/src/world/custom_bossbar.rs index dd6badfad..594a787d9 100644 --- a/crates/pumpkin/src/world/custom_bossbar.rs +++ b/crates/pumpkin/src/world/custom_bossbar.rs @@ -3,7 +3,7 @@ use crate::entity::player::Player; use crate::server::Server; use crate::world::bossbar::{Bossbar, BossbarColor, BossbarDivisions}; use pumpkin_util::text::TextComponent; -use std::collections::HashMap; +use rustc_hash::FxHashMap; use std::sync::Arc; use thiserror::Error; use uuid::Uuid; @@ -43,7 +43,7 @@ impl CustomBossbar { } pub struct CustomBossbars { - pub custom_bossbars: HashMap, + pub custom_bossbars: FxHashMap, } impl Default for CustomBossbars { @@ -56,7 +56,7 @@ impl CustomBossbars { #[must_use] pub fn new() -> Self { Self { - custom_bossbars: HashMap::new(), + custom_bossbars: FxHashMap::default(), } } diff --git a/crates/pumpkin/src/world/entity_tracker.rs b/crates/pumpkin/src/world/entity_tracker.rs new file mode 100644 index 000000000..06778311f --- /dev/null +++ b/crates/pumpkin/src/world/entity_tracker.rs @@ -0,0 +1,461 @@ +use std::sync::Arc; + +use bytes::BufMut; +use dashmap::DashMap; +use dashmap::DashSet; +use pumpkin_protocol::bedrock::client::remove_actor::CRemoveActor; +use pumpkin_protocol::codec::var_long::VarLong; +use pumpkin_protocol::java::client::play::{ + CEntityVelocity, CHeadRot, CRemoveEntities, CSetEntityMetadata, Metadata, +}; +use pumpkin_protocol::{BClientPacket, ClientPacket}; +use pumpkin_util::version::JavaMinecraftVersion; +use uuid::Uuid; + +use crate::entity::EntityBase; +use crate::entity::player::Player; +use crate::net::ClientPlatform; +use crate::net::java::JavaClient; +use crate::world::World; +use crate::world::chunker::{get_view_distance, is_within_view_distance}; + +/// Represents an entity tracked in the world and its current watchers, +/// corresponding to Vanilla's `ChunkMap.TrackedEntity`. +pub struct TrackedEntity { + pub entity: Arc, + pub entity_id: i32, + pub tracking_range: u32, + pub update_interval: u32, + pub track_deltas: bool, + pub seen_by: DashSet, +} + +impl TrackedEntity { + #[must_use] + pub fn new( + entity: Arc, + range: u32, + update_interval: u32, + track_deltas: bool, + ) -> Self { + let entity_id = entity.get_entity().entity_id; + Self { + entity, + entity_id, + tracking_range: range, + update_interval, + track_deltas, + seen_by: DashSet::new(), + } + } + + /// Gets the effective tracking range in chunks, taking passengers into account. + #[must_use] + pub fn get_effective_range(&self) -> u32 { + let mut effective_range = self.tracking_range; + if let Ok(passengers) = self.entity.get_entity().passengers.try_lock() { + for passenger in passengers.iter() { + let passenger_range = passenger.get_entity().entity_type.client_tracking_range; + if passenger_range > effective_range { + effective_range = passenger_range; + } + } + } + effective_range + } + + /// Updates visibility for a single player. + pub fn update_player(&self, player: &Arc, _world: &World) { + if player.get_entity().entity_id == self.entity_id { + return; + } + + let player_entity = player.get_entity(); + let player_pos = player_entity.pos.load(); + let entity_pos = self.entity.get_entity().pos.load(); + let dx = player_pos.x - entity_pos.x; + let dz = player_pos.z - entity_pos.z; + let dist_sq = dx.mul_add(dx, dz * dz); + + let player_vd = get_view_distance(player).get() as i32; + let effective_range = self.get_effective_range(); + let visible_range_blocks = f64::from((effective_range as i32).min(player_vd) * 16); + let range_sq = visible_range_blocks * visible_range_blocks; + + let entity_chunk = self.entity.get_entity().chunk_pos.load(); + let player_chunk = player_entity.chunk_pos.load(); + let in_view = is_within_view_distance(entity_chunk, player_chunk, player_vd); + + let is_visible = dist_sq <= range_sq && in_view; + + if is_visible { + if self.seen_by.insert(player.gameprofile.id) { + self.add_pairing(player); + } + } else if self.seen_by.remove(&player.gameprofile.id).is_some() { + self.remove_pairing(player); + } + } + + /// Updates visibility for a list of players. + pub fn update_players(&self, players: &[Arc], world: &World) { + for player in players { + self.update_player(player, world); + } + } + + /// Sends spawn and initial state packets to the new watcher. + pub fn add_pairing(&self, player: &Arc) { + player.client.try_enqueue_spawn_packet(&self.entity); + + if let Some(target_player) = self.entity.get_player() { + let skin_parts = target_player.config.load().skin_parts; + let target_entity = target_player.get_entity(); + let target_id = target_entity.entity_id; + + if let ClientPlatform::Java(client) = player.client.as_ref() { + let version = client.version.load(); + if version >= JavaMinecraftVersion::V_1_21 { + let mut buf = Vec::new(); + for meta in [ + Metadata::new( + pumpkin_data::tracked_data::player::PLAYER_MODE_CUSTOMISATION, + skin_parts, + ), + Metadata::new( + pumpkin_data::tracked_data::player::PLAYER_MODE_CUSTOMIZATION_ID, + skin_parts, + ), + ] { + let _ = meta.write(&mut buf, &version); + } + buf.put_u8(255); + let meta_packet = CSetEntityMetadata::new(target_id.into(), buf.into()); + if let Ok(packet_data) = + JavaClient::serialize_packet_for_version(&meta_packet, version) + { + client.try_enqueue_packet(packet_data); + } + } + + let head_yaw = target_entity.head_yaw.load(); + let head_rot_packet = CHeadRot::new( + target_id.into(), + (head_yaw * 256.0 / 360.0).rem_euclid(256.0) as u8, + ); + if let Ok(data) = client.serialize_packet(&head_rot_packet) { + client.try_enqueue_packet(data); + } + } + } else if self.entity.get_living_entity().is_some() + && let ClientPlatform::Java(client) = player.client.as_ref() + { + let head_yaw = self.entity.get_entity().head_yaw.load(); + let head_rot_packet = CHeadRot::new( + self.entity_id.into(), + (head_yaw * 256.0 / 360.0).rem_euclid(256.0) as u8, + ); + if let Ok(data) = client.serialize_packet(&head_rot_packet) { + client.try_enqueue_packet(data); + } + } + + let vel = self.entity.get_entity().velocity.load(); + if vel.length_squared() > 1e-4 + && let ClientPlatform::Java(client) = player.client.as_ref() + { + let motion = CEntityVelocity::new(self.entity_id.into(), vel); + if let Ok(data) = client.serialize_packet(&motion) { + client.try_enqueue_packet(data); + } + } + } + + /// Sends despawn packet to a player leaving visibility range. + pub fn remove_pairing(&self, player: &Arc) { + let entity_ids = [self.entity_id.into()]; + match player.client.as_ref() { + ClientPlatform::Java(client) => { + let packet = CRemoveEntities::new(&entity_ids); + if let Ok(data) = client.serialize_packet(&packet) { + client.try_enqueue_packet(data); + } + } + ClientPlatform::Bedrock(client) => { + let packet = CRemoveActor::new(VarLong(i64::from(self.entity_id))); + if let Ok(data) = client.serialize_packet(&packet) { + client.try_enqueue_packet(data); + } + } + } + } + + /// Broadcasts removal of this entity to all current watchers. + pub fn broadcast_removed(&self, world: &World) { + let entity_ids = [self.entity_id.into()]; + let je_packet = CRemoveEntities::new(&entity_ids); + let be_packet = CRemoveActor::new(VarLong(i64::from(self.entity_id))); + + let players = world.players.load(); + let recipients = players + .iter() + .filter(|p| self.seen_by.contains(&p.gameprofile.id)); + + let mut java_recipients = Vec::new(); + let mut bedrock_recipients = Vec::new(); + for p in recipients { + match p.client.as_ref() { + ClientPlatform::Java(_) => java_recipients.push(p), + ClientPlatform::Bedrock(be_client) => bedrock_recipients.push(be_client), + } + } + let recipients_by_version = + World::collect_java_recipients_by_version(java_recipients.into_iter()); + World::broadcast_java_grouped(&je_packet, recipients_by_version); + World::broadcast_bedrock_grouped(&be_packet, bedrock_recipients.into_iter()); + + self.seen_by.clear(); + } + + /// Removes a player by UUID without sending despawn packet (used on disconnect). + pub fn remove_player(&self, player_uuid: &Uuid) { + self.seen_by.remove(player_uuid); + } + + /// Sends a Java client packet to all tracking players. + pub fn send_to_tracking_players(&self, packet: &P, world: &World) { + let players = world.players.load(); + let recipients = players + .iter() + .filter(|p| self.seen_by.contains(&p.gameprofile.id)); + let recipients_by_version = World::collect_java_recipients_by_version(recipients); + World::broadcast_java_grouped(packet, recipients_by_version); + } + + /// Sends a Bedrock client packet to all tracking players. + pub fn send_to_tracking_players_bedrock( + &self, + packet: &P, + world: &World, + ) { + let players = world.players.load(); + let recipients = players.iter().filter_map(|p| { + if self.seen_by.contains(&p.gameprofile.id) + && let ClientPlatform::Bedrock(client) = p.client.as_ref() + { + return Some(client); + } + None + }); + World::broadcast_bedrock_grouped(packet, recipients); + } + + /// Sends an editioned packet (Java + Bedrock) to all tracking players. + pub fn send_to_tracking_players_editioned( + &self, + je_packet: &J, + be_packet: &B, + world: &World, + ) { + let players = world.players.load(); + let recipients = players + .iter() + .filter(|p| self.seen_by.contains(&p.gameprofile.id)); + + let mut java_recipients = Vec::new(); + let mut bedrock_recipients = Vec::new(); + for p in recipients { + match p.client.as_ref() { + ClientPlatform::Java(_) => java_recipients.push(p), + ClientPlatform::Bedrock(be_client) => bedrock_recipients.push(be_client), + } + } + let recipients_by_version = + World::collect_java_recipients_by_version(java_recipients.into_iter()); + World::broadcast_java_grouped(je_packet, recipients_by_version); + World::broadcast_bedrock_grouped(be_packet, bedrock_recipients.into_iter()); + } + + /// Sends a packet to all tracking players and the entity itself if it is a player. + pub fn send_to_tracking_players_and_self( + &self, + packet: &P, + world: &World, + ) { + self.send_to_tracking_players(packet, world); + if let Some(player) = self.entity.get_player() { + player.try_send_client_packet(packet); + } + } + + /// Sends an editioned packet to all tracking players and the entity itself if it is a player. + pub fn send_to_tracking_players_and_self_editioned< + J: ClientPacket + Sync, + B: BClientPacket + Sync, + >( + &self, + je_packet: &J, + be_packet: &B, + world: &World, + ) { + self.send_to_tracking_players_editioned(je_packet, be_packet, world); + if let Some(player) = self.entity.get_player() { + player.try_enqueue_packet_editioned(je_packet, be_packet); + } + } + + /// Sends a packet to tracking players filtered by predicate. + pub fn send_to_tracking_players_filtered bool>( + &self, + packet: &P, + world: &World, + filter: F, + ) { + let players = world.players.load(); + let recipients = players + .iter() + .filter(|p| self.seen_by.contains(&p.gameprofile.id) && filter(p)); + let recipients_by_version = World::collect_java_recipients_by_version(recipients); + World::broadcast_java_grouped(packet, recipients_by_version); + } + + /// Sends an editioned packet to tracking players filtered by predicate. + pub fn send_to_tracking_players_filtered_editioned< + J: ClientPacket + Sync, + B: BClientPacket + Sync, + F: Fn(&Player) -> bool, + >( + &self, + je_packet: &J, + be_packet: &B, + world: &World, + filter: F, + ) { + let players = world.players.load(); + let recipients = players + .iter() + .filter(|p| self.seen_by.contains(&p.gameprofile.id) && filter(p)); + + let mut java_recipients = Vec::new(); + let mut bedrock_recipients = Vec::new(); + for p in recipients { + match p.client.as_ref() { + ClientPlatform::Java(_) => java_recipients.push(p), + ClientPlatform::Bedrock(be_client) => bedrock_recipients.push(be_client), + } + } + let recipients_by_version = + World::collect_java_recipients_by_version(java_recipients.into_iter()); + World::broadcast_java_grouped(je_packet, recipients_by_version); + World::broadcast_bedrock_grouped(be_packet, bedrock_recipients.into_iter()); + } +} + +/// The entity tracking system for a world, corresponding to Vanilla's `ChunkMap.entityMap`. +pub struct EntityTracker { + pub entity_map: DashMap>, +} + +impl Default for EntityTracker { + fn default() -> Self { + Self::new() + } +} + +impl EntityTracker { + #[must_use] + pub fn new() -> Self { + Self { + entity_map: DashMap::new(), + } + } + + #[must_use] + pub fn get_tracked_entity(&self, entity_id: i32) -> Option> { + self.entity_map.get(&entity_id).map(|r| r.value().clone()) + } + + #[must_use] + pub fn has_entity_with_id(&self, entity_id: i32) -> bool { + self.entity_map.contains_key(&entity_id) + } + + #[must_use] + pub fn is_tracked_by_any_player(&self, entity_id: i32) -> bool { + self.entity_map + .get(&entity_id) + .is_some_and(|t| !t.seen_by.is_empty()) + } + + pub fn add_entity(&self, entity: &Arc, world: &World) { + let entity_type = entity.get_entity().entity_type; + let range = entity_type.client_tracking_range; + if range == 0 { + return; + } + let update_interval = entity_type.update_interval; + let track_deltas = entity_type.track_deltas; + let entity_id = entity.get_entity().entity_id; + + let tracked = Arc::new(TrackedEntity::new( + entity.clone(), + range, + update_interval, + track_deltas, + )); + self.entity_map.insert(entity_id, tracked.clone()); + + let players = world.players.load(); + tracked.update_players(players.as_ref(), world); + + // If the newly added entity is a player, update all other tracked entities for this player + if let Some(player) = entity.get_player() + && let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id) + { + for entry in &self.entity_map { + if *entry.key() != entity_id { + entry.value().update_player(&player_arc, world); + } + } + } + } + + pub fn remove_entity(&self, entity: &dyn EntityBase, world: &World) { + let entity_id = entity.get_entity().entity_id; + if let Some(player) = entity.get_player() { + let player_id = player.gameprofile.id; + for entry in &self.entity_map { + entry.value().remove_player(&player_id); + } + } + + if let Some((_, tracked)) = self.entity_map.remove(&entity_id) { + tracked.broadcast_removed(world); + } + } + + pub fn update_player_position(&self, player: &Arc, world: &World) { + for entry in &self.entity_map { + if *entry.key() == player.get_entity().entity_id { + let players = world.players.load(); + entry.value().update_players(players.as_ref(), world); + } else { + entry.value().update_player(player, world); + } + } + } + + pub fn update_entity_position(&self, entity: &dyn EntityBase, world: &World) { + if let Some(tracked) = self.entity_map.get(&entity.get_entity().entity_id) { + let players = world.players.load(); + tracked.update_players(players.as_ref(), world); + } + } + + pub fn update_all(&self, world: &World) { + let players = world.players.load(); + for entry in &self.entity_map { + entry.value().update_players(players.as_ref(), world); + } + } +} diff --git a/crates/pumpkin/src/world/mod.rs b/crates/pumpkin/src/world/mod.rs index 9fd3660b8..1b9bbef52 100644 --- a/crates/pumpkin/src/world/mod.rs +++ b/crates/pumpkin/src/world/mod.rs @@ -116,7 +116,7 @@ use pumpkin_protocol::{ java::{ self, client::play::{ - CBlockEntityData, CEntityStatus, CGameEvent, CLogin, CMultiBlockUpdate, + CBlockEntityData, CDamageEvent, CEntityStatus, CGameEvent, CLogin, CMultiBlockUpdate, CPlayerChatMessage, CPlayerInfoUpdate, CRemoveEntities, CRemovePlayerInfo, CSetSelectedSlot, CSoundEffect, CSpawnEntity, FilterType, GameEvent, InitChat, PlayerAction, PlayerInfoFlags, @@ -160,6 +160,7 @@ pub mod bossbar; pub mod custom_bossbar; pub mod dragon_fight; pub mod end_podium; +pub mod entity_tracker; pub mod natural_spawner; pub mod scoreboard; pub mod weather; @@ -280,6 +281,8 @@ pub struct World { pub custom_data: std::sync::Mutex, /// Persistent custom data for block entities at specific positions pub custom_block_entity_data: DashMap, + /// Entity tracker responsible for tracking entity visibility and sending delta/status packets to watchers. + pub entity_tracker: entity_tracker::EntityTracker, } #[derive(Clone, Copy)] @@ -403,6 +406,7 @@ impl World { block_entities: DashMap::new(), custom_data: std::sync::Mutex::new(custom_data), custom_block_entity_data: DashMap::new(), + entity_tracker: entity_tracker::EntityTracker::new(), } } @@ -546,14 +550,15 @@ impl World { } } - /// Sends an entity status update to all players tracking the specified entity. - pub fn send_entity_status( + /// Broadcasts an entity status update / event to all players tracking the specified entity, + /// and to the entity itself if it is a player. + /// Matching Vanilla's `ServerLevel.broadcastEntityEvent(entity, event)`. + pub fn broadcast_entity_event( &self, entity: &Entity, java_status: EntityStatus, bedrock_status: Option, ) { - let chunk_pos = entity.chunk_pos.load(); let je_packet = CEntityStatus::new(entity.entity_id, java_status as i8); if let Some(be_event) = bedrock_status { let be_packet = SActorEvent { @@ -562,14 +567,44 @@ impl World { data: VarInt(0), fire_at_position: None, }; - self.broadcast_to_chunk_editioned(chunk_pos, &je_packet, &be_packet); + self.send_to_tracking_players_and_self_editioned(entity, &je_packet, &be_packet); } else { - self.broadcast_to_chunk(chunk_pos, &je_packet); + self.send_to_tracking_players_and_self(entity, &je_packet); } } + /// Broadcasts a damage event to all players tracking the specified entity, + /// and to the entity itself if it is a player. + /// Matching Vanilla's `ServerLevel.broadcastDamageEvent(entity, source)`. + pub fn broadcast_damage_event( + &self, + entity: &Entity, + damage_type_id: i32, + source_entity_id: Option, + cause_entity_id: Option, + position: Option>, + ) { + let je_packet = CDamageEvent::new( + entity.entity_id.into(), + damage_type_id.into(), + source_entity_id.map(Into::into), + cause_entity_id.map(Into::into), + position, + ); + self.send_to_tracking_players_and_self(entity, &je_packet); + } + + /// Sends an entity status update to all players tracking the specified entity. + pub fn send_entity_status( + &self, + entity: &Entity, + java_status: EntityStatus, + bedrock_status: Option, + ) { + self.broadcast_entity_event(entity, java_status, bedrock_status); + } + pub fn send_remove_mob_effect(&self, entity: &Entity, effect_type: &'static StatusEffect) { - let chunk_pos = entity.chunk_pos.load(); let je_packet = CRemoveMobEffect::new(entity.entity_id.into(), VarInt(i32::from(effect_type.id))); @@ -583,11 +618,10 @@ impl World { tick: VarULong(0), ambient: false, }; - self.broadcast_to_chunk_editioned(chunk_pos, &je_packet, &be_packet); + self.send_to_tracking_players_and_self_editioned(entity, &je_packet, &be_packet); } pub fn send_add_mob_effect(&self, entity: &Entity, effect: &pumpkin_data::potion::Effect) { - let chunk_pos = entity.chunk_pos.load(); let mut flags: i8 = 0; if effect.ambient { flags |= 0x01; @@ -618,7 +652,91 @@ impl World { ambient: effect.ambient, }; - self.broadcast_to_chunk_editioned(chunk_pos, &je_packet, &be_packet); + self.send_to_tracking_players_and_self_editioned(entity, &je_packet, &be_packet); + } + + pub fn send_to_tracking_players(&self, entity: &Entity, packet: &P) { + if let Some(tracked) = self.entity_tracker.get_tracked_entity(entity.entity_id) { + tracked.send_to_tracking_players(packet, self); + } + } + + pub fn send_to_tracking_players_bedrock( + &self, + entity: &Entity, + packet: &P, + ) { + if let Some(tracked) = self.entity_tracker.get_tracked_entity(entity.entity_id) { + tracked.send_to_tracking_players_bedrock(packet, self); + } + } + + pub fn send_to_tracking_players_editioned( + &self, + entity: &Entity, + je_packet: &J, + be_packet: &B, + ) { + if let Some(tracked) = self.entity_tracker.get_tracked_entity(entity.entity_id) { + tracked.send_to_tracking_players_editioned(je_packet, be_packet, self); + } + } + + pub fn send_to_tracking_players_and_self( + &self, + entity: &Entity, + packet: &P, + ) { + if let Some(tracked) = self.entity_tracker.get_tracked_entity(entity.entity_id) { + tracked.send_to_tracking_players_and_self(packet, self); + } + } + + pub fn send_to_tracking_players_and_self_editioned< + J: ClientPacket + Sync, + B: BClientPacket + Sync, + >( + &self, + entity: &Entity, + je_packet: &J, + be_packet: &B, + ) { + if let Some(tracked) = self.entity_tracker.get_tracked_entity(entity.entity_id) { + tracked.send_to_tracking_players_and_self_editioned(je_packet, be_packet, self); + } + } + + pub fn send_to_tracking_players_filtered bool>( + &self, + entity: &Entity, + packet: &P, + filter: F, + ) { + if let Some(tracked) = self.entity_tracker.get_tracked_entity(entity.entity_id) { + tracked.send_to_tracking_players_filtered(packet, self, filter); + } + } + + pub fn send_to_tracking_players_filtered_editioned< + J: ClientPacket + Sync, + B: BClientPacket + Sync, + F: Fn(&Player) -> bool, + >( + &self, + entity: &Entity, + je_packet: &J, + be_packet: &B, + filter: F, + ) { + if let Some(tracked) = self.entity_tracker.get_tracked_entity(entity.entity_id) { + tracked.send_to_tracking_players_filtered_editioned(je_packet, be_packet, self, filter); + } + } + + #[must_use] + pub fn is_tracked_by_any_player(&self, entity: &Entity) -> bool { + self.entity_tracker + .is_tracked_by_any_player(entity.entity_id) } pub fn set_difficulty(&self, difficulty: Difficulty) { @@ -1323,6 +1441,8 @@ impl World { }); let entity_elapsed = t_entities.elapsed(); + self.entity_tracker.update_all(self); + let mut block_entities: Vec> = Vec::new(); for chunk_pos in active_chunks.iter() { if let Some(chunk_block_entities) = self.block_entities.get(chunk_pos) { @@ -3788,13 +3908,7 @@ impl World { container_id: 0, }; - let chunk_pos = from.get_entity().chunk_pos.load(); - self.broadcast_to_chunk_except_editioned( - chunk_pos, - &[from.get_entity().entity_uuid], - &je_packet, - &be_mob_equipment, - ); + self.send_to_tracking_players_editioned(from.get_entity(), &je_packet, &be_mob_equipment); } pub fn send_world_info( @@ -4095,11 +4209,7 @@ impl World { // observer sees the player in a world whose chunk manager doesn't match. self.remove_player(player, false).await; player.unload_watched_chunks(self).await; - player - .chunk_manager - .lock() - .unwrap_or_else(std::sync::PoisonError::into_inner) - .change_world(&self.level, destination.clone()); + player.change_world_chunks(&self.level, &destination); player.living_entity.entity.set_world(destination.clone()); destination.players.rcu(|current_list| { let mut new_list = (**current_list).clone(); @@ -4710,6 +4820,8 @@ impl World { new_list.push(player.clone()); new_list }); + self.entity_tracker + .add_entity(&(player.clone() as Arc), self); Ok(()) } @@ -4751,6 +4863,8 @@ impl World { new_list }); if let Some(ref player) = removed_player { + self.entity_tracker + .remove_entity(player.as_ref() as &dyn EntityBase, self); let uuid = player.gameprofile.id; let entity_id = player.entity_id(); @@ -4805,7 +4919,7 @@ impl World { #[expect(clippy::needless_pass_by_value)] pub fn spawn_entity_non_save(&self, entity: Arc) { let _base_entity = entity.get_entity(); - self.broadcast_entity_spawn(&entity); + self.entity_tracker.add_entity(&entity, self); self.spawn_state.load().add_entity(self, entity.as_ref()); self.entities.rcu(|current_entities| { @@ -4829,7 +4943,6 @@ impl World { return; } - self.broadcast_entity_spawn(&entity); entity.init_data_tracker(); self.add_entity_silent(entity); } @@ -4869,6 +4982,7 @@ impl World { // unload (see `save_entity`), never at spawn, so it can't be both live and // serialized at once (which would double it on the next reload). self.spawn_state.load().add_entity(self, entity.as_ref()); + self.entity_tracker.add_entity(&entity, self); self.entities.rcu(|current_entities| { let mut new_entities = (**current_entities).clone(); @@ -4889,18 +5003,12 @@ impl World { base_entity.removed.store(true, Ordering::Release); self.spawn_state.load().remove_entity(self, entity); + self.entity_tracker.remove_entity(entity, self); self.entities.rcu(|current_entities| { let mut new_entities = (**current_entities).clone(); new_entities.retain(|e| e.get_entity().entity_uuid != base_entity.entity_uuid); new_entities }); - - let chunk_pos = base_entity.chunk_pos.load(); - self.broadcast_to_chunk_editioned( - chunk_pos, - &CRemoveEntities::new(&[base_entity.entity_id.into()]), - &CRemoveActor::new(VarLong(base_entity.entity_id as i64)), - ); } pub async fn remove_entities_in_chunks( @@ -4929,6 +5037,7 @@ impl World { }); for entity in entities_to_remove { + self.entity_tracker.remove_entity(entity.as_ref(), self); self.save_entity(&entity).await; self.spawn_state.load().remove_entity(self, entity.as_ref()); } diff --git a/crates/pumpkin/src/world/natural_spawner.rs b/crates/pumpkin/src/world/natural_spawner.rs index 9b21dbd31..3cb4cd9c5 100644 --- a/crates/pumpkin/src/world/natural_spawner.rs +++ b/crates/pumpkin/src/world/natural_spawner.rs @@ -11,7 +11,6 @@ use pumpkin_data::tag::Taggable; use pumpkin_data::tag::WorldgenBiome::MINECRAFT_REDUCE_WATER_AMBIENT_SPAWNS; use pumpkin_data::{Block, BlockDirection, BlockState}; use pumpkin_util::GameMode; -use pumpkin_util::math::boundingbox::{BoundingBox, EntityDimensions}; use pumpkin_util::math::get_section_cord; use pumpkin_util::math::position::BlockPos; use pumpkin_util::math::vector2::Vector2; @@ -826,16 +825,10 @@ pub fn is_valid_spawn_position_for_type( if !check_spawn_rules(entity_type, world, block_pos, is_thundering) { return false; } - // TODO: we should use getSpawnBox, but this is only modified for slimes and magma slimes - if !world.is_space_empty(BoundingBox::new_from_pos( + if !world.is_space_empty(entity_type.get_spawn_bounding_box( f64::from(block_pos.0.x) + 0.5, f64::from(block_pos.0.y), f64::from(block_pos.0.z) + 0.5, - &EntityDimensions { - width: entity_type.dimension[0], - height: entity_type.dimension[1], - eye_height: entity_type.eye_height, - }, )) { return false; } diff --git a/crates/pumpkin/src/world/scoreboard.rs b/crates/pumpkin/src/world/scoreboard.rs index 78529507b..9021bd369 100644 --- a/crates/pumpkin/src/world/scoreboard.rs +++ b/crates/pumpkin/src/world/scoreboard.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use pumpkin_data::scoreboard::ScoreboardDisplaySlot; use pumpkin_protocol::{ @@ -114,10 +114,10 @@ impl ScoreboardTarget for NoTarget { #[derive(Clone, Debug, Default)] pub struct Scoreboard { - objectives: HashMap, - display_slots: HashMap, - scores: HashMap>, - teams: HashMap, + objectives: FxHashMap, + display_slots: FxHashMap, + scores: FxHashMap>, + teams: FxHashMap, } impl Scoreboard { @@ -127,7 +127,7 @@ impl Scoreboard { } #[must_use] - pub const fn get_objectives(&self) -> &HashMap { + pub const fn get_objectives(&self) -> &FxHashMap { &self.objectives } @@ -141,7 +141,7 @@ impl Scoreboard { } #[must_use] - pub const fn get_display_slots(&self) -> &HashMap { + pub const fn get_display_slots(&self) -> &FxHashMap { &self.display_slots } @@ -151,7 +151,7 @@ impl Scoreboard { } #[must_use] - pub const fn get_scores(&self) -> &HashMap> { + pub const fn get_scores(&self) -> &FxHashMap> { &self.scores } @@ -170,13 +170,13 @@ impl Scoreboard { pub fn get_scores_for_objective( &self, objective_name: &str, - ) -> Option<&HashMap> { + ) -> Option<&FxHashMap> { self.scores.get(objective_name) } #[must_use] - pub fn get_scores_for_entity(&self, entity_name: &str) -> HashMap { - let mut entity_scores = HashMap::new(); + pub fn get_scores_for_entity(&self, entity_name: &str) -> FxHashMap { + let mut entity_scores = FxHashMap::default(); for (obj_name, obj_scores) in &self.scores { if let Some(score) = obj_scores.get(entity_name) { entity_scores.insert(obj_name.clone(), score); @@ -186,7 +186,7 @@ impl Scoreboard { } #[must_use] - pub const fn get_teams(&self) -> &HashMap { + pub const fn get_teams(&self) -> &FxHashMap { &self.teams } @@ -859,9 +859,9 @@ pub struct BedrockObjective { #[derive(Clone, Debug, Default)] pub struct BedrockScoreboard { - pub objectives: HashMap, - pub display_slots: HashMap, - pub scores: HashMap<(String, String), i32>, + pub objectives: FxHashMap, + pub display_slots: FxHashMap, + pub scores: FxHashMap<(String, String), i32>, } impl BedrockScoreboard { diff --git a/tools/pumpkin-codegen/src/entity_type.rs b/tools/pumpkin-codegen/src/entity_type.rs index 6e5a6209d..2f418ff51 100644 --- a/tools/pumpkin-codegen/src/entity_type.rs +++ b/tools/pumpkin-codegen/src/entity_type.rs @@ -36,10 +36,18 @@ pub struct EntityType { pub category: MobCategory, /// Whether this entity can spawn far from the player (beyond normal spawn range). pub can_spawn_far_from_player: bool, + /// Client tracking range in chunks. + pub client_tracking_range: u32, + /// Update interval in ticks. + pub update_interval: u32, + /// Whether movement deltas should be tracked. + pub track_deltas: bool, /// Bounding box dimensions as `[width, height]` in blocks. pub dimension: [f32; 2], /// Eye height in blocks, used for line-of-sight calculations. pub eye_height: f32, + /// Scale factor for spawn dimensions (e.g. slimes/magma cubes). + pub spawn_dimensions_scale: f32, /// Spawn location restrictions for natural spawning. pub spawn_restriction: SpawnRestriction, } @@ -173,6 +181,7 @@ impl ToTokens for NamedEntityType<'_> { let dimension0 = entity.dimension[0]; let dimension1 = entity.dimension[1]; + let spawn_dimensions_scale = entity.spawn_dimensions_scale; let loot_table = if let Some(table) = &entity.loot_table { let table_tokens = table.to_token_stream(); @@ -182,6 +191,9 @@ impl ToTokens for NamedEntityType<'_> { }; let experience_reward = entity.experience_reward.unwrap_or(0); + let client_tracking_range = entity.client_tracking_range; + let update_interval = entity.update_interval; + let track_deltas = entity.track_deltas; tokens.extend(quote! { EntityType { @@ -197,9 +209,13 @@ impl ToTokens for NamedEntityType<'_> { fire_immune: #fire_immune, category: &#spawn_category, can_spawn_far_from_player: #can_spawn_far_from_player, + client_tracking_range: #client_tracking_range, + update_interval: #update_interval, + track_deltas: #track_deltas, loot_table: #loot_table, dimension: [#dimension0, #dimension1], // Correctly construct the array eye_height: #eye_height, + spawn_dimensions_scale: #spawn_dimensions_scale, spawn_restriction: #spawn_restriction, resource_name: #name, } @@ -250,6 +266,8 @@ pub fn build() -> TokenStream { use crate::sound::Sound; use pumpkin_util::loot_table::*; use pumpkin_util::HeightMap; + use pumpkin_util::math::boundingbox::BoundingBox; + use pumpkin_util::math::vector3::Vector3; use std::hash::Hash; #[derive(Debug, Clone)] @@ -266,9 +284,13 @@ pub fn build() -> TokenStream { pub fire_immune: bool, pub category: &'static MobCategory, pub can_spawn_far_from_player: bool, + pub client_tracking_range: u32, + pub update_interval: u32, + pub track_deltas: bool, pub loot_table: Option, pub dimension: [f32; 2], pub eye_height: f32, + pub spawn_dimensions_scale: f32, pub spawn_restriction: SpawnRestriction, pub resource_name: &'static str, } @@ -423,6 +445,31 @@ pub fn build() -> TokenStream { _ => None } } + + #[must_use] + pub const fn width(&self) -> f32 { + self.dimension[0] + } + + #[must_use] + pub const fn height(&self) -> f32 { + self.dimension[1] + } + + #[must_use] + pub fn get_spawn_bounding_box(&self, x: f64, y: f64, z: f64) -> BoundingBox { + let half_width = f64::from(self.spawn_dimensions_scale * self.dimension[0] / 2.0); + let height = f64::from(self.spawn_dimensions_scale * self.dimension[1]); + BoundingBox::new( + Vector3::new(x - half_width, y, z - half_width), + Vector3::new(x + half_width, y + height, z + half_width), + ) + } + + #[must_use] + pub fn get_spawn_aabb(&self, x: f64, y: f64, z: f64) -> BoundingBox { + self.get_spawn_bounding_box(x, y, z) + } } impl IDSetContent for EntityType {