diff --git a/Cargo.lock b/Cargo.lock
index 747a262b..a468a521 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -43,9 +43,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "0.7.19"
+version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
@@ -82,9 +82,9 @@ dependencies = [
[[package]]
name = "async-trait"
-version = "0.1.58"
+version = "0.1.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
+checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
dependencies = [
"proc-macro2",
"quote",
@@ -182,6 +182,7 @@ version = "0.4.0"
dependencies = [
"azalea-buf-macros",
"byteorder",
+ "log",
"serde_json",
"thiserror",
"tokio",
@@ -203,6 +204,7 @@ version = "0.4.0"
dependencies = [
"azalea-buf",
"azalea-language",
+ "log",
"once_cell",
"serde",
"serde_json",
@@ -380,7 +382,7 @@ dependencies = [
"cc",
"cfg-if",
"libc",
- "miniz_oxide",
+ "miniz_oxide 0.5.4",
"object",
"rustc-demangle",
]
@@ -446,9 +448,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
-version = "1.2.1"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
+checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
[[package]]
name = "cast"
@@ -458,9 +460,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
-version = "1.0.76"
+version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
[[package]]
name = "cfb8"
@@ -601,9 +603,9 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.11"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
@@ -614,9 +616,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
-version = "0.8.12"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
@@ -661,9 +663,9 @@ checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
[[package]]
name = "digest"
-version = "0.10.5"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer",
"crypto-common",
@@ -726,12 +728,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flate2"
-version = "1.0.24"
+version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [
"crc32fast",
- "miniz_oxide",
+ "miniz_oxide 0.6.2",
]
[[package]]
@@ -1026,9 +1028,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "1.9.1"
+version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
@@ -1096,9 +1098,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.137"
+version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "linked-hash-map"
@@ -1148,9 +1150,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
-version = "0.6.5"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
@@ -1170,6 +1172,15 @@ dependencies = [
"adler",
]
+[[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
[[package]]
name = "mio"
version = "0.8.5"
@@ -1326,9 +1337,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "openssl"
-version = "0.10.42"
+version = "0.10.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13"
+checksum = "020433887e44c27ff16365eaa2d380547a94544ad509aff6eb5b6e3e0b27b376"
dependencies = [
"bitflags",
"cfg-if",
@@ -1358,9 +1369,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
-version = "0.9.77"
+version = "0.9.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a"
+checksum = "07d5c8cb6e57b3a3612064d7b18b117912b4ce70955c2504d4b741c9e244b132"
dependencies = [
"autocfg",
"cc",
@@ -1381,9 +1392,9 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.4"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
+checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
dependencies = [
"backtrace",
"cfg-if",
@@ -1523,11 +1534,10 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.5.3"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
dependencies = [
- "autocfg",
"crossbeam-deque",
"either",
"rayon-core",
@@ -1535,9 +1545,9 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.9.3"
+version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
@@ -1588,9 +1598,9 @@ dependencies = [
[[package]]
name = "reqwest"
-version = "0.11.12"
+version = "0.11.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc"
+checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
dependencies = [
"base64",
"bytes",
@@ -1696,9 +1706,9 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.148"
+version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
+checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
dependencies = [
"serde_derive",
]
@@ -1715,9 +1725,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.148"
+version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
+checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4"
dependencies = [
"proc-macro2",
"quote",
@@ -1726,9 +1736,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.87"
+version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
+checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
dependencies = [
"itoa 1.0.4",
"ryu",
@@ -1749,9 +1759,9 @@ dependencies = [
[[package]]
name = "sha-1"
-version = "0.10.0"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
+checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -1905,9 +1915,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
-version = "1.21.2"
+version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
+checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
dependencies = [
"autocfg",
"bytes",
@@ -1925,9 +1935,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
-version = "1.8.0"
+version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
+checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
dependencies = [
"proc-macro2",
"quote",
@@ -2053,9 +2063,9 @@ checksum = "4fc45e9608894c9fefd9792d880560280086d73a4d8c8cb7436f27ca98550fb5"
[[package]]
name = "typenum"
-version = "1.15.0"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "unicode-bidi"
diff --git a/README.md b/README.md
index f9e77191..5bb99dca 100755
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ A collection of Rust crates for making Minecraft bots, clients, and tools.
-*Currently supported Minecraft version: `1.19.2`.*
+*Currently supported Minecraft version: `1.19.3`.*
## ⚠️ Azalea is still very unfinished, though most crates are in a somewhat useable state
diff --git a/azalea-auth/src/game_profile.rs b/azalea-auth/src/game_profile.rs
index 333f926f..39cd29e7 100755
--- a/azalea-auth/src/game_profile.rs
+++ b/azalea-auth/src/game_profile.rs
@@ -2,7 +2,7 @@ use azalea_buf::McBuf;
use std::collections::HashMap;
use uuid::Uuid;
-#[derive(McBuf, Debug, Clone)]
+#[derive(McBuf, Debug, Clone, Default)]
pub struct GameProfile {
pub uuid: Uuid,
pub name: String,
diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs
index 10779937..226542dc 100755
--- a/azalea-block/src/blocks.rs
+++ b/azalea-block/src/blocks.rs
@@ -178,7 +178,7 @@ make_block_states! {
Down,
},
"triggered" => bool,
- "instrument" => Instrument {
+ "instrument" => Sound {
Harp,
Basedrum,
Snare,
@@ -195,6 +195,13 @@ make_block_states! {
Bit,
Banjo,
Pling,
+ Zombie,
+ Skeleton,
+ Creeper,
+ Dragon,
+ WitherSkeleton,
+ Piglin,
+ CustomHead,
},
"note" => NoteBlockNote {
_0,
@@ -254,6 +261,12 @@ make_block_states! {
},
"short" => bool,
"unstable" => bool,
+ "slot_0_occupied" => bool,
+ "slot_1_occupied" => bool,
+ "slot_2_occupied" => bool,
+ "slot_3_occupied" => bool,
+ "slot_4_occupied" => bool,
+ "slot_5_occupied" => bool,
"age" => FireAge {
_0,
_1,
@@ -478,6 +491,24 @@ make_block_states! {
_14,
_15,
},
+ "rotation" => BambooSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
"hinge" => Hinge {
Left,
Right,
@@ -495,6 +526,187 @@ make_block_states! {
NorthWest,
NorthEast,
},
+ "attached" => bool,
+ "rotation" => OakHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => SpruceHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => BirchHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => AcaciaHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => JungleHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => DarkOakHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => CrimsonHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => WarpedHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => MangroveHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
+ "rotation" => BambooHangingSignRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
"face" => Face {
Floor,
Wall,
@@ -588,7 +800,11 @@ make_block_states! {
_6,
_7,
},
- "berries" => bool,
+ "down" => bool,
+ "north" => bool,
+ "south" => bool,
+ "up" => bool,
+ "west" => bool,
"in_wall" => bool,
"age" => NetherWartAge {
_0,
@@ -613,7 +829,6 @@ make_block_states! {
_1,
_2,
},
- "attached" => bool,
"disarmed" => bool,
"conditional" => bool,
"east" => EastWall {
@@ -764,6 +979,24 @@ make_block_states! {
_14,
_15,
},
+ "rotation" => PiglinHeadRotation {
+ _0,
+ _1,
+ _2,
+ _3,
+ _4,
+ _5,
+ _6,
+ _7,
+ _8,
+ _9,
+ _10,
+ _11,
+ _12,
+ _13,
+ _14,
+ _15,
+ },
"power" => LightWeightedPressurePlatePower {
_0,
_1,
@@ -1535,6 +1768,8 @@ make_block_states! {
Active,
Cooldown,
},
+ "south" => bool,
+ "west" => bool,
"bloom" => bool,
"can_summon" => bool,
"shrieking" => bool,
@@ -1549,7 +1784,7 @@ make_block_states! {
Up,
Down,
},
- "age" => _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25 {
+ "age" => CaveVinesAge {
_0,
_1,
_2,
@@ -1577,13 +1812,14 @@ make_block_states! {
_24,
_25,
},
+ "berries" => bool,
"tilt" => Tilt {
None,
Unstable,
Partial,
Full,
},
- "axis" => XYZ {
+ "axis" => CacheSize {
X,
Y,
Z,
@@ -1614,6 +1850,8 @@ make_block_states! {
acacia_planks => BlockBehavior::default(), {},
dark_oak_planks => BlockBehavior::default(), {},
mangrove_planks => BlockBehavior::default(), {},
+ bamboo_planks => BlockBehavior::default(), {},
+ bamboo_mosaic => BlockBehavior::default(), {},
oak_sapling => BlockBehavior::default(), {
stage: OakSaplingStage::_0,
},
@@ -1682,6 +1920,9 @@ make_block_states! {
muddy_mangrove_roots => BlockBehavior::default(), {
axis: Axis::Y,
},
+ bamboo_block => BlockBehavior::default(), {
+ axis: Axis::Y,
+ },
stripped_spruce_log => BlockBehavior::default(), {
axis: Axis::Y,
},
@@ -1703,6 +1944,9 @@ make_block_states! {
stripped_mangrove_log => BlockBehavior::default(), {
axis: Axis::Y,
},
+ stripped_bamboo_block => BlockBehavior::default(), {
+ axis: Axis::Y,
+ },
oak_wood => BlockBehavior::default(), {
axis: Axis::Y,
},
@@ -1804,7 +2048,7 @@ make_block_states! {
chiseled_sandstone => BlockBehavior::default(), {},
cut_sandstone => BlockBehavior::default(), {},
note_block => BlockBehavior::default(), {
- instrument: Instrument::Harp,
+ instrument: Sound::Harp,
note: NoteBlockNote::_0,
powered: false,
},
@@ -1961,6 +2205,15 @@ make_block_states! {
unstable: false,
},
bookshelf => BlockBehavior::default(), {},
+ chiseled_bookshelf => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ slot_0_occupied: false,
+ slot_1_occupied: false,
+ slot_2_occupied: false,
+ slot_3_occupied: false,
+ slot_4_occupied: false,
+ slot_5_occupied: false,
+ },
mossy_cobblestone => BlockBehavior::default(), {},
obsidian => BlockBehavior::default(), {},
torch => BlockBehavior::default(), {},
@@ -2037,6 +2290,10 @@ make_block_states! {
rotation: MangroveSignRotation::_0,
waterlogged: false,
},
+ bamboo_sign => BlockBehavior::default(), {
+ rotation: BambooSignRotation::_0,
+ waterlogged: false,
+ },
oak_door => BlockBehavior::default(), {
facing: FacingCardinal::North,
half: Half::Lower,
@@ -2086,6 +2343,100 @@ make_block_states! {
facing: FacingCardinal::North,
waterlogged: false,
},
+ bamboo_wall_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ oak_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: OakHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ spruce_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: SpruceHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ birch_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: BirchHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ acacia_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: AcaciaHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ jungle_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: JungleHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ dark_oak_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: DarkOakHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ crimson_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: CrimsonHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ warped_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: WarpedHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ mangrove_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: MangroveHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ bamboo_hanging_sign => BlockBehavior::default(), {
+ attached: false,
+ rotation: BambooHangingSignRotation::_0,
+ waterlogged: false,
+ },
+ oak_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ spruce_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ birch_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ acacia_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ jungle_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ dark_oak_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ mangrove_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ crimson_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ warped_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
+ bamboo_wall_hanging_sign => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ waterlogged: false,
+ },
lever => BlockBehavior::default(), {
face: Face::Wall,
facing: FacingCardinal::North,
@@ -2122,6 +2473,9 @@ make_block_states! {
mangrove_pressure_plate => BlockBehavior::default(), {
powered: false,
},
+ bamboo_pressure_plate => BlockBehavior::default(), {
+ powered: false,
+ },
redstone_ore => BlockBehavior::default(), {
lit: false,
},
@@ -2260,6 +2614,13 @@ make_block_states! {
powered: false,
waterlogged: false,
},
+ bamboo_trapdoor => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ half: TopBottom::Bottom,
+ open: false,
+ powered: false,
+ waterlogged: false,
+ },
stone_bricks => BlockBehavior::default(), {},
mossy_stone_bricks => BlockBehavior::default(), {},
cracked_stone_bricks => BlockBehavior::default(), {},
@@ -2549,6 +2910,11 @@ make_block_states! {
facing: FacingCardinal::North,
powered: false,
},
+ bamboo_button => BlockBehavior::default(), {
+ face: Face::Wall,
+ facing: FacingCardinal::North,
+ powered: false,
+ },
skeleton_skull => BlockBehavior::default(), {
rotation: SkeletonSkullRotation::_0,
},
@@ -2585,6 +2951,12 @@ make_block_states! {
dragon_wall_head => BlockBehavior::default(), {
facing: FacingCardinal::North,
},
+ piglin_head => BlockBehavior::default(), {
+ rotation: PiglinHeadRotation::_0,
+ },
+ piglin_wall_head => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ },
anvil => BlockBehavior::default(), {
facing: FacingCardinal::North,
},
@@ -2786,6 +3158,18 @@ make_block_states! {
shape: StairShape::Straight,
waterlogged: false,
},
+ bamboo_stairs => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ half: TopBottom::Bottom,
+ shape: StairShape::Straight,
+ waterlogged: false,
+ },
+ bamboo_mosaic_stairs => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ half: TopBottom::Bottom,
+ shape: StairShape::Straight,
+ waterlogged: false,
+ },
slime_block => BlockBehavior::default(), {},
barrier => BlockBehavior::default(), {},
light => BlockBehavior::default(), {
@@ -3006,6 +3390,14 @@ make_block_states! {
kind: Type::Bottom,
waterlogged: false,
},
+ bamboo_slab => BlockBehavior::default(), {
+ kind: Type::Bottom,
+ waterlogged: false,
+ },
+ bamboo_mosaic_slab => BlockBehavior::default(), {
+ kind: Type::Bottom,
+ waterlogged: false,
+ },
stone_slab => BlockBehavior::default(), {
kind: Type::Bottom,
waterlogged: false,
@@ -3102,6 +3494,12 @@ make_block_states! {
open: false,
powered: false,
},
+ bamboo_fence_gate => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ in_wall: false,
+ open: false,
+ powered: false,
+ },
spruce_fence => BlockBehavior::default(), {
east: false,
north: false,
@@ -3144,6 +3542,13 @@ make_block_states! {
waterlogged: false,
west: false,
},
+ bamboo_fence => BlockBehavior::default(), {
+ east: false,
+ north: false,
+ south: false,
+ waterlogged: false,
+ west: false,
+ },
spruce_door => BlockBehavior::default(), {
facing: FacingCardinal::North,
half: Half::Lower,
@@ -3186,6 +3591,13 @@ make_block_states! {
open: false,
powered: false,
},
+ bamboo_door => BlockBehavior::default(), {
+ facing: FacingCardinal::North,
+ half: Half::Lower,
+ hinge: Hinge::Left,
+ open: false,
+ powered: false,
+ },
end_rod => BlockBehavior::default(), {
facing: FacingCubic::Up,
},
@@ -4355,7 +4767,7 @@ make_block_states! {
},
dripstone_block => BlockBehavior::default(), {},
cave_vines => BlockBehavior::default(), {
- age: _0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25::_0,
+ age: CaveVinesAge::_0,
berries: false,
},
cave_vines_plant => BlockBehavior::default(), {
@@ -4468,7 +4880,7 @@ make_block_states! {
cracked_deepslate_bricks => BlockBehavior::default(), {},
cracked_deepslate_tiles => BlockBehavior::default(), {},
infested_deepslate => BlockBehavior::default(), {
- axis: XYZ::Y,
+ axis: CacheSize::Y,
},
smooth_basalt => BlockBehavior::default(), {},
raw_iron_block => BlockBehavior::default(), {},
diff --git a/azalea-buf/Cargo.toml b/azalea-buf/Cargo.toml
old mode 100755
new mode 100644
index 01048ceb..d58e6733
--- a/azalea-buf/Cargo.toml
+++ b/azalea-buf/Cargo.toml
@@ -9,10 +9,11 @@ version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.4.0" }
+azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.4.0"}
byteorder = "^1.4.3"
+log = "0.4.17"
serde_json = {version = "^1.0", optional = true}
-thiserror = "^1.0.34"
+thiserror = "1.0.37"
tokio = {version = "^1.21.2", features = ["io-util", "net", "macros"]}
uuid = "^1.1.2"
diff --git a/azalea-buf/azalea-buf-macros/src/lib.rs b/azalea-buf/azalea-buf-macros/src/lib.rs
index a247db0f..4089b4b7 100755
--- a/azalea-buf/azalea-buf-macros/src/lib.rs
+++ b/azalea-buf/azalea-buf-macros/src/lib.rs
@@ -1,294 +1,30 @@
+mod read;
+mod write;
+
use proc_macro::TokenStream;
-use quote::{quote, ToTokens};
-use syn::{self, parse_macro_input, Data, DeriveInput, FieldsNamed, Ident};
-
-fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
- match data {
- syn::Data::Struct(syn::DataStruct { fields, .. }) => {
- let FieldsNamed { named, .. } = match fields {
- syn::Fields::Named(f) => f,
- _ => panic!("#[derive(McBuf)] can only be used on structs with named fields"),
- };
-
- let read_fields = named
- .iter()
- .map(|f| {
- let field_name = &f.ident;
- let field_type = &f.ty;
- // do a different buf.write_* for each field depending on the type
- // if it's a string, use buf.write_string
- match field_type {
- syn::Type::Path(_) | syn::Type::Array(_) => {
- if f.attrs.iter().any(|a| a.path.is_ident("var")) {
- quote! {
- let #field_name = azalea_buf::McBufVarReadable::var_read_from(buf)?;
- }
- } else {
- quote! {
- let #field_name = azalea_buf::McBufReadable::read_from(buf)?;
- }
- }
- }
- _ => panic!(
- "Error reading field {}: {}",
- field_name.clone().unwrap(),
- field_type.to_token_stream()
- ),
- }
- })
- .collect::>();
- let read_field_names = named.iter().map(|f| &f.ident).collect::>();
-
- quote! {
- impl azalea_buf::McBufReadable for #ident {
- fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result {
- #(#read_fields)*
- Ok(#ident {
- #(#read_field_names: #read_field_names),*
- })
- }
- }
- }
- }
- syn::Data::Enum(syn::DataEnum { variants, .. }) => {
- let mut match_contents = quote!();
- let mut variant_discrim: u32 = 0;
- let mut first = true;
- let mut first_reader = None;
- for variant in variants {
- let variant_name = &variant.ident;
- match &variant.discriminant.as_ref() {
- Some(d) => {
- variant_discrim = match &d.1 {
- syn::Expr::Lit(e) => match &e.lit {
- syn::Lit::Int(i) => i.base10_parse().unwrap(),
- _ => panic!("Error parsing enum discriminant as int"),
- },
- syn::Expr::Unary(_) => {
- panic!("Negative enum discriminants are not supported")
- }
- _ => {
- panic!("Error parsing enum discriminant as literal (is {:?})", d.1)
- }
- }
- }
- None => {
- if !first {
- variant_discrim += 1;
- }
- }
- }
- let reader = match variant.fields {
- syn::Fields::Named(_) => {
- panic!("writing named fields in enums is not supported")
- }
- syn::Fields::Unnamed(_) => quote! {
- Ok(Self::#variant_name(azalea_buf::McBufReadable::read_from(buf)?))
- },
- syn::Fields::Unit => quote! {
- Ok(Self::#variant_name)
- },
- };
- if first {
- first_reader = Some(reader.clone());
- first = false;
- };
-
- match_contents.extend(quote! {
- #variant_discrim => {
- #reader
- },
- });
- }
-
- let first_reader = first_reader.expect("There should be at least one variant");
-
- quote! {
- impl azalea_buf::McBufReadable for #ident {
- fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result {
- let id = azalea_buf::McBufVarReadable::var_read_from(buf)?;
- Self::read_from_id(buf, id)
- }
- }
-
- impl #ident {
- pub fn read_from_id(buf: &mut std::io::Cursor<&[u8]>, id: u32) -> Result {
- match id {
- #match_contents
- // you'd THINK this throws an error, but mojang decided to make it default for some reason
- _ => #first_reader
- }
- }
- }
- }
- }
- _ => panic!("#[derive(McBuf)] can only be used on structs"),
- }
-}
-
-fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
- match data {
- syn::Data::Struct(syn::DataStruct { fields, .. }) => {
- let FieldsNamed { named, .. } = match fields {
- syn::Fields::Named(f) => f,
- _ => panic!("#[derive(McBuf)] can only be used on structs with named fields"),
- };
-
- let write_fields = named
- .iter()
- .map(|f| {
- let field_name = &f.ident;
- let field_type = &f.ty;
- // do a different buf.write_* for each field depending on the type
- // if it's a string, use buf.write_string
- match field_type {
- syn::Type::Path(_) | syn::Type::Array(_) => {
- if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
- quote! {
- azalea_buf::McBufVarWritable::var_write_into(&self.#field_name, buf)?;
- }
- } else {
- quote! {
- azalea_buf::McBufWritable::write_into(&self.#field_name, buf)?;
- }
- }
- }
- _ => panic!(
- "Error writing field {}: {}",
- field_name.clone().unwrap(),
- field_type.to_token_stream()
- ),
- }
- })
- .collect::>();
-
- quote! {
- impl azalea_buf::McBufWritable for #ident {
- fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
- #(#write_fields)*
- Ok(())
- }
- }
- }
- }
- syn::Data::Enum(syn::DataEnum { variants, .. }) => {
- // remember whether it's a data variant so we can do an optimization later
- let mut is_data_enum = false;
- let mut match_arms = quote!();
- let mut match_arms_without_id = quote!();
- let mut variant_discrim: u32 = 0;
- let mut first = true;
- for variant in variants {
- match &variant.discriminant.as_ref() {
- Some(d) => {
- variant_discrim = match &d.1 {
- syn::Expr::Lit(e) => match &e.lit {
- syn::Lit::Int(i) => i.base10_parse().unwrap(),
- _ => panic!("Error parsing enum discriminant as int"),
- },
- syn::Expr::Unary(_) => {
- panic!("Negative enum discriminants are not supported")
- }
- _ => {
- panic!("Error parsing enum discriminant as literal (is {:?})", d.1)
- }
- }
- }
- None => {
- if first {
- first = false;
- } else {
- variant_discrim += 1;
- }
- }
- }
-
- match &variant.fields {
- syn::Fields::Named(_) => {
- panic!("Enum variants with named fields are not supported yet");
- }
- syn::Fields::Unit => {
- let variant_name = &variant.ident;
- match_arms.extend(quote! {
- Self::#variant_name => {
- azalea_buf::McBufVarWritable::var_write_into(variant_discrim, buf)?;
- }
- });
- match_arms_without_id.extend(quote! {
- Self::#variant_name => {}
- });
- }
- syn::Fields::Unnamed(_) => {
- is_data_enum = true;
- let variant_name = &variant.ident;
- match_arms.extend(quote! {
- Self::#variant_name(data) => {
- azalea_buf::McBufVarWritable::var_write_into(variant_discrim, buf)?;
- azalea_buf::McBufWritable::write_into(data, buf)?;
- }
- });
- match_arms_without_id.extend(quote! {
- Self::#variant_name(data) => {
- azalea_buf::McBufWritable::write_into(data, buf)?;
- }
- });
- }
- }
- }
- if is_data_enum {
- quote! {
- impl azalea_buf::McBufWritable for #ident {
- fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
- match self {
- #match_arms
- }
- Ok(())
- }
- }
- impl #ident {
- pub fn write_without_id(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
- match self {
- #match_arms_without_id
- }
- Ok(())
- }
- }
- }
- } else {
- // optimization: if it doesn't have data we can just do `as u32`
- quote! {
- impl azalea_buf::McBufWritable for #ident {
- fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
- azalea_buf::McBufVarWritable::var_write_into(&(*self as u32), buf)
- }
- }
- }
- }
- }
- _ => panic!("#[derive(McBuf)] can only be used on structs"),
- }
-}
+use quote::quote;
+use syn::{self, parse_macro_input, DeriveInput};
#[proc_macro_derive(McBufReadable, attributes(var))]
pub fn derive_mcbufreadable(input: TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
- create_impl_mcbufreadable(&ident, &data).into()
+ read::create_impl_mcbufreadable(&ident, &data).into()
}
#[proc_macro_derive(McBufWritable, attributes(var))]
pub fn derive_mcbufwritable(input: TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
- create_impl_mcbufwritable(&ident, &data).into()
+ write::create_impl_mcbufwritable(&ident, &data).into()
}
#[proc_macro_derive(McBuf, attributes(var))]
pub fn derive_mcbuf(input: TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
- let writable = create_impl_mcbufwritable(&ident, &data);
- let readable = create_impl_mcbufreadable(&ident, &data);
+ let writable = write::create_impl_mcbufwritable(&ident, &data);
+ let readable = read::create_impl_mcbufreadable(&ident, &data);
quote! {
#writable
#readable
diff --git a/azalea-buf/azalea-buf-macros/src/read.rs b/azalea-buf/azalea-buf-macros/src/read.rs
new file mode 100644
index 00000000..42050d6b
--- /dev/null
+++ b/azalea-buf/azalea-buf-macros/src/read.rs
@@ -0,0 +1,158 @@
+use proc_macro::TokenStream;
+use proc_macro2::Span;
+use quote::{quote, ToTokens};
+use syn::{
+ self, parse_macro_input, punctuated::Punctuated, token::Comma, Data, DeriveInput, Field,
+ FieldsNamed, Ident,
+};
+
+fn read_named_fields(
+ named: &Punctuated,
+) -> (Vec, Vec<&Option>) {
+ let read_fields = named
+ .iter()
+ .map(|f| {
+ let field_name = &f.ident;
+ let field_type = &f.ty;
+ // do a different buf.write_* for each field depending on the type
+ // if it's a string, use buf.write_string
+ match field_type {
+ syn::Type::Path(_) | syn::Type::Array(_) => {
+ if f.attrs.iter().any(|a| a.path.is_ident("var")) {
+ quote! {
+ let #field_name = azalea_buf::McBufVarReadable::var_read_from(buf)?;
+ }
+ } else {
+ quote! {
+ let #field_name = azalea_buf::McBufReadable::read_from(buf)?;
+ }
+ }
+ }
+ _ => panic!(
+ "Error reading field {}: {}",
+ field_name.clone().unwrap(),
+ field_type.to_token_stream()
+ ),
+ }
+ })
+ .collect::>();
+ let read_field_names = named.iter().map(|f| &f.ident).collect::>();
+
+ (read_fields, read_field_names)
+}
+
+pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
+ match data {
+ syn::Data::Struct(syn::DataStruct { fields, .. }) => {
+ let FieldsNamed { named, .. } = match fields {
+ syn::Fields::Named(f) => f,
+ _ => panic!("#[derive(McBuf)] can only be used on structs with named fields"),
+ };
+
+ let (read_fields, read_field_names) = read_named_fields(named);
+
+ quote! {
+ impl azalea_buf::McBufReadable for #ident {
+ fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result {
+ #(#read_fields)*
+ Ok(#ident {
+ #(#read_field_names: #read_field_names),*
+ })
+ }
+ }
+ }
+ }
+ syn::Data::Enum(syn::DataEnum { variants, .. }) => {
+ let mut match_contents = quote!();
+ let mut variant_discrim: u32 = 0;
+ let mut first = true;
+ let mut first_reader = None;
+ for variant in variants {
+ let variant_name = &variant.ident;
+ match &variant.discriminant.as_ref() {
+ Some(d) => {
+ variant_discrim = match &d.1 {
+ syn::Expr::Lit(e) => match &e.lit {
+ syn::Lit::Int(i) => i.base10_parse().unwrap(),
+ _ => panic!("Error parsing enum discriminant as int (is {:?})", e),
+ },
+ syn::Expr::Unary(_) => {
+ panic!("Negative enum discriminants are not supported")
+ }
+ _ => {
+ panic!("Error parsing enum discriminant as literal (is {:?})", d.1)
+ }
+ }
+ }
+ None => {
+ if !first {
+ variant_discrim += 1;
+ }
+ }
+ }
+ let reader = match &variant.fields {
+ syn::Fields::Named(f) => {
+ let (read_fields, read_field_names) = read_named_fields(&f.named);
+
+ quote! {
+ #(#read_fields)*
+ Ok(#ident::#variant_name {
+ #(#read_field_names: #read_field_names),*
+ })
+ }
+ }
+ syn::Fields::Unnamed(fields) => {
+ let mut reader_code = quote! {};
+ for f in &fields.unnamed {
+ if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
+ reader_code.extend(quote! {
+ Self::#variant_name(azalea_buf::McBufVarReadable::var_read_from(buf)?),
+ })
+ } else {
+ reader_code.extend(quote! {
+ Self::#variant_name(azalea_buf::McBufReadable::read_from(buf)?),
+ })
+ }
+ }
+ quote! { Ok(#reader_code) }
+ }
+ syn::Fields::Unit => quote! {
+ Ok(Self::#variant_name)
+ },
+ };
+ if first {
+ first_reader = Some(reader.clone());
+ first = false;
+ };
+
+ match_contents.extend(quote! {
+ #variant_discrim => {
+ #reader
+ },
+ });
+ }
+
+ let first_reader = first_reader.expect("There should be at least one variant");
+
+ quote! {
+ impl azalea_buf::McBufReadable for #ident {
+ fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result {
+ let id = azalea_buf::McBufVarReadable::var_read_from(buf)?;
+ Self::read_from_id(buf, id)
+ }
+ }
+
+ impl #ident {
+ pub fn read_from_id(buf: &mut std::io::Cursor<&[u8]>, id: u32) -> Result {
+ match id {
+ #match_contents
+ // you'd THINK this throws an error, but mojang decided to make it default for some reason
+ _ => {#first_reader}
+ }
+ }
+ }
+ }
+ }
+ _ => panic!("#[derive(McBuf)] can only be used on structs"),
+ }
+}
diff --git a/azalea-buf/azalea-buf-macros/src/write.rs b/azalea-buf/azalea-buf-macros/src/write.rs
new file mode 100644
index 00000000..a711dbdd
--- /dev/null
+++ b/azalea-buf/azalea-buf-macros/src/write.rs
@@ -0,0 +1,193 @@
+use proc_macro2::Span;
+use quote::{quote, ToTokens};
+use syn::{self, punctuated::Punctuated, token::Comma, Data, Field, FieldsNamed, Ident};
+
+fn write_named_fields(
+ named: &Punctuated,
+ ident_name: Option<&Ident>,
+) -> proc_macro2::TokenStream {
+ let write_fields = named.iter().map(|f| {
+ let field_name = &f.ident;
+ let field_type = &f.ty;
+ let ident_dot_field = match ident_name {
+ Some(ident) => quote! { ident.#field_name },
+ None => quote! { #field_name },
+ };
+ // do a different buf.write_* for each field depending on the type
+ // if it's a string, use buf.write_string
+ match field_type {
+ syn::Type::Path(_) | syn::Type::Array(_) => {
+ if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
+ quote! {
+ azalea_buf::McBufVarWritable::var_write_into(#ident_dot_field, buf)?;
+ }
+ } else {
+ quote! {
+ azalea_buf::McBufWritable::write_into(#ident_dot_field, buf)?;
+ }
+ }
+ }
+ _ => panic!(
+ "Error writing field {}: {}",
+ field_name.clone().unwrap(),
+ field_type.to_token_stream()
+ ),
+ }
+ });
+ quote! { #(#write_fields)* }
+}
+
+pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
+ match data {
+ syn::Data::Struct(syn::DataStruct { fields, .. }) => {
+ let FieldsNamed { named, .. } = match fields {
+ syn::Fields::Named(f) => f,
+ _ => panic!("#[derive(McBuf)] can only be used on structs with named fields"),
+ };
+
+ let write_fields =
+ write_named_fields(named, Some(&Ident::new("self", Span::call_site())));
+
+ quote! {
+ impl azalea_buf::McBufWritable for #ident {
+ fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
+ #write_fields
+ Ok(())
+ }
+ }
+ }
+ }
+ syn::Data::Enum(syn::DataEnum { variants, .. }) => {
+ // remember whether it's a data variant so we can do an optimization later
+ let mut is_data_enum = false;
+ let mut match_arms = quote!();
+ let mut match_arms_without_id = quote!();
+ let mut variant_discrim: u32 = 0;
+ let mut first = true;
+ for variant in variants {
+ match &variant.discriminant.as_ref() {
+ Some(d) => {
+ variant_discrim = match &d.1 {
+ syn::Expr::Lit(e) => match &e.lit {
+ syn::Lit::Int(i) => i.base10_parse().unwrap(),
+ // syn::Lit::Str(s) => s.value(),
+ _ => panic!("Error parsing enum discriminant as int (is {:?})", e),
+ },
+ syn::Expr::Unary(_) => {
+ panic!("Negative enum discriminants are not supported")
+ }
+ _ => {
+ panic!("Error parsing enum discriminant as literal (is {:?})", d.1)
+ }
+ }
+ }
+ None => {
+ if first {
+ first = false;
+ } else {
+ variant_discrim += 1;
+ }
+ }
+ }
+
+ let variant_name = &variant.ident;
+
+ // the variant number that we're going to write
+ let write_the_variant = quote! {
+ azalea_buf::McBufVarWritable::var_write_into(variant_discrim, buf)?;
+ };
+ match &variant.fields {
+ syn::Fields::Named(f) => {
+ is_data_enum = true;
+ let field_names = f
+ .named
+ .iter()
+ .map(|f| f.ident.clone().unwrap())
+ .collect::>();
+ let write_fields = write_named_fields(&f.named, None);
+ match_arms.extend(quote! {
+ Self::#variant_name { #(#field_names),* } => {
+ #write_the_variant
+ #write_fields
+ }
+ });
+ match_arms_without_id.extend(quote! {
+ Self::#variant_name { #(#field_names),* } => {
+ #write_fields
+ }
+ });
+ }
+ syn::Fields::Unit => {
+ match_arms.extend(quote! {
+ Self::#variant_name => {
+ #write_the_variant
+ }
+ });
+ match_arms_without_id.extend(quote! {
+ Self::#variant_name => {}
+ });
+ }
+ syn::Fields::Unnamed(fields) => {
+ is_data_enum = true;
+ let mut writers_code = quote! {};
+ let mut params_code = quote! {};
+ for (i, f) in fields.unnamed.iter().enumerate() {
+ let param_ident = Ident::new(&format!("data{i}"), Span::call_site());
+ params_code.extend(quote! { #param_ident, });
+ if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
+ writers_code.extend(quote! {
+ azalea_buf::McBufVarWritable::var_write_into(#param_ident, buf)?;
+ })
+ } else {
+ writers_code.extend(quote! {
+ azalea_buf::McBufWritable::write_into(#param_ident, buf)?;
+ })
+ }
+ }
+ match_arms.extend(quote! {
+ Self::#variant_name(#params_code) => {
+ #write_the_variant
+ #writers_code
+ }
+ });
+ match_arms_without_id.extend(quote! {
+ Self::#variant_name(data) => {
+ azalea_buf::McBufWritable::write_into(data, buf)?;
+ }
+ });
+ }
+ }
+ }
+ if is_data_enum {
+ quote! {
+ impl azalea_buf::McBufWritable for #ident {
+ fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
+ match self {
+ #match_arms
+ }
+ Ok(())
+ }
+ }
+ impl #ident {
+ pub fn write_without_id(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
+ match self {
+ #match_arms_without_id
+ }
+ Ok(())
+ }
+ }
+ }
+ } else {
+ // optimization: if it doesn't have data we can just do `as u32`
+ quote! {
+ impl azalea_buf::McBufWritable for #ident {
+ fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
+ azalea_buf::McBufVarWritable::var_write_into(&(*self as u32), buf)
+ }
+ }
+ }
+ }
+ }
+ _ => panic!("#[derive(McBuf)] can only be used on structs"),
+ }
+}
diff --git a/azalea-buf/src/read.rs b/azalea-buf/src/read.rs
index b387dcfb..69a7d8ef 100755
--- a/azalea-buf/src/read.rs
+++ b/azalea-buf/src/read.rs
@@ -1,6 +1,8 @@
use super::{UnsizedByteArray, MAX_STRING_LENGTH};
use byteorder::{ReadBytesExt, BE};
+use log::warn;
use std::{
+ backtrace::Backtrace,
collections::HashMap,
hash::Hash,
io::{Cursor, Read},
@@ -17,14 +19,18 @@ pub enum BufReadError {
CouldNotReadBytes,
#[error("The received encoded string buffer length is longer than maximum allowed ({length} > {max_length})")]
StringLengthTooLong { length: u32, max_length: u32 },
- #[error("{0}")]
- Io(
+ #[error("{source}")]
+ Io {
#[from]
#[backtrace]
- std::io::Error,
- ),
- #[error("Invalid UTF-8")]
- InvalidUtf8,
+ source: std::io::Error,
+ },
+ #[error("Invalid UTF-8: {bytes:?} (lossy: {lossy:?})")]
+ InvalidUtf8 {
+ bytes: Vec,
+ lossy: String,
+ // backtrace: Backtrace,
+ },
#[error("Unexpected enum variant {id}")]
UnexpectedEnumVariant { id: i32 },
#[error("Unexpected enum variant {id}")]
@@ -33,12 +39,17 @@ pub enum BufReadError {
UnexpectedEof {
attempted_read: usize,
actual_read: usize,
+ backtrace: Backtrace,
},
#[error("{0}")]
Custom(String),
#[cfg(feature = "serde_json")]
- #[error("{0}")]
- Deserialization(#[from] serde_json::Error),
+ #[error("{source}")]
+ Deserialization {
+ #[from]
+ #[backtrace]
+ source: serde_json::Error,
+ },
}
fn read_bytes<'a>(buf: &'a mut Cursor<&[u8]>, length: usize) -> Result<&'a [u8], BufReadError> {
@@ -46,6 +57,7 @@ fn read_bytes<'a>(buf: &'a mut Cursor<&[u8]>, length: usize) -> Result<&'a [u8],
return Err(BufReadError::UnexpectedEof {
attempted_read: length,
actual_read: buf.get_ref().len() - buf.position() as usize,
+ backtrace: Backtrace::capture(),
});
}
let initial_position = buf.position() as usize;
@@ -66,7 +78,11 @@ fn read_utf_with_len(buf: &mut Cursor<&[u8]>, max_length: u32) -> Result length as usize {
return Err(BufReadError::StringLengthTooLong { length, max_length });
@@ -265,7 +281,11 @@ impl McBufReadable for u64 {
impl McBufReadable for bool {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result {
- Ok(u8::read_from(buf)? != 0)
+ let byte = u8::read_from(buf)?;
+ if byte > 1 {
+ warn!("Boolean value was not 0 or 1, but {}", byte);
+ }
+ Ok(byte != 0)
}
}
diff --git a/azalea-chat/Cargo.toml b/azalea-chat/Cargo.toml
index a1caccf2..482ce536 100755
--- a/azalea-chat/Cargo.toml
+++ b/azalea-chat/Cargo.toml
@@ -9,8 +9,11 @@ version = "0.4.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-azalea-buf = {path = "../azalea-buf", features = ["serde_json"], version = "^0.4.0"}
-azalea-language = {path = "../azalea-language", version = "^0.4.0"}
+azalea-buf = { path = "../azalea-buf", features = [
+ "serde_json",
+], version = "^0.4.0" }
+azalea-language = { path = "../azalea-language", version = "^0.4.0" }
+log = "0.4.17"
once_cell = "1.16.0"
-serde = {version = "^1.0.148", features = ["derive"]}
+serde = { version = "^1.0.148", features = ["derive"] }
serde_json = "^1.0.72"
diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs
index b60beaf5..3a232ee5 100755
--- a/azalea-chat/src/component.rs
+++ b/azalea-chat/src/component.rs
@@ -5,6 +5,7 @@ use crate::{
translatable_component::{StringOrComponent, TranslatableComponent},
};
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
+use log::debug;
use once_cell::sync::Lazy;
use serde::{de, Deserialize, Deserializer, Serialize};
use std::{
@@ -266,6 +267,7 @@ impl<'de> Deserialize<'de> for Component {
impl McBufReadable for Component {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result {
let string = String::read_from(buf)?;
+ debug!("Component string: {}", string);
let json: serde_json::Value = serde_json::from_str(string.as_str())?;
let component = Component::deserialize(json)?;
Ok(component)
diff --git a/azalea-client/src/chat.rs b/azalea-client/src/chat.rs
index 26f37d58..510bf043 100755
--- a/azalea-client/src/chat.rs
+++ b/azalea-client/src/chat.rs
@@ -2,12 +2,11 @@
use crate::Client;
use azalea_chat::Component;
-use azalea_crypto::MessageSignature;
use azalea_protocol::packets::game::{
- clientbound_player_chat_packet::{ClientboundPlayerChatPacket, LastSeenMessagesUpdate},
+ clientbound_player_chat_packet::ClientboundPlayerChatPacket,
clientbound_system_chat_packet::ClientboundSystemChatPacket,
serverbound_chat_command_packet::ServerboundChatCommandPacket,
- serverbound_chat_packet::ServerboundChatPacket,
+ serverbound_chat_packet::{LastSeenMessagesUpdate, ServerboundChatPacket},
};
use std::{
sync::Arc,
@@ -33,7 +32,7 @@ impl ChatPacket {
pub fn message(&self) -> Component {
match self {
ChatPacket::System(p) => p.content.clone(),
- ChatPacket::Player(p) => p.message(false),
+ ChatPacket::Player(p) => p.message(),
}
}
@@ -47,7 +46,7 @@ impl ChatPacket {
// If it's a player chat packet, then the sender and content
// are already split for us.
Some(p.chat_type.name.to_string()),
- p.message.content(false).to_string(),
+ p.body.content.clone(),
),
ChatPacket::System(p) => {
let message = p.content.to_string();
@@ -88,7 +87,7 @@ impl Client {
/// so you should use that instead.
pub async fn send_chat_packet(&self, message: &str) -> Result<(), std::io::Error> {
// TODO: chat signing
- let signature = sign_message();
+ // let signature = sign_message();
let packet = ServerboundChatPacket {
message: message.to_string(),
timestamp: SystemTime::now()
@@ -98,8 +97,7 @@ impl Client {
.try_into()
.expect("Instant should fit into a u64"),
salt: azalea_crypto::make_salt(),
- signature,
- signed_preview: false,
+ signature: None,
last_seen_messages: LastSeenMessagesUpdate::default(),
}
.get();
@@ -120,7 +118,6 @@ impl Client {
.expect("Instant should fit into a u64"),
salt: azalea_crypto::make_salt(),
argument_signatures: vec![],
- signed_preview: false,
last_seen_messages: LastSeenMessagesUpdate::default(),
}
.get();
@@ -143,14 +140,10 @@ impl Client {
self.send_chat_packet(message).await
}
}
-
- // will be used for when the server tells the client about a chat preview
- // with custom formatting
- // pub fn acknowledge_preview(&self, message: &str) {}
}
// TODO
// MessageSigner, ChatMessageContent, LastSeenMessages
-fn sign_message() -> MessageSignature {
- MessageSignature::default()
-}
+// fn sign_message() -> MessageSignature {
+// MessageSignature::default()
+// }
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs
index 1cd26aa8..17fb4840 100644
--- a/azalea-client/src/client.rs
+++ b/azalea-client/src/client.rs
@@ -1,8 +1,7 @@
pub use crate::chat::ChatPacket;
use crate::{movement::WalkDirection, plugins::PluginStates, Account, PlayerInfo};
use azalea_auth::game_profile::GameProfile;
-use azalea_chat::Component;
-use azalea_core::{ChunkPos, GameType, ResourceLocation, Vec3};
+use azalea_core::{ChunkPos, ResourceLocation, Vec3};
use azalea_protocol::{
connect::{Connection, ConnectionError, ReadConnection, WriteConnection},
packets::{
@@ -22,8 +21,7 @@ use azalea_protocol::{
login::{
serverbound_custom_query_packet::ServerboundCustomQueryPacket,
serverbound_hello_packet::ServerboundHelloPacket,
- serverbound_key_packet::{NonceOrSaltSignature, ServerboundKeyPacket},
- ClientboundLoginPacket,
+ serverbound_key_packet::ServerboundKeyPacket, ClientboundLoginPacket,
},
ConnectionProtocol, PROTOCOL_VERSION,
},
@@ -37,6 +35,8 @@ use azalea_world::{
use log::{debug, error, info, trace, warn};
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::{
+ any,
+ backtrace::Backtrace,
collections::HashMap,
fmt::Debug,
io::{self, Cursor},
@@ -52,8 +52,11 @@ use uuid::Uuid;
pub type ClientInformation = ServerboundClientInformationPacket;
-/// Events are sent before they're processed, so for example game ticks happen
-/// at the beginning of a tick before anything has happened.
+/// Something that happened in-game, such as a tick passing or chat message
+/// being sent.
+///
+/// Note: Events are sent before they're processed, so for example game ticks
+/// happen at the beginning of a tick before anything has happened.
#[derive(Debug, Clone)]
pub enum Event {
/// Happens right after the bot switches into the Game state, but before
@@ -61,43 +64,26 @@ pub enum Event {
/// information with `Client::set_client_information`, so the packet
/// doesn't have to be sent twice.
Init,
+ /// The client is now in the world. Fired when we receive a login packet.
Login,
+ /// A chat message was sent in the game chat.
Chat(ChatPacket),
/// Happens 20 times per second, but only when the world is loaded.
Tick,
Packet(Arc),
- /// Happens when a player is added, removed, or updated in the tab list.
- UpdatePlayers(UpdatePlayersEvent),
- /// Emits when the player dies.
+ /// A player joined the game (or more specifically, was added to the tab
+ /// list).
+ AddPlayer(PlayerInfo),
+ /// A player left the game (or maybe is still in the game and was just
+ /// removed from the tab list).
+ RemovePlayer(PlayerInfo),
+ /// A player was updated in the tab list (gamemode, display
+ /// name, or latency changed).
+ UpdatePlayer(PlayerInfo),
+ /// The client player died in-game.
Death(Option>),
}
-/// Happens when a player is added, removed, or updated in the tab list.
-#[derive(Debug, Clone)]
-pub enum UpdatePlayersEvent {
- /// A player with the given info was added to the tab list (usually means
- /// they joined the server).
- Add(PlayerInfo),
- /// A player with the given UUID was removed from the tab list (usually
- /// means they left the server)
- Remove { uuid: Uuid },
- /// The latency of the player with the given UUID was updated in the tab
- /// list. Note that this can be spoofed by the player and may not represent
- /// their actual latency.
- Latency {
- uuid: Uuid,
- /// The time it took in milliseconds for this player to reply to the ping packet.
- latency: i32,
- },
- /// The played switched to a different gamemode (i.e. survival, creative, spectator)
- GameMode { uuid: Uuid, game_mode: GameType },
- /// The name of the player with the given UUID in the tab list was changed or reset.
- DisplayName {
- uuid: Uuid,
- display_name: Option,
- },
-}
-
/// A player that you control that is currently in a Minecraft server.
#[derive(Clone)]
pub struct Client {
@@ -141,6 +127,7 @@ pub struct PhysicsState {
/// Whether we should ignore errors when decoding packets.
const IGNORE_ERRORS: bool = !cfg!(debug_assertions);
+/// An error that happened while joining the server.
#[derive(Error, Debug)]
pub enum JoinError {
#[error("{0}")]
@@ -148,7 +135,7 @@ pub enum JoinError {
#[error("{0}")]
Connection(#[from] ConnectionError),
#[error("{0}")]
- ReadPacket(#[from] azalea_protocol::read::ReadPacketError),
+ ReadPacket(#[from] Box),
#[error("{0}")]
Io(#[from] io::Error),
#[error("{0}")]
@@ -280,8 +267,7 @@ impl Client {
// login
conn.write(
ServerboundHelloPacket {
- username: account.username.clone(),
- public_key: None,
+ name: account.username.clone(),
profile_id: None,
}
.get(),
@@ -309,8 +295,8 @@ impl Client {
conn.write(
ServerboundKeyPacket {
- nonce_or_salt_signature: NonceOrSaltSignature::Nonce(e.encrypted_nonce),
key_bytes: e.encrypted_public_key,
+ encrypted_challenge: e.encrypted_nonce,
}
.get(),
)
@@ -396,6 +382,7 @@ impl Client {
}
},
Err(e) => {
+ let e = *e;
if let ReadPacketError::ConnectionClosed = e {
info!("Connection closed");
if let Err(e) = client.disconnect().await {
@@ -403,13 +390,19 @@ impl Client {
}
break;
}
+ let default_backtrace = Backtrace::capture();
if IGNORE_ERRORS {
- warn!("{}", e);
- if let ReadPacketError::FrameSplitter { .. } = e {
- panic!("Error: {e:?}");
+ let backtrace =
+ any::request_ref::(&e).unwrap_or(&default_backtrace);
+ warn!("{e}\n{backtrace}");
+ match e {
+ ReadPacketError::FrameSplitter { .. } => panic!("Error: {e:?}"),
+ _ => continue,
}
} else {
- panic!("{}", e);
+ let backtrace =
+ any::request_ref::(&e).unwrap_or(&default_backtrace);
+ panic!("{e}\n{backtrace}")
}
}
};
@@ -657,100 +650,56 @@ impl Client {
)
.await?;
}
- ClientboundGamePacket::PlayerInfo(p) => {
- use azalea_protocol::packets::game::clientbound_player_info_packet::Action;
-
+ ClientboundGamePacket::PlayerInfoUpdate(p) => {
debug!("Got player info packet {:?}", p);
let mut events = Vec::new();
{
let mut players_lock = client.players.write();
- match &p.action {
- Action::AddPlayer(players) => {
- for player in players {
- let player_info = PlayerInfo {
- profile: GameProfile {
- uuid: player.uuid,
- name: player.name.clone(),
- properties: player.properties.clone(),
- },
- uuid: player.uuid,
- gamemode: player.gamemode,
- latency: player.latency,
- display_name: player.display_name.clone(),
- };
- players_lock.insert(player.uuid, player_info.clone());
- events.push(Event::UpdatePlayers(UpdatePlayersEvent::Add(
- player_info,
- )));
+ for updated_info in &p.entries {
+ // add the new player maybe
+ if p.actions.add_player {
+ let player_info = PlayerInfo {
+ profile: updated_info.profile.clone(),
+ uuid: updated_info.profile.uuid,
+ gamemode: updated_info.game_mode,
+ latency: updated_info.latency,
+ display_name: updated_info.display_name.clone(),
+ };
+ players_lock.insert(updated_info.profile.uuid, player_info.clone());
+ events.push(Event::AddPlayer(player_info));
+ } else if let Some(info) = players_lock.get_mut(&updated_info.profile.uuid)
+ {
+ // `else if` because the block for add_player above
+ // already sets all the fields
+ if p.actions.update_game_mode {
+ info.gamemode = updated_info.game_mode;
}
+ if p.actions.update_latency {
+ info.latency = updated_info.latency;
+ }
+ if p.actions.update_display_name {
+ info.display_name = updated_info.display_name.clone();
+ }
+ events.push(Event::UpdatePlayer(info.clone()));
+ } else {
+ warn!(
+ "Ignoring PlayerInfoUpdate for unknown player {}",
+ updated_info.profile.uuid
+ );
}
- Action::UpdateGameMode(players) => {
- for player in players {
- if let Some(p) = players_lock.get_mut(&player.uuid) {
- p.gamemode = player.gamemode;
- events.push(Event::UpdatePlayers(
- UpdatePlayersEvent::GameMode {
- uuid: player.uuid,
- game_mode: player.gamemode,
- },
- ));
- } else {
- warn!(
- "Ignoring PlayerInfo (UpdateGameMode) for unknown player {}",
- player.uuid
- );
- }
- }
- }
- Action::UpdateLatency(players) => {
- for player in players {
- if let Some(p) = players_lock.get_mut(&player.uuid) {
- p.latency = player.latency;
- events.push(Event::UpdatePlayers(
- UpdatePlayersEvent::Latency {
- uuid: player.uuid,
- latency: player.latency,
- },
- ));
- } else {
- warn!(
- "Ignoring PlayerInfo (UpdateLatency) for unknown player {}",
- player.uuid
- );
- }
- }
- }
- Action::UpdateDisplayName(players) => {
- for player in players {
- if let Some(p) = players_lock.get_mut(&player.uuid) {
- p.display_name = player.display_name.clone();
- events.push(Event::UpdatePlayers(
- UpdatePlayersEvent::DisplayName {
- uuid: player.uuid,
- display_name: player.display_name.clone(),
- },
- ));
- } else {
- warn!(
- "Ignoring PlayerInfo (UpdateDisplayName) for unknown player {}",
- player.uuid
- );
- }
- }
- }
- Action::RemovePlayer(players) => {
- for player in players {
- if players_lock.remove(&player.uuid).is_some() {
- events.push(Event::UpdatePlayers(UpdatePlayersEvent::Remove {
- uuid: player.uuid,
- }));
- } else {
- warn!(
- "Ignoring PlayerInfo (RemovePlayer) for unknown player {}",
- player.uuid
- );
- }
- }
+ }
+ }
+ for event in events {
+ tx.send(event).await?;
+ }
+ }
+ ClientboundGamePacket::PlayerInfoRemove(p) => {
+ let mut events = Vec::new();
+ {
+ let mut players_lock = client.players.write();
+ for uuid in &p.profile_ids {
+ if let Some(info) = players_lock.remove(uuid) {
+ events.push(Event::RemovePlayer(info));
}
}
}
@@ -948,13 +897,11 @@ impl Client {
ClientboundGamePacket::BlockEntityData(_) => {}
ClientboundGamePacket::BlockEvent(_) => {}
ClientboundGamePacket::BossEvent(_) => {}
- ClientboundGamePacket::ChatPreview(_) => {}
ClientboundGamePacket::CommandSuggestions(_) => {}
ClientboundGamePacket::ContainerSetData(_) => {}
ClientboundGamePacket::ContainerSetSlot(_) => {}
ClientboundGamePacket::Cooldown(_) => {}
ClientboundGamePacket::CustomChatCompletions(_) => {}
- ClientboundGamePacket::CustomSound(_) => {}
ClientboundGamePacket::DeleteChat(_) => {}
ClientboundGamePacket::Explode(_) => {}
ClientboundGamePacket::ForgetLevelChunk(_) => {}
@@ -967,7 +914,6 @@ impl Client {
ClientboundGamePacket::OpenSignEditor(_) => {}
ClientboundGamePacket::Ping(_) => {}
ClientboundGamePacket::PlaceGhostRecipe(_) => {}
- ClientboundGamePacket::PlayerChatHeader(_) => {}
ClientboundGamePacket::PlayerCombatEnd(_) => {}
ClientboundGamePacket::PlayerCombatEnter(_) => {}
ClientboundGamePacket::PlayerCombatKill(p) => {
@@ -998,7 +944,6 @@ impl Client {
ClientboundGamePacket::SetBorderWarningDelay(_) => {}
ClientboundGamePacket::SetBorderWarningDistance(_) => {}
ClientboundGamePacket::SetCamera(_) => {}
- ClientboundGamePacket::SetDisplayChatPreview(_) => {}
ClientboundGamePacket::SetDisplayObjective(_) => {}
ClientboundGamePacket::SetObjective(_) => {}
ClientboundGamePacket::SetPassengers(_) => {}
@@ -1013,6 +958,8 @@ impl Client {
ClientboundGamePacket::TabList(_) => {}
ClientboundGamePacket::TagQuery(_) => {}
ClientboundGamePacket::TakeItemEntity(_) => {}
+ ClientboundGamePacket::DisguisedChat(_) => {}
+ ClientboundGamePacket::UpdateEnabledFeatures(_) => {}
ClientboundGamePacket::ContainerClose(_) => {}
}
diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs
index 91c8cd91..f2952248 100644
--- a/azalea-client/src/lib.rs
+++ b/azalea-client/src/lib.rs
@@ -2,13 +2,13 @@
//! real clients. If you want to make bots, you should use the
//! [`azalea`] crate instead.
//!
-//! [`azalea_protocol`]: https://crates.io/crates/azalea-protocol
-//! [`azalea`]: https://crates.io/crates/azalea
+//! [`azalea_protocol`]: https://docs.rs/azalea-protocol
+//! [`azalea`]: https://docs.rs/azalea
+#![feature(provide_any)]
#![allow(incomplete_features)]
#![feature(trait_upcasting)]
#![feature(error_generic_member_access)]
-#![feature(provide_any)]
mod account;
mod chat;
diff --git a/azalea-client/src/ping.rs b/azalea-client/src/ping.rs
index 289622b6..8acde7a5 100755
--- a/azalea-client/src/ping.rs
+++ b/azalea-client/src/ping.rs
@@ -23,7 +23,7 @@ pub enum PingError {
#[error("{0}")]
Connection(#[from] ConnectionError),
#[error("{0}")]
- ReadPacket(#[from] azalea_protocol::read::ReadPacketError),
+ ReadPacket(#[from] Box),
#[error("{0}")]
WritePacket(#[from] io::Error),
#[error("The given address could not be parsed into a ServerAddress")]
diff --git a/azalea-core/src/bitset.rs b/azalea-core/src/bitset.rs
index d878bbf5..41d43165 100755
--- a/azalea-core/src/bitset.rs
+++ b/azalea-core/src/bitset.rs
@@ -1,4 +1,6 @@
-use azalea_buf::McBuf;
+use std::io::{Cursor, Read, Write};
+
+use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
/// Represents Java's BitSet, a list of bits.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, McBuf)]
@@ -105,6 +107,89 @@ impl BitSet {
pub fn set(&mut self, bit_index: usize) {
self.data[bit_index / 64] |= 1u64 << (bit_index % 64);
}
+
+ /// Read a BitSet with a known length.
+ pub fn read_fixed(buf: &mut Cursor<&[u8]>, length: usize) -> Result {
+ let mut data = vec![0; length.div_ceil(8)];
+ buf.read_exact(&mut data)?;
+ Ok(BitSet::from(data))
+ }
+}
+
+impl From> for BitSet {
+ fn from(data: Vec) -> Self {
+ BitSet { data }
+ }
+}
+
+impl From> for BitSet {
+ fn from(data: Vec) -> Self {
+ let mut words = vec![0; data.len().div_ceil(8)];
+ for (i, byte) in data.iter().enumerate() {
+ words[i / 8] |= (*byte as u64) << ((i % 8) * 8);
+ }
+ BitSet { data: words }
+ }
+}
+
+/// A list of bits with a known fixed size.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FixedBitSet
+where
+ [(); N.div_ceil(8)]: Sized,
+{
+ data: [u8; N.div_ceil(8)],
+}
+
+impl FixedBitSet
+where
+ [u8; N.div_ceil(8)]: Sized,
+{
+ pub fn new() -> Self {
+ FixedBitSet {
+ data: [0; N.div_ceil(8)],
+ }
+ }
+
+ pub fn index(&self, index: usize) -> bool {
+ (self.data[index / 8] & (1u8 << (index % 8))) != 0
+ }
+
+ pub fn set(&mut self, bit_index: usize) {
+ self.data[bit_index / 8] |= 1u8 << (bit_index % 8);
+ }
+}
+
+impl McBufReadable for FixedBitSet
+where
+ [u8; N.div_ceil(8)]: Sized,
+{
+ fn read_from(buf: &mut Cursor<&[u8]>) -> Result {
+ let mut data = [0; N.div_ceil(8)];
+ for item in data.iter_mut().take(N.div_ceil(8)) {
+ *item = u8::read_from(buf)?;
+ }
+ Ok(FixedBitSet { data })
+ }
+}
+impl McBufWritable for FixedBitSet
+where
+ [u8; N.div_ceil(8)]: Sized,
+{
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ for i in 0..N.div_ceil(8) {
+ self.data[i].write_into(buf)?;
+ }
+ Ok(())
+ }
+}
+impl Default for FixedBitSet
+where
+ [u8; N.div_ceil(8)]: Sized,
+{
+ fn default() -> Self {
+ Self::new()
+ }
}
#[cfg(test)]
diff --git a/azalea-core/src/game_type.rs b/azalea-core/src/game_type.rs
old mode 100755
new mode 100644
index 75ee0674..c4b4cf76
--- a/azalea-core/src/game_type.rs
+++ b/azalea-core/src/game_type.rs
@@ -1,8 +1,9 @@
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use std::io::{Cursor, Write};
-#[derive(Hash, Copy, Clone, Debug)]
+#[derive(Hash, Copy, Clone, Debug, Default)]
pub enum GameType {
+ #[default]
Survival,
Creative,
Adventure,
diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs
index 7c74bdcb..30af2448 100755
--- a/azalea-core/src/lib.rs
+++ b/azalea-core/src/lib.rs
@@ -1,6 +1,8 @@
//! Random miscellaneous things like UUIDs that don't deserve their own crate.
#![feature(int_roundings)]
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
mod difficulty;
pub use difficulty::*;
diff --git a/azalea-crypto/src/signing.rs b/azalea-crypto/src/signing.rs
index 1753eec2..93892c17 100755
--- a/azalea-crypto/src/signing.rs
+++ b/azalea-crypto/src/signing.rs
@@ -7,9 +7,9 @@ pub struct SaltSignaturePair {
pub signature: Vec,
}
-#[derive(Clone, Debug, Default, McBuf, PartialEq)]
+#[derive(Clone, Debug, PartialEq, McBuf)]
pub struct MessageSignature {
- pub bytes: Vec,
+ pub bytes: [u8; 256],
}
#[derive(Clone, Debug, McBuf, PartialEq)]
diff --git a/azalea-language/src/en_us.json b/azalea-language/src/en_us.json
index 9bc48bbe..b480393b 100755
--- a/azalea-language/src/en_us.json
+++ b/azalea-language/src/en_us.json
@@ -30,7 +30,7 @@
"narration.checkbox": "Checkbox: %s",
"narration.checkbox.usage.focused": "Press Enter to toggle",
"narration.checkbox.usage.hovered": "Left click to toggle",
- "narration.recipe": "Reciple for %s",
+ "narration.recipe": "Recipe for %s",
"narration.recipe.usage": "Left click to select",
"narration.recipe.usage.more": "Right click to show more recipes",
"narration.selection.usage": "Press up and down buttons to move to another entry",
@@ -54,6 +54,7 @@
"gui.all": "All",
"gui.ok": "Ok",
"gui.proceed": "Proceed",
+ "gui.acknowledge": "Acknowledge",
"gui.recipebook.moreRecipes": "Right Click for More",
"gui.recipebook.search_hint": "Search...",
"gui.recipebook.toggleRecipes.all": "Showing All",
@@ -79,13 +80,95 @@
"gui.socialInteractions.empty_blocked": "No blocked players in chat",
"gui.socialInteractions.hide": "Hide in Chat",
"gui.socialInteractions.show": "Show in Chat",
+ "gui.socialInteractions.report": "Report",
"gui.socialInteractions.hidden_in_chat": "Chat messages from %s will be hidden",
"gui.socialInteractions.shown_in_chat": "Chat messages from %s will be shown",
- "gui.socialInteractions.tooltip.hide": "Hide messages from %s in chat",
- "gui.socialInteractions.tooltip.show": "Show messages from %s in chat",
+ "gui.socialInteractions.tooltip.hide": "Hide messages",
+ "gui.socialInteractions.tooltip.show": "Show messages",
+ "gui.socialInteractions.tooltip.report": "Report player",
+ "gui.socialInteractions.tooltip.report.disabled": "The reporting service is unavailable",
+ "gui.socialInteractions.tooltip.report.no_messages": "No reportable messages from player %s",
+ "gui.socialInteractions.tooltip.report.not_reportable": "This player can't be reported, because their chat messages can't be verified on this server",
+ "gui.socialInteractions.narration.hide": "Hide messages from %s",
+ "gui.socialInteractions.narration.show": "Show messages from %s",
+ "gui.socialInteractions.narration.report": "Report player %s",
"gui.narrate.button": "%s button",
"gui.narrate.slider": "%s slider",
"gui.narrate.editBox": "%s edit box: %s",
+ "gui.chatReport.title": "Report Player",
+ "gui.chatReport.send": "Send Report",
+ "gui.chatReport.send.comments_too_long": "Please shorten the comment",
+ "gui.chatReport.send.no_reason": "Please select a report category",
+ "gui.chatReport.send.no_reported_messages": "Please select at least one chat message to report",
+ "gui.chatReport.send.too_many_messages": "Trying to include too many messages in the report",
+ "gui.chatReport.observed_what": "Why are you reporting this?",
+ "gui.chatReport.select_reason": "Select Report Category",
+ "gui.chatReport.more_comments": "Please describe what happened:",
+ "gui.chatReport.describe": "Sharing details will help us make a well-informed decision.",
+ "gui.chatReport.comments": "Comments",
+ "gui.chatReport.read_info": "Learn About Reporting",
+ "gui.chatReport.select_chat": "Select Chat Messages to Report",
+ "gui.chatReport.selected_chat": "%s Chat Message(s) Selected to Report",
+ "gui.chatReport.report_sent_msg": "We\u2019ve successfully received your report. Thank you!\n\nOur team will review it as soon as possible.",
+ "gui.chatReport.discard.title": "Discard report and comments?",
+ "gui.chatReport.discard.content": "If you leave, you'll lose this report and your comments.\nAre you sure you want to leave?",
+ "gui.chatReport.discard.discard": "Leave and Discard Report",
+ "gui.chatReport.discard.draft": "Save as Draft",
+ "gui.chatReport.discard.return": "Continue Editing",
+ "gui.chatReport.draft.title": "Edit draft chat report?",
+ "gui.chatReport.draft.content": "Would you like to continue editing the existing report or discard it and create a new one?",
+ "gui.chatReport.draft.quittotitle.title": "You have a draft chat report that will be lost if you quit",
+ "gui.chatReport.draft.quittotitle.content": "Would you like to continue editing it or discard it?",
+ "gui.chatReport.draft.discard": "Discard",
+ "gui.chatReport.draft.edit": "Continue Editing",
+ "gui.abuseReport.reason.title": "Select Report Category",
+ "gui.abuseReport.reason.description": "Description:",
+ "gui.abuseReport.reason.narration": "%s: %s",
+ "gui.abuseReport.reason.false_reporting": "False Reporting",
+ "gui.abuseReport.reason.child_sexual_exploitation_or_abuse": "Child sexual exploitation or abuse",
+ "gui.abuseReport.reason.child_sexual_exploitation_or_abuse.description": "Someone is talking about or otherwise promoting indecent behavior involving children.",
+ "gui.abuseReport.reason.terrorism_or_violent_extremism": "Terrorism or violent extremism",
+ "gui.abuseReport.reason.terrorism_or_violent_extremism.description": "Someone is talking about, promoting, or threatening to commit acts of terrorism or violent extremism for political, religious, ideological, or other reasons.",
+ "gui.abuseReport.reason.hate_speech": "Hate speech",
+ "gui.abuseReport.reason.hate_speech.description": "Someone is attacking you or another player based on characteristics of their identity, like religion, race, or sexuality.",
+ "gui.abuseReport.reason.harassment_or_bullying": "Harassment or bullying",
+ "gui.abuseReport.reason.harassment_or_bullying.description": "Someone is shaming, attacking, or bullying you or someone else. This includes when someone is repeatedly trying to contact you or someone else without consent or posting private personal information about you or someone else without consent (\"doxing\").",
+ "gui.abuseReport.reason.imminent_harm": "Imminent harm - Threat to harm others",
+ "gui.abuseReport.reason.imminent_harm.description": "Someone is threatening to harm you or someone else in real life.",
+ "gui.abuseReport.reason.defamation_impersonation_false_information": "Defamation, impersonation, or false information",
+ "gui.abuseReport.reason.defamation_impersonation_false_information.description": "Someone is damaging someone else's reputation, pretending to be someone they're not, or sharing false information with the aim to exploit or mislead others.",
+ "gui.abuseReport.reason.self_harm_or_suicide": "Imminent harm - Self-harm or suicide",
+ "gui.abuseReport.reason.self_harm_or_suicide.description": "Someone is threatening to harm themselves in real life or talking about harming themselves in real life.",
+ "gui.abuseReport.reason.alcohol_tobacco_drugs": "Drugs or alcohol",
+ "gui.abuseReport.reason.alcohol_tobacco_drugs.description": "Someone is encouraging others to partake in illegal drug related activities or encouraging underage drinking.",
+ "gui.abuseReport.reason.non_consensual_intimate_imagery": "Non-consensual intimate imagery",
+ "gui.abuseReport.reason.non_consensual_intimate_imagery.description": "Someone is talking about, sharing, or otherwise promoting private and intimate images.",
+ "gui.abuseReport.sending.title": "Sending your report...",
+ "gui.abuseReport.sent.title": "Report sent",
+ "gui.abuseReport.error.title": "Problem sending your report",
+ "gui.abuseReport.send.generic_error": "Encountered an unexpected error while sending your report.",
+ "gui.abuseReport.send.error_message": "An error was returned while sending your report:\n'%s'",
+ "gui.abuseReport.send.service_unavailable": "Unable to reach the Abuse Reporting service. Please make sure you are connected to the internet and try again.",
+ "gui.abuseReport.send.http_error": "An unexpected HTTP error occurred while sending your report.",
+ "gui.abuseReport.send.json_error": "Encountered malformed payload while sending your report.",
+ "gui.chatSelection.title": "Select Chat Messages to Report",
+ "gui.chatSelection.context": "Messages surrounding this selection will be included to provide additional context",
+ "gui.chatSelection.selected": "%s/%s message(s) selected",
+ "gui.chatSelection.heading": "%s %s",
+ "gui.chatSelection.message.narrate": "%s said: %s at %s",
+ "gui.chatSelection.fold": "%s message(s) hidden",
+ "gui.chatSelection.join": "%s joined the chat",
+ "gui.multiLineEditBox.character_limit": "%s/%s",
+ "gui.banned.title.temporary": "Account temporarily suspended",
+ "gui.banned.title.permanent": "Account permanently banned",
+ "gui.banned.description": "%s\n\n%s\n\nLearn more at the following link: %s",
+ "gui.banned.description.reason": "We recently received a report for bad behavior by your account. Our moderators have now reviewed your case and identified it as %s, which goes against the Minecraft Community Standards.",
+ "gui.banned.description.reason_id": "Code: %s",
+ "gui.banned.description.reason_id_message": "Code: %s - %s",
+ "gui.banned.description.unknownreason": "We recently received a report for bad behavior by your account. Our moderators have now reviewed your case and identified that it goes against the Minecraft Community Standards.",
+ "gui.banned.description.temporary.duration": "Your account is temporarily suspended and will be reactivated in %s.",
+ "gui.banned.description.temporary": "%s Until then, you can\u2019t play online or join Realms.",
+ "gui.banned.description.permanent": "Your account is permanently banned, which means you can\u2019t play online or join Realms.",
"translation.test.none": "Hello, world!",
"translation.test.complex": "Prefix, %s%2$s again %s and %1$s lastly %s and also %1$s again!",
"translation.test.escape": "%%s %%%s %%%%s %%%%%s",
@@ -115,6 +198,7 @@
"menu.shareToLan": "Open to LAN",
"menu.sendFeedback": "Give Feedback",
"menu.reportBugs": "Report Bugs",
+ "menu.playerReporting": "Player Reporting",
"menu.paused": "Game Paused",
"menu.modded": " (Modded)",
"optimizeWorld.confirm.title": "Optimize World",
@@ -162,6 +246,7 @@
"selectWorld.enterSeed": "Seed for the world generator",
"selectWorld.seedInfo": "Leave blank for a random seed",
"selectWorld.cheats": "Cheats",
+ "selectWorld.experimental": "Experimental",
"selectWorld.customizeType": "Customize",
"selectWorld.version": "Version:",
"selectWorld.versionUnknown": "unknown",
@@ -176,7 +261,7 @@
"selectWorld.backupWarning.customized": "Unfortunately, we do not support customized worlds in this version of Minecraft. We can still load this world and keep everything the way it was, but any newly generated terrain will no longer be customized. We're sorry for the inconvenience!",
"selectWorld.backupQuestion.experimental": "Worlds using Experimental Settings are not supported",
"selectWorld.backupWarning.experimental": "This world uses experimental settings that could stop working at any time. We cannot guarantee it will load or work. Here be dragons!",
- "selectWorld.backupEraseCache": "Erase cached data",
+ "selectWorld.backupEraseCache": "Erase Cached Data",
"selectWorld.backupJoinConfirmButton": "Create Backup and Load",
"selectWorld.backupJoinSkipButton": "I know what I'm doing!",
"selectWorld.tooltip.fromNewerVersion1": "World was saved in a newer version,",
@@ -194,6 +279,7 @@
"selectWorld.access_failure": "Failed to access world",
"selectWorld.delete_failure": "Failed to delete world",
"selectWorld.data_read": "Reading world data...",
+ "selectWorld.loading_list": "Loading world list",
"createWorld.customize.presets": "Presets",
"createWorld.customize.presets.title": "Select a Preset",
"createWorld.customize.presets.select": "Use Preset",
@@ -208,15 +294,16 @@
"createWorld.customize.flat.layer.bottom": "Bottom - %s",
"createWorld.customize.buffet.title": "Buffet world customization",
"createWorld.customize.buffet.biome": "Please select a biome",
- "createWorld.customize.preset.classic_flat": "Classic Flat",
- "createWorld.customize.preset.tunnelers_dream": "Tunnelers' Dream",
- "createWorld.customize.preset.water_world": "Water World",
- "createWorld.customize.preset.overworld": "Overworld",
- "createWorld.customize.preset.snowy_kingdom": "Snowy Kingdom",
- "createWorld.customize.preset.bottomless_pit": "Bottomless Pit",
- "createWorld.customize.preset.desert": "Desert",
- "createWorld.customize.preset.redstone_ready": "Redstone Ready",
- "createWorld.customize.preset.the_void": "The Void",
+ "flat_world_preset.unknown": "???",
+ "flat_world_preset.minecraft.classic_flat": "Classic Flat",
+ "flat_world_preset.minecraft.tunnelers_dream": "Tunnelers' Dream",
+ "flat_world_preset.minecraft.water_world": "Water World",
+ "flat_world_preset.minecraft.overworld": "Overworld",
+ "flat_world_preset.minecraft.snowy_kingdom": "Snowy Kingdom",
+ "flat_world_preset.minecraft.bottomless_pit": "Bottomless Pit",
+ "flat_world_preset.minecraft.desert": "Desert",
+ "flat_world_preset.minecraft.redstone_ready": "Redstone Ready",
+ "flat_world_preset.minecraft.the_void": "The Void",
"createWorld.customize.custom.page0": "Basic Settings",
"createWorld.customize.custom.page1": "Ore Settings",
"createWorld.customize.custom.page2": "Advanced Settings (Expert Users Only!)",
@@ -327,19 +414,24 @@
"selectWorld.import_worldgen_settings": "Import Settings",
"selectWorld.import_worldgen_settings.select_file": "Select settings file (.json)",
"selectWorld.import_worldgen_settings.failure": "Error importing settings",
- "selectWorld.import_worldgen_settings.experimental.title": "Warning! These settings are using experimental features",
- "selectWorld.import_worldgen_settings.experimental.question": "These settings are experimental and could one day stop working. Do you wish to proceed?",
- "selectWorld.import_worldgen_settings.deprecated.title": "Warning! These settings are using deprecated features",
- "selectWorld.import_worldgen_settings.deprecated.question": "Some features used are deprecated and will stop working in the future. Do you wish to proceed?",
- "generator.default": "Default",
- "generator.flat": "Superflat",
- "generator.large_biomes": "Large Biomes",
- "generator.amplified": "AMPLIFIED",
- "generator.customized": "Old Customized",
+ "selectWorld.warning.experimental.title": "Warning! These settings are using experimental features",
+ "selectWorld.warning.experimental.question": "These settings are experimental and could one day stop working. Do you wish to proceed?",
+ "selectWorld.warning.deprecated.title": "Warning! These settings are using deprecated features",
+ "selectWorld.warning.deprecated.question": "Some features used are deprecated and will stop working in the future. Do you wish to proceed?",
+ "selectWorld.experimental.title": "Experimental Features Warning",
+ "selectWorld.experimental.message": "Be careful!\nSome of the selected packs require features that are still under development. Your world might crash, break or not work with future updates.",
+ "selectWorld.experimental.details": "Details",
+ "selectWorld.experimental.details.title": "Experimental feature requirements",
+ "selectWorld.experimental.details.entry": "Required experimental features: %s",
"generator.custom": "Custom",
- "generator.debug_all_block_states": "Debug Mode",
- "generator.amplified.info": "Notice: Just for fun! Requires a beefy computer.",
- "generator.single_biome_surface": "Single Biome",
+ "generator.minecraft.normal": "Default",
+ "generator.minecraft.flat": "Superflat",
+ "generator.minecraft.large_biomes": "Large Biomes",
+ "generator.minecraft.amplified": "AMPLIFIED",
+ "generator.minecraft.amplified.info": "Notice: Just for fun! Requires a beefy computer.",
+ "generator.minecraft.debug_all_block_states": "Debug Mode",
+ "generator.minecraft.single_biome_surface": "Single Biome",
+ "generator.customized": "Old Customized",
"generator.single_biome_caves": "Caves",
"generator.single_biome_floating_islands": "Floating Islands",
"selectServer.title": "Select Server",
@@ -367,6 +459,11 @@
"lanServer.scanning": "Scanning for games on your local network",
"lanServer.start": "Start LAN World",
"lanServer.otherPlayers": "Settings for Other Players",
+ "lanServer.port": "Port Number",
+ "lanServer.port.unavailable": "Port not available.\nLeave the edit box empty or enter a different number between 1024 and 65535.",
+ "lanServer.port.unavailable.new": "Port not available.\nLeave the edit box empty or enter a different number between %s and %s.",
+ "lanServer.port.invalid": "Not a valid port.\nLeave the edit box empty or enter a number between 1024 and 65535.",
+ "lanServer.port.invalid.new": "Not a valid port.\nLeave the edit box empty or enter a number between %s and %s.",
"multiplayerWarning.header": "Caution: Third-Party Online Play",
"multiplayerWarning.message": "Caution: Online play is offered by third-party servers that are not owned, operated, or supervised by Mojang Studios or Microsoft. During online play, you may be exposed to unmoderated chat messages or other types of user-generated content that may not be suitable for everyone.",
"multiplayerWarning.check": "Do not show this screen again",
@@ -430,12 +527,24 @@
"multiplayer.disconnect.name_taken": "That name is already taken",
"multiplayer.disconnect.unexpected_query_response": "Unexpected custom data from client",
"multiplayer.disconnect.missing_tags": "Incomplete set of tags received from server.\nPlease contact server operator.",
+ "multiplayer.disconnect.expired_public_key": "Expired profile public key. Check that your system time is synchronized, and try restarting your game.",
+ "multiplayer.disconnect.invalid_public_key_signature": "Invalid signature for profile public key.\nTry restarting your game.",
+ "multiplayer.disconnect.out_of_order_chat": "Out-of-order chat packet received. Did your system time change?",
+ "multiplayer.disconnect.unsigned_chat": "Received chat packet with missing or invalid signature.",
+ "multiplayer.disconnect.too_many_pending_chats": "Too many unacknowledged chat messages",
+ "multiplayer.disconnect.chat_validation_failed": "Chat message validation failure",
"multiplayer.socialInteractions.not_available": "Social Interactions are only available in Multiplayer worlds",
+ "multiplayer.unsecureserver.toast.title": "Chat messages can't be verified",
+ "multiplayer.unsecureserver.toast": "Messages sent on this server may be modified and might not reflect the original message",
"chat.editBox": "chat",
"chat.cannotSend": "Cannot send chat message",
"chat.disabled.options": "Chat disabled in client options",
"chat.disabled.launcher": "Chat disabled by launcher option. Cannot send message",
- "chat.disabled.profile": "Chat not allowed by account settings. Cannot send message",
+ "chat.disabled.profile": "Chat not allowed by account settings. Press '%s' again for more information",
+ "chat.disabled.profile.moreInfo": "Chat not allowed by account settings. Cannot send or view messages.",
+ "chat.disabled.expiredProfileKey": "Chat disabled due to expired profile public key. Please try reconnecting.",
+ "chat.disabled.chain_broken": "Chat disabled due to broken chain. Please try reconnecting.",
+ "chat.disabled.missingProfileKey": "Chat disabled due to missing profile public key. Please try reconnecting.",
"chat.type.text": "<%s> %s",
"chat.type.text.narrate": "%s says %s",
"chat.type.emote": "* %s %s",
@@ -457,6 +566,13 @@
"chat.coordinates.tooltip": "Click to teleport",
"chat.queue": "[+%s pending lines]",
"chat.square_brackets": "[%s]",
+ "chat.tag.system": "Server message. Cannot be reported.",
+ "chat.tag.system_single_player": "Server message.",
+ "chat.tag.not_secure": "Unverified message. Cannot be reported.",
+ "chat.tag.modified": "Message modified by the server. Original:",
+ "chat.filtered_full": "The server has hidden your message for some players.",
+ "chat.filtered": "Filtered by the server.",
+ "chat.deleted_marker": "This chat message has been deleted by the server.",
"menu.playdemo": "Play Demo World",
"menu.resetdemo": "Reset Demo World",
"demo.day.1": "This demo will last five game days. Do your best!",
@@ -497,6 +613,7 @@
"disconnect.loginFailedInfo.serversUnavailable": "The authentication servers are currently not reachable. Please try again.",
"disconnect.loginFailedInfo.invalidSession": "Invalid session (Try restarting your game and the launcher)",
"disconnect.loginFailedInfo.insufficientPrivileges": "Multiplayer is disabled. Please check your Microsoft account settings.",
+ "disconnect.loginFailedInfo.userBanned": "You are banned from playing online",
"disconnect.quitting": "Quitting",
"disconnect.endOfStream": "End of stream",
"disconnect.overflow": "Buffer overflow",
@@ -541,7 +658,9 @@
"options.screenEffectScale": "Distortion Effects",
"options.screenEffectScale.tooltip": "Strength of nausea and Nether portal screen distortion effects.\nAt lower values, the nausea effect is replaced with a green overlay.",
"options.fovEffectScale": "FOV Effects",
- "options.fovEffectScale.tooltip": "Controls how much the field of view can change with speed effects.",
+ "options.fovEffectScale.tooltip": "Controls how much the field of view can change with gameplay effects.",
+ "options.darknessEffectScale": "Darkness Pulsing",
+ "options.darknessEffectScale.tooltip": "Controls how much the Darkness effect pulses when a Warden or Sculk Shrieker gives it to you.",
"options.biomeBlendRadius": "Biome Blend",
"options.biomeBlendRadius.1": "OFF (Fastest)",
"options.biomeBlendRadius.3": "3x3 (Fast)",
@@ -624,12 +743,21 @@
"options.chat.width": "Width",
"options.chat.height.focused": "Focused Height",
"options.chat.height.unfocused": "Unfocused Height",
+ "options.onlyShowSecureChat": "Only Show Secure Chat",
+ "options.onlyShowSecureChat.tooltip": "Only display messages from other players that can be verified to have been sent by that player, and have not been modified.",
"options.accessibility.title": "Accessibility Settings...",
"options.accessibility.text_background": "Text Background",
"options.accessibility.text_background.chat": "Chat",
"options.accessibility.text_background.everywhere": "Everywhere",
"options.accessibility.text_background_opacity": "Text Background Opacity",
+ "options.accessibility.panorama_speed": "Panorama Scroll Speed",
"options.accessibility.link": "Accessibility Guide",
+ "options.telemetry": "Telemetry Data",
+ "options.telemetry.button": "Data Collection",
+ "options.telemetry.state.none": "None",
+ "options.telemetry.state.minimal": "Minimal",
+ "options.telemetry.state.all": "All",
+ "options.telemetry.button.tooltip": "\"%s\" includes only the required data.\n\"%s\" includes optional, as well as the required data.",
"options.audioDevice": "Device",
"options.audioDevice.default": "System Default",
"options.key.toggle": "Toggle",
@@ -656,12 +784,16 @@
"options.attack.crosshair": "Crosshair",
"options.attack.hotbar": "Hotbar",
"options.showSubtitles": "Show Subtitles",
+ "options.directionalAudio": "Directional Audio",
+ "options.directionalAudio.on.tooltip": "Uses HRTF-based directional audio to improve the simulation of 3D sound. Requires HRTF compatible audio hardware, and is best experienced with headphones.",
+ "options.directionalAudio.off.tooltip": "Classic Stereo sound",
"options.online": "Online...",
"options.online.title": "Online Options",
"options.allowServerListing": "Allow Server Listings",
"options.allowServerListing.tooltip": "Servers may list online players as part of their public status.\nWith this option off your name will not show up in such lists.",
"options.realmsNotifications": "Realms Notifications",
"options.autoJump": "Auto-Jump",
+ "options.operatorItemsTab": "Operator Items Tab",
"options.autoSuggestCommands": "Command Suggestions",
"options.autosaveIndicator": "Autosave Indicator",
"options.discrete_mouse_scroll": "Discrete Scrolling",
@@ -693,6 +825,8 @@
"title.32bit.deprecation.realms": "Minecraft will soon require a 64-bit system, which will prevent you from playing or using Realms on this device. You will need to manually cancel any Realms subscription.",
"title.32bit.deprecation.realms.check": "Do not show this screen again",
"title.multiplayer.disabled": "Multiplayer is disabled. Please check your Microsoft account settings.",
+ "title.multiplayer.disabled.banned.temporary": "Your account is temporarily suspended from online play",
+ "title.multiplayer.disabled.banned.permanent": "Your account is permanently suspended from online play",
"controls.title": "Controls",
"controls.reset": "Reset",
"controls.resetAll": "Reset Keys",
@@ -844,16 +978,22 @@
"pack.folderInfo": "(Place pack files here)",
"resourcePack.title": "Select Resource Packs",
"resourcePack.server.name": "World Specific Resources",
+ "resourcePack.programmer_art.name": "Programmer Art",
"resourcePack.broken_assets": "BROKEN ASSETS DETECTED",
- "resourcePack.vanilla.description": "The default resources for Minecraft",
+ "resourcePack.vanilla.name": "Default",
+ "resourcePack.vanilla.description": "The default look and feel of Minecraft",
"resourcePack.load_fail": "Resource reload failed",
"dataPack.title": "Select Data Packs",
"dataPack.validation.working": "Validating selected data packs...",
"dataPack.validation.failed": "Data pack validation failed!",
"dataPack.validation.back": "Go Back",
"dataPack.validation.reset": "Reset to Default",
+ "dataPack.vanilla.name": "Default",
"dataPack.vanilla.description": "The default data for Minecraft",
+ "dataPack.bundle.description": "Enables experimental Bundle item",
+ "dataPack.update_1_20.description": "New features and content for Minecraft 1.20",
"sign.edit": "Edit Sign Message",
+ "hanging_sign.edit": "Edit Hanging Sign Message",
"book.pageIndicator": "Page %1$s of %2$s",
"book.byAuthor": "by %1$s",
"book.signButton": "Sign",
@@ -896,18 +1036,24 @@
"block.minecraft.jungle_planks": "Jungle Planks",
"block.minecraft.acacia_planks": "Acacia Planks",
"block.minecraft.dark_oak_planks": "Dark Oak Planks",
+ "block.minecraft.mangrove_planks": "Mangrove Planks",
+ "block.minecraft.bamboo_planks": "Bamboo Planks",
+ "block.minecraft.bamboo_mosaic": "Bamboo Mosaic",
"block.minecraft.oak_sapling": "Oak Sapling",
"block.minecraft.spruce_sapling": "Spruce Sapling",
"block.minecraft.birch_sapling": "Birch Sapling",
"block.minecraft.jungle_sapling": "Jungle Sapling",
"block.minecraft.acacia_sapling": "Acacia Sapling",
"block.minecraft.dark_oak_sapling": "Dark Oak Sapling",
+ "block.minecraft.mangrove_propagule": "Mangrove Propagule",
"block.minecraft.oak_door": "Oak Door",
"block.minecraft.spruce_door": "Spruce Door",
"block.minecraft.birch_door": "Birch Door",
"block.minecraft.jungle_door": "Jungle Door",
"block.minecraft.acacia_door": "Acacia Door",
"block.minecraft.dark_oak_door": "Dark Oak Door",
+ "block.minecraft.mangrove_door": "Mangrove Door",
+ "block.minecraft.bamboo_door": "Bamboo Door",
"block.minecraft.bedrock": "Bedrock",
"block.minecraft.water": "Water",
"block.minecraft.lava": "Lava",
@@ -933,30 +1079,39 @@
"block.minecraft.jungle_wood": "Jungle Wood",
"block.minecraft.acacia_wood": "Acacia Wood",
"block.minecraft.dark_oak_wood": "Dark Oak Wood",
+ "block.minecraft.mangrove_wood": "Mangrove Wood",
"block.minecraft.oak_log": "Oak Log",
"block.minecraft.spruce_log": "Spruce Log",
"block.minecraft.birch_log": "Birch Log",
"block.minecraft.jungle_log": "Jungle Log",
"block.minecraft.acacia_log": "Acacia Log",
"block.minecraft.dark_oak_log": "Dark Oak Log",
+ "block.minecraft.mangrove_log": "Mangrove Log",
+ "block.minecraft.mangrove_roots": "Mangrove Roots",
+ "block.minecraft.muddy_mangrove_roots": "Muddy Mangrove Roots",
+ "block.minecraft.bamboo_block": "Block of Bamboo",
"block.minecraft.stripped_oak_log": "Stripped Oak Log",
"block.minecraft.stripped_spruce_log": "Stripped Spruce Log",
"block.minecraft.stripped_birch_log": "Stripped Birch Log",
"block.minecraft.stripped_jungle_log": "Stripped Jungle Log",
"block.minecraft.stripped_acacia_log": "Stripped Acacia Log",
"block.minecraft.stripped_dark_oak_log": "Stripped Dark Oak Log",
+ "block.minecraft.stripped_mangrove_log": "Stripped Mangrove Log",
+ "block.minecraft.stripped_bamboo_block": "Block of Stripped Bamboo",
"block.minecraft.stripped_oak_wood": "Stripped Oak Wood",
"block.minecraft.stripped_spruce_wood": "Stripped Spruce Wood",
"block.minecraft.stripped_birch_wood": "Stripped Birch Wood",
"block.minecraft.stripped_jungle_wood": "Stripped Jungle Wood",
"block.minecraft.stripped_acacia_wood": "Stripped Acacia Wood",
"block.minecraft.stripped_dark_oak_wood": "Stripped Dark Oak Wood",
+ "block.minecraft.stripped_mangrove_wood": "Stripped Mangrove Wood",
"block.minecraft.oak_leaves": "Oak Leaves",
"block.minecraft.spruce_leaves": "Spruce Leaves",
"block.minecraft.birch_leaves": "Birch Leaves",
"block.minecraft.jungle_leaves": "Jungle Leaves",
"block.minecraft.acacia_leaves": "Acacia Leaves",
"block.minecraft.dark_oak_leaves": "Dark Oak Leaves",
+ "block.minecraft.mangrove_leaves": "Mangrove Leaves",
"block.minecraft.dead_bush": "Dead Bush",
"block.minecraft.grass": "Grass",
"block.minecraft.fern": "Fern",
@@ -1041,6 +1196,7 @@
"block.minecraft.cobblestone_slab": "Cobblestone Slab",
"block.minecraft.brick_slab": "Brick Slab",
"block.minecraft.stone_brick_slab": "Stone Brick Slab",
+ "block.minecraft.mud_brick_slab": "Mud Brick Slab",
"block.minecraft.nether_brick_slab": "Nether Brick Slab",
"block.minecraft.quartz_slab": "Quartz Slab",
"block.minecraft.oak_slab": "Oak Slab",
@@ -1049,12 +1205,16 @@
"block.minecraft.jungle_slab": "Jungle Slab",
"block.minecraft.acacia_slab": "Acacia Slab",
"block.minecraft.dark_oak_slab": "Dark Oak Slab",
+ "block.minecraft.mangrove_slab": "Mangrove Slab",
+ "block.minecraft.bamboo_slab": "Bamboo Slab",
+ "block.minecraft.bamboo_mosaic_slab": "Bamboo Mosaic Slab",
"block.minecraft.dark_prismarine_slab": "Dark Prismarine Slab",
"block.minecraft.prismarine_slab": "Prismarine Slab",
"block.minecraft.prismarine_brick_slab": "Prismarine Brick Slab",
"block.minecraft.bricks": "Bricks",
"block.minecraft.tnt": "TNT",
"block.minecraft.bookshelf": "Bookshelf",
+ "block.minecraft.chiseled_bookshelf": "Chiseled Bookshelf",
"block.minecraft.mossy_cobblestone": "Mossy Cobblestone",
"block.minecraft.obsidian": "Obsidian",
"block.minecraft.torch": "Torch",
@@ -1062,7 +1222,9 @@
"block.minecraft.soul_torch": "Soul Torch",
"block.minecraft.soul_wall_torch": "Soul Wall Torch",
"block.minecraft.fire": "Fire",
- "block.minecraft.spawner": "Spawner",
+ "block.minecraft.spawner": "Monster Spawner",
+ "block.minecraft.spawner.desc1": "Interact with Spawn Egg:",
+ "block.minecraft.spawner.desc2": "Sets Mob Type",
"block.minecraft.respawn_anchor": "Respawn Anchor",
"block.minecraft.oak_stairs": "Oak Stairs",
"block.minecraft.spruce_stairs": "Spruce Stairs",
@@ -1070,6 +1232,9 @@
"block.minecraft.jungle_stairs": "Jungle Stairs",
"block.minecraft.acacia_stairs": "Acacia Stairs",
"block.minecraft.dark_oak_stairs": "Dark Oak Stairs",
+ "block.minecraft.mangrove_stairs": "Mangrove Stairs",
+ "block.minecraft.bamboo_stairs": "Bamboo Stairs",
+ "block.minecraft.bamboo_mosaic_stairs": "Bamboo Mosaic Stairs",
"block.minecraft.dark_prismarine_stairs": "Dark Prismarine Stairs",
"block.minecraft.prismarine_stairs": "Prismarine Stairs",
"block.minecraft.prismarine_brick_stairs": "Prismarine Brick Stairs",
@@ -1090,12 +1255,36 @@
"block.minecraft.acacia_sign": "Acacia Sign",
"block.minecraft.jungle_sign": "Jungle Sign",
"block.minecraft.dark_oak_sign": "Dark Oak Sign",
+ "block.minecraft.mangrove_sign": "Mangrove Sign",
+ "block.minecraft.bamboo_sign": "Bamboo Sign",
"block.minecraft.oak_wall_sign": "Oak Wall Sign",
"block.minecraft.spruce_wall_sign": "Spruce Wall Sign",
"block.minecraft.birch_wall_sign": "Birch Wall Sign",
"block.minecraft.acacia_wall_sign": "Acacia Wall Sign",
"block.minecraft.jungle_wall_sign": "Jungle Wall Sign",
"block.minecraft.dark_oak_wall_sign": "Dark Oak Wall Sign",
+ "block.minecraft.mangrove_wall_sign": "Mangrove Wall Sign",
+ "block.minecraft.bamboo_wall_sign": "Bamboo Wall Sign",
+ "block.minecraft.oak_hanging_sign": "Oak Hanging Sign",
+ "block.minecraft.spruce_hanging_sign": "Spruce Hanging Sign",
+ "block.minecraft.birch_hanging_sign": "Birch Hanging Sign",
+ "block.minecraft.acacia_hanging_sign": "Acacia Hanging Sign",
+ "block.minecraft.jungle_hanging_sign": "Jungle Hanging Sign",
+ "block.minecraft.crimson_hanging_sign": "Crimson Hanging Sign",
+ "block.minecraft.warped_hanging_sign": "Warped Hanging Sign",
+ "block.minecraft.dark_oak_hanging_sign": "Dark Oak Hanging Sign",
+ "block.minecraft.mangrove_hanging_sign": "Mangrove Hanging Sign",
+ "block.minecraft.bamboo_hanging_sign": "Bamboo Hanging Sign",
+ "block.minecraft.oak_wall_hanging_sign": "Oak Wall Hanging Sign",
+ "block.minecraft.spruce_wall_hanging_sign": "Spruce Wall Hanging Sign",
+ "block.minecraft.birch_wall_hanging_sign": "Birch Wall Hanging Sign",
+ "block.minecraft.acacia_wall_hanging_sign": "Acacia Wall Hanging Sign",
+ "block.minecraft.jungle_wall_hanging_sign": "Jungle Wall Hanging Sign",
+ "block.minecraft.dark_oak_wall_hanging_sign": "Dark Oak Wall Hanging Sign",
+ "block.minecraft.mangrove_wall_hanging_sign": "Mangrove Wall Hanging Sign",
+ "block.minecraft.crimson_wall_hanging_sign": "Crimson Wall Hanging Sign",
+ "block.minecraft.warped_wall_hanging_sign": "Warped Wall Hanging Sign",
+ "block.minecraft.bamboo_wall_hanging_sign": "Bamboo Wall Hanging Sign",
"block.minecraft.ladder": "Ladder",
"block.minecraft.scaffolding": "Scaffolding",
"block.minecraft.rail": "Rail",
@@ -1113,6 +1302,8 @@
"block.minecraft.jungle_pressure_plate": "Jungle Pressure Plate",
"block.minecraft.acacia_pressure_plate": "Acacia Pressure Plate",
"block.minecraft.dark_oak_pressure_plate": "Dark Oak Pressure Plate",
+ "block.minecraft.mangrove_pressure_plate": "Mangrove Pressure Plate",
+ "block.minecraft.bamboo_pressure_plate": "Bamboo Pressure Plate",
"block.minecraft.light_weighted_pressure_plate": "Light Weighted Pressure Plate",
"block.minecraft.heavy_weighted_pressure_plate": "Heavy Weighted Pressure Plate",
"block.minecraft.iron_door": "Iron Door",
@@ -1127,6 +1318,8 @@
"block.minecraft.jungle_button": "Jungle Button",
"block.minecraft.acacia_button": "Acacia Button",
"block.minecraft.dark_oak_button": "Dark Oak Button",
+ "block.minecraft.mangrove_button": "Mangrove Button",
+ "block.minecraft.bamboo_button": "Bamboo Button",
"block.minecraft.snow": "Snow",
"block.minecraft.white_carpet": "White Carpet",
"block.minecraft.orange_carpet": "Orange Carpet",
@@ -1173,14 +1366,18 @@
"block.minecraft.spruce_fence": "Spruce Fence",
"block.minecraft.birch_fence": "Birch Fence",
"block.minecraft.jungle_fence": "Jungle Fence",
- "block.minecraft.dark_oak_fence": "Dark Oak Fence",
"block.minecraft.acacia_fence": "Acacia Fence",
+ "block.minecraft.dark_oak_fence": "Dark Oak Fence",
+ "block.minecraft.mangrove_fence": "Mangrove Fence",
+ "block.minecraft.bamboo_fence": "Bamboo Fence",
"block.minecraft.oak_fence_gate": "Oak Fence Gate",
"block.minecraft.spruce_fence_gate": "Spruce Fence Gate",
"block.minecraft.birch_fence_gate": "Birch Fence Gate",
"block.minecraft.jungle_fence_gate": "Jungle Fence Gate",
- "block.minecraft.dark_oak_fence_gate": "Dark Oak Fence Gate",
"block.minecraft.acacia_fence_gate": "Acacia Fence Gate",
+ "block.minecraft.dark_oak_fence_gate": "Dark Oak Fence Gate",
+ "block.minecraft.mangrove_fence_gate": "Mangrove Fence Gate",
+ "block.minecraft.bamboo_fence_gate": "Bamboo Fence Gate",
"block.minecraft.pumpkin_stem": "Pumpkin Stem",
"block.minecraft.attached_pumpkin_stem": "Attached Pumpkin Stem",
"block.minecraft.pumpkin": "Pumpkin",
@@ -1226,12 +1423,16 @@
"block.minecraft.jungle_trapdoor": "Jungle Trapdoor",
"block.minecraft.acacia_trapdoor": "Acacia Trapdoor",
"block.minecraft.dark_oak_trapdoor": "Dark Oak Trapdoor",
+ "block.minecraft.mangrove_trapdoor": "Mangrove Trapdoor",
+ "block.minecraft.bamboo_trapdoor": "Bamboo Trapdoor",
"block.minecraft.iron_trapdoor": "Iron Trapdoor",
"block.minecraft.cobweb": "Cobweb",
"block.minecraft.stone_bricks": "Stone Bricks",
"block.minecraft.mossy_stone_bricks": "Mossy Stone Bricks",
"block.minecraft.cracked_stone_bricks": "Cracked Stone Bricks",
"block.minecraft.chiseled_stone_bricks": "Chiseled Stone Bricks",
+ "block.minecraft.packed_mud": "Packed Mud",
+ "block.minecraft.mud_bricks": "Mud Bricks",
"block.minecraft.infested_stone": "Infested Stone",
"block.minecraft.infested_cobblestone": "Infested Cobblestone",
"block.minecraft.infested_stone_bricks": "Infested Stone Bricks",
@@ -1244,6 +1445,7 @@
"block.minecraft.melon": "Melon",
"block.minecraft.brick_stairs": "Brick Stairs",
"block.minecraft.stone_brick_stairs": "Stone Brick Stairs",
+ "block.minecraft.mud_brick_stairs": "Mud Brick Stairs",
"block.minecraft.vine": "Vines",
"block.minecraft.nether_bricks": "Nether Bricks",
"block.minecraft.nether_brick_fence": "Nether Brick Fence",
@@ -1436,6 +1638,7 @@
"block.minecraft.potted_jungle_sapling": "Potted Jungle Sapling",
"block.minecraft.potted_acacia_sapling": "Potted Acacia Sapling",
"block.minecraft.potted_dark_oak_sapling": "Potted Dark Oak Sapling",
+ "block.minecraft.potted_mangrove_propagule": "Potted Mangrove Propagule",
"block.minecraft.potted_fern": "Potted Fern",
"block.minecraft.potted_dandelion": "Potted Dandelion",
"block.minecraft.potted_poppy": "Potted Poppy",
@@ -1474,6 +1677,8 @@
"block.minecraft.creeper_head": "Creeper Head",
"block.minecraft.dragon_wall_head": "Dragon Wall Head",
"block.minecraft.dragon_head": "Dragon Head",
+ "block.minecraft.piglin_wall_head": "Piglin Wall Head",
+ "block.minecraft.piglin_head": "Piglin Head",
"block.minecraft.end_gateway": "End Gateway",
"block.minecraft.structure_void": "Structure Void",
"block.minecraft.structure_block": "Structure Block",
@@ -1560,6 +1765,7 @@
"block.minecraft.mossy_stone_brick_wall": "Mossy Stone Brick Wall",
"block.minecraft.granite_wall": "Granite Wall",
"block.minecraft.stone_brick_wall": "Stone Brick Wall",
+ "block.minecraft.mud_brick_wall": "Mud Brick Wall",
"block.minecraft.nether_brick_wall": "Nether Brick Wall",
"block.minecraft.andesite_wall": "Andesite Wall",
"block.minecraft.red_nether_brick_wall": "Red Nether Brick Wall",
@@ -1704,6 +1910,7 @@
"block.minecraft.big_dripleaf_stem": "Big Dripleaf Stem",
"block.minecraft.small_dripleaf": "Small Dripleaf",
"block.minecraft.rooted_dirt": "Rooted Dirt",
+ "block.minecraft.mud": "Mud",
"block.minecraft.hanging_roots": "Hanging Roots",
"block.minecraft.powder_snow": "Powder Snow",
"block.minecraft.glow_lichen": "Glow Lichen",
@@ -1733,6 +1940,15 @@
"block.minecraft.raw_iron_block": "Block of Raw Iron",
"block.minecraft.raw_copper_block": "Block of Raw Copper",
"block.minecraft.raw_gold_block": "Block of Raw Gold",
+ "block.minecraft.sculk": "Sculk",
+ "block.minecraft.sculk_catalyst": "Sculk Catalyst",
+ "block.minecraft.sculk_shrieker": "Sculk Shrieker",
+ "block.minecraft.sculk_vein": "Sculk Vein",
+ "block.minecraft.ochre_froglight": "Ochre Froglight",
+ "block.minecraft.verdant_froglight": "Verdant Froglight",
+ "block.minecraft.pearlescent_froglight": "Pearlescent Froglight",
+ "block.minecraft.frogspawn": "Frogspawn",
+ "block.minecraft.reinforced_deepslate": "Reinforced Deepslate",
"item.minecraft.name_tag": "Name Tag",
"item.minecraft.lead": "Lead",
"item.minecraft.iron_shovel": "Iron Shovel",
@@ -1840,16 +2056,27 @@
"item.minecraft.tropical_fish_bucket": "Bucket of Tropical Fish",
"item.minecraft.powder_snow_bucket": "Powder Snow Bucket",
"item.minecraft.axolotl_bucket": "Bucket of Axolotl",
+ "item.minecraft.tadpole_bucket": "Bucket of Tadpole",
"item.minecraft.minecart": "Minecart",
"item.minecraft.saddle": "Saddle",
"item.minecraft.redstone": "Redstone Dust",
"item.minecraft.snowball": "Snowball",
"item.minecraft.oak_boat": "Oak Boat",
+ "item.minecraft.oak_chest_boat": "Oak Boat with Chest",
"item.minecraft.spruce_boat": "Spruce Boat",
+ "item.minecraft.spruce_chest_boat": "Spruce Boat with Chest",
"item.minecraft.birch_boat": "Birch Boat",
+ "item.minecraft.birch_chest_boat": "Birch Boat with Chest",
"item.minecraft.jungle_boat": "Jungle Boat",
+ "item.minecraft.jungle_chest_boat": "Jungle Boat with Chest",
"item.minecraft.acacia_boat": "Acacia Boat",
+ "item.minecraft.acacia_chest_boat": "Acacia Boat with Chest",
"item.minecraft.dark_oak_boat": "Dark Oak Boat",
+ "item.minecraft.dark_oak_chest_boat": "Dark Oak Boat with Chest",
+ "item.minecraft.mangrove_boat": "Mangrove Boat",
+ "item.minecraft.mangrove_chest_boat": "Mangrove Boat with Chest",
+ "item.minecraft.bamboo_raft": "Bamboo Raft",
+ "item.minecraft.bamboo_chest_raft": "Bamboo Raft with Chest",
"item.minecraft.leather": "Leather",
"item.minecraft.milk_bucket": "Milk Bucket",
"item.minecraft.brick": "Brick",
@@ -1864,6 +2091,7 @@
"item.minecraft.command_block_minecart": "Minecart with Command Block",
"item.minecraft.egg": "Egg",
"item.minecraft.compass": "Compass",
+ "item.minecraft.recovery_compass": "Recovery Compass",
"item.minecraft.fishing_rod": "Fishing Rod",
"item.minecraft.clock": "Clock",
"item.minecraft.glowstone_dust": "Glowstone Dust",
@@ -1887,6 +2115,7 @@
"item.minecraft.music_disc_wait": "Music Disc",
"item.minecraft.music_disc_pigstep": "Music Disc",
"item.minecraft.music_disc_otherside": "Music Disc",
+ "item.minecraft.music_disc_5": "Music Disc",
"item.minecraft.music_disc_13.desc": "C418 - 13",
"item.minecraft.music_disc_cat.desc": "C418 - cat",
"item.minecraft.music_disc_blocks.desc": "C418 - blocks",
@@ -1901,6 +2130,7 @@
"item.minecraft.music_disc_wait.desc": "C418 - wait",
"item.minecraft.music_disc_pigstep.desc": "Lena Raine - Pigstep",
"item.minecraft.music_disc_otherside.desc": "Lena Raine - otherside",
+ "item.minecraft.music_disc_5.desc": "Samuel \u00c5berg - 5",
"item.minecraft.bone": "Bone",
"item.minecraft.ink_sac": "Ink Sac",
"item.minecraft.red_dye": "Red Dye",
@@ -1926,6 +2156,8 @@
"item.minecraft.amethyst_shard": "Amethyst Shard",
"item.minecraft.spyglass": "Spyglass",
"item.minecraft.glow_berries": "Glow Berries",
+ "item.minecraft.disc_fragment_5": "Disc Fragment",
+ "item.minecraft.disc_fragment_5.desc": "Music Disc - 5",
"block.minecraft.black_bed": "Black Bed",
"block.minecraft.red_bed": "Red Bed",
"block.minecraft.green_bed": "Green Bed",
@@ -1965,11 +2197,13 @@
"item.minecraft.brewing_stand": "Brewing Stand",
"item.minecraft.ender_eye": "Eye of Ender",
"item.minecraft.glistering_melon_slice": "Glistering Melon Slice",
+ "item.minecraft.allay_spawn_egg": "Allay Spawn Egg",
"item.minecraft.axolotl_spawn_egg": "Axolotl Spawn Egg",
"item.minecraft.bat_spawn_egg": "Bat Spawn Egg",
"item.minecraft.bee_spawn_egg": "Bee Spawn Egg",
"item.minecraft.blaze_spawn_egg": "Blaze Spawn Egg",
"item.minecraft.cat_spawn_egg": "Cat Spawn Egg",
+ "item.minecraft.camel_spawn_egg": "Camel Spawn Egg",
"item.minecraft.cave_spider_spawn_egg": "Cave Spider Spawn Egg",
"item.minecraft.chicken_spawn_egg": "Chicken Spawn Egg",
"item.minecraft.cod_spawn_egg": "Cod Spawn Egg",
@@ -1979,6 +2213,7 @@
"item.minecraft.donkey_spawn_egg": "Donkey Spawn Egg",
"item.minecraft.drowned_spawn_egg": "Drowned Spawn Egg",
"item.minecraft.elder_guardian_spawn_egg": "Elder Guardian Spawn Egg",
+ "item.minecraft.ender_dragon_spawn_egg": "Ender Dragon Spawn Egg",
"item.minecraft.enderman_spawn_egg": "Enderman Spawn Egg",
"item.minecraft.endermite_spawn_egg": "Endermite Spawn Egg",
"item.minecraft.evoker_spawn_egg": "Evoker Spawn Egg",
@@ -1988,6 +2223,7 @@
"item.minecraft.hoglin_spawn_egg": "Hoglin Spawn Egg",
"item.minecraft.horse_spawn_egg": "Horse Spawn Egg",
"item.minecraft.husk_spawn_egg": "Husk Spawn Egg",
+ "item.minecraft.iron_golem_spawn_egg": "Iron Golem Spawn Egg",
"item.minecraft.ravager_spawn_egg": "Ravager Spawn Egg",
"item.minecraft.llama_spawn_egg": "Llama Spawn Egg",
"item.minecraft.magma_cube_spawn_egg": "Magma Cube Spawn Egg",
@@ -2005,6 +2241,7 @@
"item.minecraft.pufferfish_spawn_egg": "Pufferfish Spawn Egg",
"item.minecraft.rabbit_spawn_egg": "Rabbit Spawn Egg",
"item.minecraft.fox_spawn_egg": "Fox Spawn Egg",
+ "item.minecraft.frog_spawn_egg": "Frog Spawn Egg",
"item.minecraft.salmon_spawn_egg": "Salmon Spawn Egg",
"item.minecraft.sheep_spawn_egg": "Sheep Spawn Egg",
"item.minecraft.shulker_spawn_egg": "Shulker Spawn Egg",
@@ -2012,10 +2249,12 @@
"item.minecraft.skeleton_spawn_egg": "Skeleton Spawn Egg",
"item.minecraft.skeleton_horse_spawn_egg": "Skeleton Horse Spawn Egg",
"item.minecraft.slime_spawn_egg": "Slime Spawn Egg",
+ "item.minecraft.snow_golem_spawn_egg": "Snow Golem Spawn Egg",
"item.minecraft.spider_spawn_egg": "Spider Spawn Egg",
"item.minecraft.squid_spawn_egg": "Squid Spawn Egg",
"item.minecraft.stray_spawn_egg": "Stray Spawn Egg",
"item.minecraft.strider_spawn_egg": "Strider Spawn Egg",
+ "item.minecraft.tadpole_spawn_egg": "Tadpole Spawn Egg",
"item.minecraft.trader_llama_spawn_egg": "Trader Llama Spawn Egg",
"item.minecraft.tropical_fish_spawn_egg": "Tropical Fish Spawn Egg",
"item.minecraft.turtle_spawn_egg": "Turtle Spawn Egg",
@@ -2023,7 +2262,9 @@
"item.minecraft.villager_spawn_egg": "Villager Spawn Egg",
"item.minecraft.wandering_trader_spawn_egg": "Wandering Trader Spawn Egg",
"item.minecraft.vindicator_spawn_egg": "Vindicator Spawn Egg",
+ "item.minecraft.warden_spawn_egg": "Warden Spawn Egg",
"item.minecraft.witch_spawn_egg": "Witch Spawn Egg",
+ "item.minecraft.wither_spawn_egg": "Wither Spawn Egg",
"item.minecraft.wither_skeleton_spawn_egg": "Wither Skeleton Spawn Egg",
"item.minecraft.wolf_spawn_egg": "Wolf Spawn Egg",
"item.minecraft.zoglin_spawn_egg": "Zoglin Spawn Egg",
@@ -2139,6 +2380,16 @@
"item.minecraft.warped_fungus_on_a_stick": "Warped Fungus on a Stick",
"item.minecraft.glow_ink_sac": "Glow Ink Sac",
"item.minecraft.glow_item_frame": "Glow Item Frame",
+ "item.minecraft.echo_shard": "Echo Shard",
+ "item.minecraft.goat_horn": "Goat Horn",
+ "instrument.minecraft.ponder_goat_horn": "Ponder",
+ "instrument.minecraft.sing_goat_horn": "Sing",
+ "instrument.minecraft.seek_goat_horn": "Seek",
+ "instrument.minecraft.feel_goat_horn": "Feel",
+ "instrument.minecraft.admire_goat_horn": "Admire",
+ "instrument.minecraft.call_goat_horn": "Call",
+ "instrument.minecraft.yearn_goat_horn": "Yearn",
+ "instrument.minecraft.dream_goat_horn": "Dream",
"container.inventory": "Inventory",
"container.hopper": "Item Hopper",
"container.crafting": "Crafting",
@@ -2191,8 +2442,8 @@
"structure_block.hover.data": "Data: %s",
"structure_block.hover.corner": "Corner: %s",
"structure_block.mode_info.save": "Save Mode - Write to File",
- "structure_block.mode_info.load": "Load mode - Load from File",
- "structure_block.mode_info.data": "Data mode - Game Logic Marker",
+ "structure_block.mode_info.load": "Load Mode - Load from File",
+ "structure_block.mode_info.data": "Data Mode - Game Logic Marker",
"structure_block.mode_info.corner": "Corner Mode - Placement and Size Marker",
"structure_block.structure_name": "Structure Name",
"structure_block.custom_data": "Custom Data Tag Name",
@@ -2231,6 +2482,7 @@
"item.color": "Color: %s",
"item.nbt_tags": "NBT: %s tag(s)",
"item.durability": "Durability: %s / %s",
+ "item.disabled": "Disabled item",
"filled_map.mansion": "Woodland Explorer Map",
"filled_map.monument": "Ocean Explorer Map",
"filled_map.buried_treasure": "Buried Treasure Map",
@@ -2239,6 +2491,7 @@
"filled_map.level": "(Level %s/%s)",
"filled_map.scale": "Scaling at 1:%s",
"filled_map.locked": "Locked",
+ "entity.minecraft.allay": "Allay",
"entity.minecraft.area_effect_cloud": "Area Effect Cloud",
"entity.minecraft.armor_stand": "Armor Stand",
"entity.minecraft.arrow": "Arrow",
@@ -2247,7 +2500,9 @@
"entity.minecraft.bee": "Bee",
"entity.minecraft.blaze": "Blaze",
"entity.minecraft.boat": "Boat",
+ "entity.minecraft.chest_boat": "Boat with Chest",
"entity.minecraft.cat": "Cat",
+ "entity.minecraft.camel": "Camel",
"entity.minecraft.cave_spider": "Cave Spider",
"entity.minecraft.chest_minecart": "Minecart with Chest",
"entity.minecraft.chicken": "Chicken",
@@ -2274,6 +2529,7 @@
"entity.minecraft.firework_rocket": "Firework Rocket",
"entity.minecraft.fishing_bobber": "Fishing Bobber",
"entity.minecraft.fox": "Fox",
+ "entity.minecraft.frog": "Frog",
"entity.minecraft.furnace_minecart": "Minecart with Furnace",
"entity.minecraft.ghast": "Ghast",
"entity.minecraft.giant": "Giant",
@@ -2324,12 +2580,13 @@
"entity.minecraft.small_fireball": "Small Fireball",
"entity.minecraft.snowball": "Snowball",
"entity.minecraft.snow_golem": "Snow Golem",
- "entity.minecraft.spawner_minecart": "Minecart with Spawner",
+ "entity.minecraft.spawner_minecart": "Minecart with Monster Spawner",
"entity.minecraft.spectral_arrow": "Spectral Arrow",
"entity.minecraft.spider": "Spider",
"entity.minecraft.squid": "Squid",
"entity.minecraft.stray": "Stray",
"entity.minecraft.strider": "Strider",
+ "entity.minecraft.tadpole": "Tadpole",
"entity.minecraft.tnt": "Primed TNT",
"entity.minecraft.tnt_minecart": "Minecart with TNT",
"entity.minecraft.trader_llama": "Trader Llama",
@@ -2390,6 +2647,7 @@
"entity.minecraft.wandering_trader": "Wandering Trader",
"entity.minecraft.iron_golem": "Iron Golem",
"entity.minecraft.vindicator": "Vindicator",
+ "entity.minecraft.warden": "Warden",
"entity.minecraft.witch": "Witch",
"entity.minecraft.wither": "Wither",
"entity.minecraft.wither_skeleton": "Wither Skeleton",
@@ -2419,6 +2677,7 @@
"death.attack.inFire": "%1$s went up in flames",
"death.attack.inFire.player": "%1$s walked into fire whilst fighting %2$s",
"death.attack.onFire": "%1$s burned to death",
+ "death.attack.onFire.item": "%1$s was burnt to a crisp whilst fighting %2$s wielding %3$s",
"death.attack.onFire.player": "%1$s was burnt to a crisp whilst fighting %2$s",
"death.attack.lava": "%1$s tried to swim in lava",
"death.attack.lava.player": "%1$s tried to swim in lava to escape %2$s",
@@ -2448,6 +2707,7 @@
"death.attack.wither": "%1$s withered away",
"death.attack.wither.player": "%1$s withered away whilst fighting %2$s",
"death.attack.witherSkull": "%1$s was shot by a skull from %2$s",
+ "death.attack.witherSkull.item": "%1$s was shot by a skull from %2$s using %3$s",
"death.attack.anvil": "%1$s was squashed by a falling anvil",
"death.attack.anvil.player": "%1$s was squashed by a falling anvil whilst fighting %2$s",
"death.attack.fallingBlock": "%1$s was squashed by a falling block",
@@ -2456,6 +2716,9 @@
"death.attack.stalagmite.player": "%1$s was impaled on a stalagmite whilst fighting %2$s",
"death.attack.fallingStalactite": "%1$s was skewered by a falling stalactite",
"death.attack.fallingStalactite.player": "%1$s was skewered by a falling stalactite whilst fighting %2$s",
+ "death.attack.sonic_boom": "%1$s was obliterated by a sonically-charged shriek",
+ "death.attack.sonic_boom.item": "%1$s was obliterated by a sonically-charged shriek whilst trying to escape %2$s wielding %3$s",
+ "death.attack.sonic_boom.player": "%1$s was obliterated by a sonically-charged shriek whilst trying to escape %2$s",
"death.attack.mob": "%1$s was slain by %2$s",
"death.attack.mob.item": "%1$s was slain by %2$s using %3$s",
"death.attack.player": "%1$s was slain by %2$s",
@@ -2488,6 +2751,7 @@
"death.attack.sweetBerryBush": "%1$s was poked to death by a sweet berry bush",
"death.attack.sweetBerryBush.player": "%1$s was poked to death by a sweet berry bush whilst trying to escape %2$s",
"death.attack.sting": "%1$s was stung to death",
+ "death.attack.sting.item": "%1$s was stung to death by %2$s using %3$s",
"death.attack.sting.player": "%1$s was stung to death by %2$s",
"death.attack.freeze": "%1$s froze to death",
"death.attack.freeze.player": "%1$s was frozen to death by %2$s",
@@ -2531,6 +2795,7 @@
"effect.minecraft.dolphins_grace": "Dolphin's Grace",
"effect.minecraft.bad_omen": "Bad Omen",
"effect.minecraft.hero_of_the_village": "Hero of the Village",
+ "effect.minecraft.darkness": "Darkness",
"event.minecraft.raid": "Raid",
"event.minecraft.raid.raiders_remaining": "Raiders Remaining: %s",
"event.minecraft.raid.victory": "Victory",
@@ -2648,6 +2913,7 @@
"enchantment.minecraft.depth_strider": "Depth Strider",
"enchantment.minecraft.frost_walker": "Frost Walker",
"enchantment.minecraft.soul_speed": "Soul Speed",
+ "enchantment.minecraft.swift_sneak": "Swift Sneak",
"enchantment.minecraft.efficiency": "Efficiency",
"enchantment.minecraft.silk_touch": "Silk Touch",
"enchantment.minecraft.unbreaking": "Unbreaking",
@@ -2680,6 +2946,9 @@
"enchantment.level.8": "VIII",
"enchantment.level.9": "IX",
"enchantment.level.10": "X",
+ "gui.minutes": "%s minute(s)",
+ "gui.hours": "%s hour(s)",
+ "gui.days": "%s day(s)",
"gui.advancements": "Advancements",
"gui.stats": "Statistics",
"gui.entity_tooltip.type": "Type: %s",
@@ -2783,16 +3052,19 @@
"recipe.toast.title": "New Recipes Unlocked!",
"recipe.toast.description": "Check your recipe book",
"itemGroup.buildingBlocks": "Building Blocks",
- "itemGroup.decorations": "Decoration Blocks",
- "itemGroup.redstone": "Redstone",
- "itemGroup.transportation": "Transportation",
- "itemGroup.misc": "Miscellaneous",
+ "itemGroup.coloredBlocks": "Colored Blocks",
+ "itemGroup.natural": "Natural Blocks",
+ "itemGroup.functional": "Functional Blocks",
+ "itemGroup.redstone": "Redstone Blocks",
+ "itemGroup.op": "Operator Utilities",
+ "itemGroup.spawnEggs": "Spawn Eggs",
"itemGroup.search": "Search Items",
- "itemGroup.food": "Foodstuffs",
- "itemGroup.tools": "Tools",
+ "itemGroup.consumables": "Consumables",
+ "itemGroup.foodAndDrink": "Food & Drinks",
+ "itemGroup.tools": "Tools & Utilities",
"itemGroup.combat": "Combat",
- "itemGroup.brewing": "Brewing",
- "itemGroup.materials": "Materials",
+ "itemGroup.crafting": "Crafting",
+ "itemGroup.ingredients": "Ingredients",
"itemGroup.inventory": "Survival Inventory",
"itemGroup.hotbar": "Saved Hotbars",
"inventory.binSlot": "Destroy Item",
@@ -2828,7 +3100,6 @@
"item.modifiers.legs": "When on Legs:",
"item.modifiers.chest": "When on Body:",
"item.modifiers.head": "When on Head:",
- "attribute.unknown": "Unknown attribute",
"attribute.modifier.plus.0": "+%s %s",
"attribute.modifier.plus.1": "+%s%% %s",
"attribute.modifier.plus.2": "+%s%% %s",
@@ -3576,6 +3847,10 @@
"subtitles.block.chest.close": "Chest closes",
"subtitles.block.chest.locked": "Chest locked",
"subtitles.block.chest.open": "Chest opens",
+ "subtitles.chiseled_bookshelf.insert": "Book placed",
+ "subtitles.chiseled_bookshelf.insert_enchanted": "Enchanted book placed",
+ "subtitles.chiseled_bookshelf.take": "Book taken",
+ "subtitles.chiseled_bookshelf.take_enchanted": "Enchanted book taken",
"subtitles.block.chorus_flower.death": "Chorus Flower withers",
"subtitles.block.chorus_flower.grow": "Chorus Flower grows",
"subtitles.block.comparator.click": "Comparator clicks",
@@ -3595,6 +3870,7 @@
"subtitles.block.fence_gate.toggle": "Fence Gate creaks",
"subtitles.block.fire.ambient": "Fire crackles",
"subtitles.block.fire.extinguish": "Fire extinguished",
+ "subtitles.block.frogspawn.hatch": "Tadpole hatches",
"subtitles.block.furnace.fire_crackle": "Furnace crackles",
"subtitles.block.generic.break": "Block broken",
"subtitles.block.generic.footsteps": "Footsteps",
@@ -3626,8 +3902,12 @@
"subtitles.block.respawn_anchor.charge": "Respawn Anchor is charged",
"subtitles.block.respawn_anchor.deplete": "Respawn Anchor depletes",
"subtitles.block.respawn_anchor.set_spawn": "Respawn Anchor sets spawn",
+ "subtitles.block.sculk.charge": "Sculk bubbles",
+ "subtitles.block.sculk.spread": "Sculk spreads",
+ "subtitles.block.sculk_catalyst.bloom": "Sculk Catalyst blooms",
"subtitles.block.sculk_sensor.clicking": "Sculk Sensor starts clicking",
"subtitles.block.sculk_sensor.clicking_stop": "Sculk Sensor stops clicking",
+ "subtitles.block.sculk_shrieker.shriek": "Sculk Shrieker shrieks",
"subtitles.block.shulker_box.close": "Shulker closes",
"subtitles.block.shulker_box.open": "Shulker opens",
"subtitles.block.smithing_table.use": "Smithing Table used",
@@ -3639,6 +3919,13 @@
"subtitles.block.tripwire.detach": "Tripwire detaches",
"subtitles.block.water.ambient": "Water flows",
"subtitles.enchant.thorns.hit": "Thorns prick",
+ "subtitles.entity.allay.death": "Allay dies",
+ "subtitles.entity.allay.hurt": "Allay hurts",
+ "subtitles.entity.allay.ambient_with_item": "Allay seeks",
+ "subtitles.entity.allay.ambient_without_item": "Allay yearns",
+ "subtitles.entity.allay.item_given": "Allay chortles",
+ "subtitles.entity.allay.item_taken": "Allay allays",
+ "subtitles.entity.allay.item_thrown": "Allay tosses",
"subtitles.entity.armor_stand.fall": "Something fell",
"subtitles.entity.arrow.hit": "Arrow hits",
"subtitles.entity.arrow.hit_player": "Player hit",
@@ -3668,6 +3955,17 @@
"subtitles.entity.blaze.shoot": "Blaze shoots",
"subtitles.entity.boat.paddle_land": "Rowing",
"subtitles.entity.boat.paddle_water": "Rowing",
+ "subtitles.entity.camel.ambient": "Camel grunts",
+ "subtitles.entity.camel.dash": "Camel yeets",
+ "subtitles.entity.camel.dash_ready": "Camel recovers",
+ "subtitles.entity.camel.death": "Camel dies",
+ "subtitles.entity.camel.eat": "Camel eats",
+ "subtitles.entity.camel.hurt": "Camel hurts",
+ "subtitles.entity.camel.saddle": "Saddle equips",
+ "subtitles.entity.camel.sit": "Camel sits down",
+ "subtitles.entity.camel.stand": "Camel stands up",
+ "subtitles.entity.camel.step": "Camel steps",
+ "subtitles.entity.camel.step_sand": "Camel sands",
"subtitles.entity.cat.ambient": "Cat meows",
"subtitles.entity.cat.beg_for_food": "Cat begs",
"subtitles.entity.cat.death": "Cat dies",
@@ -3731,6 +4029,7 @@
"subtitles.entity.enderman.ambient": "Enderman vwoops",
"subtitles.entity.enderman.death": "Enderman dies",
"subtitles.entity.enderman.hurt": "Enderman hurts",
+ "subtitles.entity.enderman.scream": "Enderman screams",
"subtitles.entity.enderman.stare": "Enderman cries out",
"subtitles.entity.enderman.teleport": "Enderman teleports",
"subtitles.entity.endermite.ambient": "Endermite scuttles",
@@ -3763,6 +4062,12 @@
"subtitles.entity.fox.sniff": "Fox sniffs",
"subtitles.entity.fox.spit": "Fox spits",
"subtitles.entity.fox.teleport": "Fox teleports",
+ "subtitles.entity.frog.ambient": "Frog croaks",
+ "subtitles.entity.frog.death": "Frog dies",
+ "subtitles.entity.frog.eat": "Frog eats",
+ "subtitles.entity.frog.hurt": "Frog hurts",
+ "subtitles.entity.frog.lay_spawn": "Frog lays spawn",
+ "subtitles.entity.frog.long_jump": "Frog jumps",
"subtitles.entity.generic.big_fall": "Something fell",
"subtitles.entity.generic.burn": "Burning",
"subtitles.entity.generic.death": "Dying",
@@ -3791,6 +4096,7 @@
"subtitles.entity.goat.screaming.ambient": "Goat bellows",
"subtitles.entity.goat.death": "Goat dies",
"subtitles.entity.goat.eat": "Goat eats",
+ "subtitles.entity.goat.horn_break": "Goat Horn breaks off",
"subtitles.entity.goat.hurt": "Goat hurts",
"subtitles.entity.goat.long_jump": "Goat leaps",
"subtitles.entity.goat.milk": "Goat gets milked",
@@ -3892,7 +4198,7 @@
"subtitles.entity.parrot.imitate.blaze": "Parrot breathes",
"subtitles.entity.parrot.imitate.creeper": "Parrot hisses",
"subtitles.entity.parrot.imitate.drowned": "Parrot gurgles",
- "subtitles.entity.parrot.imitate.elder_guardian": "Parrot flaps",
+ "subtitles.entity.parrot.imitate.elder_guardian": "Parrot moans",
"subtitles.entity.parrot.imitate.ender_dragon": "Parrot roars",
"subtitles.entity.parrot.imitate.endermite": "Parrot scuttles",
"subtitles.entity.parrot.imitate.evoker": "Parrot murmurs",
@@ -3904,7 +4210,7 @@
"subtitles.entity.parrot.imitate.magma_cube": "Parrot squishes",
"subtitles.entity.parrot.imitate.phantom": "Parrot screeches",
"subtitles.entity.parrot.imitate.piglin": "Parrot snorts",
- "subtitles.entity.parrot.imitate.piglin_brute": "Parrot snorts mightily",
+ "subtitles.entity.parrot.imitate.piglin_brute": "Parrot snorts",
"subtitles.entity.parrot.imitate.pillager": "Parrot murmurs",
"subtitles.entity.parrot.imitate.ravager": "Parrot grunts",
"subtitles.entity.parrot.imitate.shulker": "Parrot lurks",
@@ -3915,6 +4221,7 @@
"subtitles.entity.parrot.imitate.stray": "Parrot rattles",
"subtitles.entity.parrot.imitate.vex": "Parrot vexes",
"subtitles.entity.parrot.imitate.vindicator": "Parrot mutters",
+ "subtitles.entity.parrot.imitate.warden": "Parrot whines",
"subtitles.entity.parrot.imitate.witch": "Parrot giggles",
"subtitles.entity.parrot.imitate.wither": "Parrot angers",
"subtitles.entity.parrot.imitate.wither_skeleton": "Parrot rattles",
@@ -4039,6 +4346,10 @@
"subtitles.entity.strider.hurt": "Strider hurts",
"subtitles.entity.strider.idle": "Strider chirps",
"subtitles.entity.strider.retreat": "Strider retreats",
+ "subtitles.entity.tadpole.death": "Tadpole dies",
+ "subtitles.entity.tadpole.flop": "Tadpole flops",
+ "subtitles.entity.tadpole.grow_up": "Tadpole grows up",
+ "subtitles.entity.tadpole.hurt": "Tadpole hurts",
"subtitles.entity.tnt.primed": "TNT fizzes",
"subtitles.entity.tropical_fish.death": "Tropical Fish dies",
"subtitles.entity.tropical_fish.flop": "Tropical Fish flops",
@@ -4093,6 +4404,26 @@
"subtitles.entity.wandering_trader.reappeared": "Wandering Trader appears",
"subtitles.entity.wandering_trader.trade": "Wandering Trader trades",
"subtitles.entity.wandering_trader.yes": "Wandering Trader agrees",
+ "subtitles.entity.warden.roar": "Warden roars",
+ "subtitles.entity.warden.sniff": "Warden sniffs",
+ "subtitles.entity.warden.emerge": "Warden emerges",
+ "subtitles.entity.warden.dig": "Warden digs",
+ "subtitles.entity.warden.hurt": "Warden hurts",
+ "subtitles.entity.warden.death": "Warden dies",
+ "subtitles.entity.warden.step": "Warden steps",
+ "subtitles.entity.warden.listening": "Warden takes notice",
+ "subtitles.entity.warden.listening_angry": "Warden takes notice angrily",
+ "subtitles.entity.warden.heartbeat": "Warden's heart beats",
+ "subtitles.entity.warden.attack_impact": "Warden lands hit",
+ "subtitles.entity.warden.tendril_clicks": "Warden's tendrils click",
+ "subtitles.entity.warden.angry": "Warden rages",
+ "subtitles.entity.warden.agitated": "Warden groans angrily",
+ "subtitles.entity.warden.ambient": "Warden whines",
+ "subtitles.entity.warden.nearby_close": "Warden approaches",
+ "subtitles.entity.warden.nearby_closer": "Warden advances",
+ "subtitles.entity.warden.nearby_closest": "Warden draws close",
+ "subtitles.entity.warden.sonic_charge": "Warden charges",
+ "subtitles.entity.warden.sonic_boom": "Warden booms",
"subtitles.entity.witch.ambient": "Witch giggles",
"subtitles.entity.witch.celebrate": "Witch cheers",
"subtitles.entity.witch.death": "Witch dies",
@@ -4160,6 +4491,7 @@
"subtitles.item.bucket.fill": "Bucket fills",
"subtitles.item.bucket.fill_axolotl": "Axolotl scooped",
"subtitles.item.bucket.fill_fish": "Fish captured",
+ "subtitles.item.bucket.fill_tadpole": "Tadpole captured",
"subtitles.item.bundle.drop_contents": "Bundle empties",
"subtitles.item.bundle.insert": "Item packed",
"subtitles.item.bundle.remove_one": "Item unpacked",
@@ -4171,6 +4503,7 @@
"subtitles.item.crossbow.shoot": "Crossbow fires",
"subtitles.item.firecharge.use": "Fireball whooshes",
"subtitles.item.flintandsteel.use": "Flint and Steel click",
+ "subtitles.item.goat_horn.play": "Goat Horn plays",
"subtitles.item.hoe.till": "Hoe tills",
"subtitles.item.honey_bottle.drink": "Gulping",
"subtitles.item.lodestone_compass.lock": "Lodestone Compass locks onto Lodestone",
@@ -4195,11 +4528,48 @@
"subtitles.ui.loom.take_result": "Loom used",
"subtitles.ui.stonecutter.take_result": "Stonecutter used",
"subtitles.weather.rain": "Rain falls",
+ "telemetry_info.screen.title": "Telemetry Data Collection",
+ "telemetry_info.screen.description": "Collecting this data helps us improve Minecraft by guiding us in directions that are relevant to our players.\nYou can also send in additional feedback to help us keep improving Minecraft.",
+ "telemetry_info.button.show_data": "Open My Data",
+ "telemetry_info.button.give_feedback": "Give Feedback",
+ "telemetry_info.property_title": "Included Data",
+ "telemetry.property.user_id.title": "User ID",
+ "telemetry.property.client_id.title": "Client ID",
+ "telemetry.property.minecraft_session_id.title": "Minecraft Session ID",
+ "telemetry.property.game_version.title": "Game Version",
+ "telemetry.property.operating_system.title": "Operating System",
+ "telemetry.property.platform.title": "Platform",
+ "telemetry.property.client_modded.title": "Client Modded",
+ "telemetry.property.event_timestamp_utc.title": "Event Timestamp (UTC)",
+ "telemetry.property.opt_in.title": "Opt-In",
+ "telemetry.property.world_session_id.title": "World Session ID",
+ "telemetry.property.server_modded.title": "Server Modded",
+ "telemetry.property.server_type.title": "Server Type",
+ "telemetry.property.frame_rate_samples.title": "Frame Rate Samples (FPS)",
+ "telemetry.property.render_time_samples.title": "Render Time Samples",
+ "telemetry.property.used_memory_samples.title": "Used Random Access Memory",
+ "telemetry.property.number_of_samples.title": "Sample Count",
+ "telemetry.property.render_distance.title": "Render Distance",
+ "telemetry.property.dedicated_memory_kb.title": "Dedicated Memory (kB)",
+ "telemetry.property.game_mode.title": "Game Mode",
+ "telemetry.property.seconds_since_load.title": "Time Since Load (Seconds)",
+ "telemetry.property.ticks_since_load.title": "Time Since Load (Ticks)",
+ "telemetry.property.world_load_time_ms.title": "World Load Time (Milliseconds)",
+ "telemetry.property.new_world.title": "New World",
+ "telemetry.event.required": "%s (Required)",
+ "telemetry.event.optional": "%s (Optional)",
+ "telemetry.event.world_loaded.title": "World Loaded",
+ "telemetry.event.world_loaded.description": "Knowing how players play Minecraft (such as Game Mode, client or server modded, and game version) allows us to focus game updates to improve the areas that players care about most.\nThe World Loaded event is paired with the World Unloaded event to calculate how long the play session has lasted.",
+ "telemetry.event.world_unloaded.title": "World Unloaded",
+ "telemetry.event.world_unloaded.description": "This event is paired with the World Loaded event to calculate how long the world session has lasted.\nThe duration (in seconds and ticks) is measured when a world session has ended (quitting to title, disconnecting from a server).",
+ "telemetry.event.performance_metrics.title": "Performance Metrics",
+ "telemetry.event.performance_metrics.description": "Knowing the overall performance profile of Minecraft helps us tune and optimize the game for a wide range of machine specifications and operating systems. \nGame version is included to help us compare the performance profile for new versions of Minecraft.",
+ "telemetry.event.world_load_times.title": "World Load Times",
+ "telemetry.event.world_load_times.description": "It\u2019s important for us to understand how long it takes to join a world, and how that changes over time. For example, when we add new features or do larger technical changes, we need to see what impact that had on load times.",
"debug.prefix": "[Debug]:",
"debug.reload_chunks.help": "F3 + A = Reload chunks",
"debug.show_hitboxes.help": "F3 + B = Show hitboxes",
"debug.clear_chat.help": "F3 + D = Clear chat",
- "debug.cycle_renderdistance.help": "F3 + F = Cycle render distance (shift to invert)",
"debug.chunk_boundaries.help": "F3 + G = Show chunk boundaries",
"debug.advanced_tooltips.help": "F3 + H = Advanced tooltips",
"debug.creative_spectator.help": "F3 + N = Cycle previous gamemode <-> spectator",
@@ -4219,7 +4589,6 @@
"debug.reload_chunks.message": "Reloading all chunks",
"debug.show_hitboxes.on": "Hitboxes: shown",
"debug.show_hitboxes.off": "Hitboxes: hidden",
- "debug.cycle_renderdistance.message": "Render Distance: %s",
"debug.chunk_boundaries.on": "Chunk borders: shown",
"debug.chunk_boundaries.off": "Chunk borders: hidden",
"debug.advanced_tooltips.on": "Advanced tooltips: shown",
@@ -4259,20 +4628,24 @@
"advancements.adventure.adventuring_time.description": "Discover every biome",
"advancements.adventure.arbalistic.title": "Arbalistic",
"advancements.adventure.arbalistic.description": "Kill five unique mobs with one crossbow shot",
+ "advancements.adventure.avoid_vibration.title": "Sneak 100",
+ "advancements.adventure.avoid_vibration.description": "Sneak near a Sculk Sensor or Warden to prevent it from detecting you",
"advancements.adventure.bullseye.title": "Bullseye",
"advancements.adventure.bullseye.description": "Hit the bullseye of a Target block from at least 30 meters away",
"advancements.adventure.fall_from_world_height.title": "Caves & Cliffs",
"advancements.adventure.fall_from_world_height.description": "Free fall from the top of the world (build limit) to the bottom of the world and survive",
+ "advancements.adventure.kill_mob_near_sculk_catalyst.title": "It Spreads",
+ "advancements.adventure.kill_mob_near_sculk_catalyst.description": "Kill a mob near a Sculk Catalyst",
"advancements.adventure.walk_on_powder_snow_with_leather_boots.title": "Light as a Rabbit",
- "advancements.adventure.walk_on_powder_snow_with_leather_boots.description": "Walk on powder snow...without sinking in it",
+ "advancements.adventure.walk_on_powder_snow_with_leather_boots.description": "Walk on Powder Snow...without sinking in it",
"advancements.adventure.lightning_rod_with_villager_no_fire.title": "Surge Protector",
- "advancements.adventure.lightning_rod_with_villager_no_fire.description": "Protect a villager from an undesired shock without starting a fire",
+ "advancements.adventure.lightning_rod_with_villager_no_fire.description": "Protect a Villager from an undesired shock without starting a fire",
"advancements.adventure.spyglass_at_parrot.title": "Is It a Bird?",
- "advancements.adventure.spyglass_at_parrot.description": "Look at a parrot through a spyglass",
+ "advancements.adventure.spyglass_at_parrot.description": "Look at a Parrot through a Spyglass",
"advancements.adventure.spyglass_at_ghast.title": "Is It a Balloon?",
- "advancements.adventure.spyglass_at_ghast.description": "Look at a ghast through a spyglass",
+ "advancements.adventure.spyglass_at_ghast.description": "Look at a Ghast through a Spyglass",
"advancements.adventure.spyglass_at_dragon.title": "Is It a Plane?",
- "advancements.adventure.spyglass_at_dragon.description": "Look at the Ender Dragon through a spyglass",
+ "advancements.adventure.spyglass_at_dragon.description": "Look at the Ender Dragon through a Spyglass",
"advancements.adventure.hero_of_the_village.title": "Hero of the Village",
"advancements.adventure.hero_of_the_village.description": "Successfully defend a village from a raid",
"advancements.adventure.honey_block_slide.title": "Sticky Situation",
@@ -4282,15 +4655,15 @@
"advancements.adventure.kill_a_mob.title": "Monster Hunter",
"advancements.adventure.kill_a_mob.description": "Kill any hostile monster",
"advancements.adventure.ol_betsy.title": "Ol' Betsy",
- "advancements.adventure.ol_betsy.description": "Shoot a crossbow",
+ "advancements.adventure.ol_betsy.description": "Shoot a Crossbow",
"advancements.adventure.play_jukebox_in_meadows.title": "Sound of Music",
- "advancements.adventure.play_jukebox_in_meadows.description": "Make the Meadows come alive with the sound of music from a jukebox",
+ "advancements.adventure.play_jukebox_in_meadows.description": "Make the Meadows come alive with the sound of music from a Jukebox",
"advancements.adventure.root.title": "Adventure",
"advancements.adventure.root.description": "Adventure, exploration and combat",
"advancements.adventure.shoot_arrow.title": "Take Aim",
- "advancements.adventure.shoot_arrow.description": "Shoot something with an arrow",
+ "advancements.adventure.shoot_arrow.description": "Shoot something with an Arrow",
"advancements.adventure.sleep_in_bed.title": "Sweet Dreams",
- "advancements.adventure.sleep_in_bed.description": "Sleep in a bed to change your respawn point",
+ "advancements.adventure.sleep_in_bed.description": "Sleep in a Bed to change your respawn point",
"advancements.adventure.sniper_duel.title": "Sniper Duel",
"advancements.adventure.sniper_duel.description": "Kill a Skeleton from at least 50 meters away",
"advancements.adventure.summon_iron_golem.title": "Hired Help",
@@ -4300,11 +4673,11 @@
"advancements.adventure.trade.title": "What a Deal!",
"advancements.adventure.trade.description": "Successfully trade with a Villager",
"advancements.adventure.trade_at_world_height.title": "Star Trader",
- "advancements.adventure.trade_at_world_height.description": "Trade with a villager at the build height limit",
+ "advancements.adventure.trade_at_world_height.description": "Trade with a Villager at the build height limit",
"advancements.adventure.throw_trident.title": "A Throwaway Joke",
- "advancements.adventure.throw_trident.description": "Throw a trident at something.\nNote: Throwing away your only weapon is not a good idea.",
+ "advancements.adventure.throw_trident.description": "Throw a Trident at something.\nNote: Throwing away your only weapon is not a good idea.",
"advancements.adventure.two_birds_one_arrow.title": "Two Birds, One Arrow",
- "advancements.adventure.two_birds_one_arrow.description": "Kill two Phantoms with a piercing arrow",
+ "advancements.adventure.two_birds_one_arrow.description": "Kill two Phantoms with a piercing Arrow",
"advancements.adventure.very_very_frightening.title": "Very Very Frightening",
"advancements.adventure.very_very_frightening.description": "Strike a Villager with lightning",
"advancements.adventure.voluntary_exile.title": "Voluntary Exile",
@@ -4318,15 +4691,21 @@
"advancements.husbandry.fishy_business.title": "Fishy Business",
"advancements.husbandry.fishy_business.description": "Catch a fish",
"advancements.husbandry.make_a_sign_glow.title": "Glow and Behold!",
- "advancements.husbandry.make_a_sign_glow.description": "Make the text of a sign glow",
+ "advancements.husbandry.make_a_sign_glow.description": "Make the text of any kind of sign glow",
"advancements.husbandry.ride_a_boat_with_a_goat.title": "Whatever Floats Your Goat!",
"advancements.husbandry.ride_a_boat_with_a_goat.description": "Get in a Boat and float with a Goat",
"advancements.husbandry.tactical_fishing.title": "Tactical Fishing",
- "advancements.husbandry.tactical_fishing.description": "Catch a fish... without a fishing rod!",
+ "advancements.husbandry.tactical_fishing.description": "Catch a Fish... without a Fishing Rod!",
"advancements.husbandry.axolotl_in_a_bucket.title": "The Cutest Predator",
- "advancements.husbandry.axolotl_in_a_bucket.description": "Catch an axolotl in a bucket",
+ "advancements.husbandry.axolotl_in_a_bucket.description": "Catch an Axolotl in a Bucket",
+ "advancements.husbandry.froglights.title": "With Our Powers Combined!",
+ "advancements.husbandry.froglights.description": "Have all Froglights in your inventory",
+ "advancements.husbandry.tadpole_in_a_bucket.title": "Bukkit Bukkit",
+ "advancements.husbandry.tadpole_in_a_bucket.description": "Catch a Tadpole in a Bucket",
+ "advancements.husbandry.leash_all_frog_variants.title": "When the Squad Hops into Town",
+ "advancements.husbandry.leash_all_frog_variants.description": "Get each Frog variant on a Lead",
"advancements.husbandry.kill_axolotl_target.title": "The Healing Power of Friendship!",
- "advancements.husbandry.kill_axolotl_target.description": "Team up with an axolotl and win a fight",
+ "advancements.husbandry.kill_axolotl_target.description": "Team up with an Axolotl and win a fight",
"advancements.husbandry.breed_all_animals.title": "Two by Two",
"advancements.husbandry.breed_all_animals.description": "Breed all the animals!",
"advancements.husbandry.tame_an_animal.title": "Best Friends Forever",
@@ -4334,25 +4713,29 @@
"advancements.husbandry.plant_seed.title": "A Seedy Place",
"advancements.husbandry.plant_seed.description": "Plant a seed and watch it grow",
"advancements.husbandry.netherite_hoe.title": "Serious Dedication",
- "advancements.husbandry.netherite_hoe.description": "Use a Netherite ingot to upgrade a hoe, and then reevaluate your life choices",
+ "advancements.husbandry.netherite_hoe.description": "Use a Netherite Ingot to upgrade a Hoe, and then reevaluate your life choices",
"advancements.husbandry.balanced_diet.title": "A Balanced Diet",
"advancements.husbandry.balanced_diet.description": "Eat everything that is edible, even if it's not good for you",
"advancements.husbandry.complete_catalogue.title": "A Complete Catalogue",
- "advancements.husbandry.complete_catalogue.description": "Tame all cat variants!",
+ "advancements.husbandry.complete_catalogue.description": "Tame all Cat variants!",
"advancements.husbandry.safely_harvest_honey.title": "Bee Our Guest",
- "advancements.husbandry.safely_harvest_honey.description": "Use a Campfire to collect Honey from a Beehive using a Bottle without aggravating the bees",
+ "advancements.husbandry.safely_harvest_honey.description": "Use a Campfire to collect Honey from a Beehive using a Bottle without aggravating the Bees",
"advancements.husbandry.silk_touch_nest.title": "Total Beelocation",
- "advancements.husbandry.silk_touch_nest.description": "Move a Bee Nest, with 3 bees inside, using Silk Touch",
+ "advancements.husbandry.silk_touch_nest.description": "Move a Bee Nest, with 3 Bees inside, using Silk Touch",
"advancements.husbandry.wax_on.title": "Wax On",
"advancements.husbandry.wax_on.description": "Apply Honeycomb to a Copper block!",
"advancements.husbandry.wax_off.title": "Wax Off",
"advancements.husbandry.wax_off.description": "Scrape Wax off of a Copper block!",
+ "advancements.husbandry.allay_deliver_item_to_player.title": "You've Got a Friend in Me",
+ "advancements.husbandry.allay_deliver_item_to_player.description": "Have an Allay deliver items to you",
+ "advancements.husbandry.allay_deliver_cake_to_note_block.title": "Birthday Song",
+ "advancements.husbandry.allay_deliver_cake_to_note_block.description": "Have an Allay drop a Cake at a Note Block",
"advancements.end.dragon_breath.title": "You Need a Mint",
- "advancements.end.dragon_breath.description": "Collect dragon's breath in a glass bottle",
+ "advancements.end.dragon_breath.description": "Collect Dragon's Breath in a Glass Bottle",
"advancements.end.dragon_egg.title": "The Next Generation",
"advancements.end.dragon_egg.description": "Hold the Dragon Egg",
"advancements.end.elytra.title": "Sky's the Limit",
- "advancements.end.elytra.description": "Find elytra",
+ "advancements.end.elytra.description": "Find Elytra",
"advancements.end.enter_end_gateway.title": "Remote Getaway",
"advancements.end.enter_end_gateway.description": "Escape the island",
"advancements.end.find_end_city.title": "The City at the End of the Game",
@@ -4366,15 +4749,15 @@
"advancements.end.root.title": "The End",
"advancements.end.root.description": "Or the beginning?",
"advancements.nether.brew_potion.title": "Local Brewery",
- "advancements.nether.brew_potion.description": "Brew a potion",
+ "advancements.nether.brew_potion.description": "Brew a Potion",
"advancements.nether.all_potions.title": "A Furious Cocktail",
"advancements.nether.all_potions.description": "Have every potion effect applied at the same time",
"advancements.nether.all_effects.title": "How Did We Get Here?",
"advancements.nether.all_effects.description": "Have every effect applied at the same time",
"advancements.nether.create_beacon.title": "Bring Home the Beacon",
- "advancements.nether.create_beacon.description": "Construct and place a beacon",
+ "advancements.nether.create_beacon.description": "Construct and place a Beacon",
"advancements.nether.create_full_beacon.title": "Beaconator",
- "advancements.nether.create_full_beacon.description": "Bring a beacon to full power",
+ "advancements.nether.create_full_beacon.description": "Bring a Beacon to full power",
"advancements.nether.find_fortress.title": "A Terrible Fortress",
"advancements.nether.find_fortress.description": "Break your way into a Nether Fortress",
"advancements.nether.get_wither_skull.title": "Spooky Scary Skeleton",
@@ -4396,27 +4779,27 @@
"advancements.nether.netherite_armor.title": "Cover Me in Debris",
"advancements.nether.netherite_armor.description": "Get a full suit of Netherite armor",
"advancements.nether.use_lodestone.title": "Country Lode, Take Me Home",
- "advancements.nether.use_lodestone.description": "Use a compass on a Lodestone",
+ "advancements.nether.use_lodestone.description": "Use a Compass on a Lodestone",
"advancements.nether.obtain_crying_obsidian.title": "Who is Cutting Onions?",
"advancements.nether.obtain_crying_obsidian.description": "Obtain Crying Obsidian",
"advancements.nether.charge_respawn_anchor.title": "Not Quite \"Nine\" Lives",
"advancements.nether.charge_respawn_anchor.description": "Charge a Respawn Anchor to the maximum",
"advancements.nether.ride_strider.title": "This Boat Has Legs",
"advancements.nether.ride_strider.description": "Ride a Strider with a Warped Fungus on a Stick",
- "advancements.nether.ride_strider_in_overworld_lava.title": "Feels like home",
+ "advancements.nether.ride_strider_in_overworld_lava.title": "Feels Like Home",
"advancements.nether.ride_strider_in_overworld_lava.description": "Take a Strider for a loooong ride on a lava lake in the Overworld",
"advancements.nether.explore_nether.title": "Hot Tourist Destinations",
"advancements.nether.explore_nether.description": "Explore all Nether biomes",
"advancements.nether.find_bastion.title": "Those Were the Days",
"advancements.nether.find_bastion.description": "Enter a Bastion Remnant",
"advancements.nether.loot_bastion.title": "War Pigs",
- "advancements.nether.loot_bastion.description": "Loot a chest in a Bastion Remnant",
+ "advancements.nether.loot_bastion.description": "Loot a Chest in a Bastion Remnant",
"advancements.nether.distract_piglin.title": "Oh Shiny",
"advancements.nether.distract_piglin.description": "Distract Piglins with gold",
"advancements.story.cure_zombie_villager.title": "Zombie Doctor",
"advancements.story.cure_zombie_villager.description": "Weaken and then cure a Zombie Villager",
"advancements.story.deflect_arrow.title": "Not Today, Thank You",
- "advancements.story.deflect_arrow.description": "Deflect a projectile with a shield",
+ "advancements.story.deflect_arrow.description": "Deflect a projectile with a Shield",
"advancements.story.enchant_item.title": "Enchanter",
"advancements.story.enchant_item.description": "Enchant an item at an Enchanting Table",
"advancements.story.enter_the_end.title": "The End?",
@@ -4426,15 +4809,15 @@
"advancements.story.follow_ender_eye.title": "Eye Spy",
"advancements.story.follow_ender_eye.description": "Follow an Eye of Ender",
"advancements.story.form_obsidian.title": "Ice Bucket Challenge",
- "advancements.story.form_obsidian.description": "Obtain a block of obsidian",
+ "advancements.story.form_obsidian.description": "Obtain a block of Obsidian",
"advancements.story.iron_tools.title": "Isn't It Iron Pick",
- "advancements.story.iron_tools.description": "Upgrade your pickaxe",
+ "advancements.story.iron_tools.description": "Upgrade your Pickaxe",
"advancements.story.lava_bucket.title": "Hot Stuff",
- "advancements.story.lava_bucket.description": "Fill a bucket with lava",
+ "advancements.story.lava_bucket.description": "Fill a Bucket with lava",
"advancements.story.mine_diamond.title": "Diamonds!",
"advancements.story.mine_diamond.description": "Acquire diamonds",
"advancements.story.mine_stone.title": "Stone Age",
- "advancements.story.mine_stone.description": "Mine stone with your new pickaxe",
+ "advancements.story.mine_stone.description": "Mine Stone with your new Pickaxe",
"advancements.story.obtain_armor.title": "Suit Up",
"advancements.story.obtain_armor.description": "Protect yourself with a piece of iron armor",
"advancements.story.root.title": "Minecraft",
@@ -4442,9 +4825,9 @@
"advancements.story.shiny_gear.title": "Cover Me with Diamonds",
"advancements.story.shiny_gear.description": "Diamond armor saves lives",
"advancements.story.smelt_iron.title": "Acquire Hardware",
- "advancements.story.smelt_iron.description": "Smelt an iron ingot",
+ "advancements.story.smelt_iron.description": "Smelt an Iron Ingot",
"advancements.story.upgrade_tools.title": "Getting an Upgrade",
- "advancements.story.upgrade_tools.description": "Construct a better pickaxe",
+ "advancements.story.upgrade_tools.description": "Construct a better Pickaxe",
"team.visibility.always": "Always",
"team.visibility.never": "Never",
"team.visibility.hideForOtherTeams": "Hide for other teams",
@@ -4480,6 +4863,10 @@
"argument.entity.options.scores.description": "Entities with scores",
"argument.entity.options.advancements.description": "Players with advancements",
"argument.entity.options.predicate.description": "Custom predicate",
+ "argument.resource.not_found": "Can't find element '%s' of type '%s'",
+ "argument.resource.invalid_type": "Element '%s' has wrong type '%s' (expected '%s')",
+ "argument.resource_tag.not_found": "Can't find tag '%s' of type '%s'",
+ "argument.resource_tag.invalid_type": "Tag '%s' has wrong type '%s' (expected '%s')",
"command.failed": "An unexpected error occurred trying to execute that command",
"command.context.here": "<--[HERE]",
"command.context.parse_error": "%s at position %s: %s",
@@ -4588,8 +4975,6 @@
"commands.kill.success.single": "Killed %s",
"commands.kill.success.multiple": "Killed %s entities",
"commands.kick.success": "Kicked %s: %s",
- "commands.locate.success": "The nearest %s is at %s (%s blocks away)",
- "commands.locatebiome.success": "The nearest %s is at %s (%s blocks away)",
"commands.message.display.outgoing": "You whisper to %s: %s",
"commands.message.display.incoming": "%s whispers to you: %s",
"commands.op.success": "Made %s a server operator",
@@ -4806,6 +5191,8 @@
"argument.entity.notfound.player": "No player was found",
"argument.player.unknown": "That player does not exist",
"arguments.nbtpath.node.invalid": "Invalid NBT path element",
+ "arguments.nbtpath.too_deep": "Resulting NBT too deeply nested",
+ "arguments.nbtpath.too_large": "Resulting NBT too large",
"arguments.nbtpath.nothing_found": "Found no elements matching %s",
"arguments.operation.invalid": "Invalid operation",
"arguments.operation.div0": "Cannot divide by zero",
@@ -4836,6 +5223,7 @@
"argument.id.invalid": "Invalid ID",
"argument.time.invalid_unit": "Invalid unit",
"argument.time.invalid_tick_count": "Tick count must be non-negative",
+ "argument.enum.invalid": "Invalid value \"%s\"",
"commands.banip.invalid": "Invalid IP address or unknown player",
"commands.banip.failed": "Nothing changed. That IP is already banned",
"commands.ban.failed": "Nothing changed. The player is already banned",
@@ -4856,19 +5244,32 @@
"commands.enchant.failed": "Nothing changed. Targets either have no item in their hands or the enchantment could not be applied",
"commands.experience.set.points.invalid": "Cannot set experience points above the maximum points for the player's current level",
"commands.fill.failed": "No blocks were filled",
+ "argument.gamemode.invalid": "Unknown gamemode: %s",
"commands.help.failed": "Unknown command or insufficient permissions",
- "commands.locate.failed": "Could not find a structure of type \"%s\" nearby",
- "commands.locate.invalid": "There is no structure with type \"%s\"",
- "commands.locatebiome.notFound": "Could not find a biome of type \"%s\" within reasonable distance",
- "commands.locatebiome.invalid": "There is no biome with type \"%s\"",
+ "commands.locate.structure.success": "The nearest %s is at %s (%s blocks away)",
+ "commands.locate.structure.not_found": "Could not find a structure of type \"%s\" nearby",
+ "commands.locate.structure.invalid": "There is no structure with type \"%s\"",
+ "commands.locate.biome.success": "The nearest %s is at %s (%s blocks away)",
+ "commands.locate.biome.not_found": "Could not find a biome of type \"%s\" within reasonable distance",
+ "commands.locate.poi.success": "The nearest %s is at %s (%s blocks away)",
+ "commands.locate.poi.not_found": "Could not find a point of interest of type \"%s\" within reasonable distance",
"commands.op.failed": "Nothing changed. The player already is an operator",
"commands.pardon.failed": "Nothing changed. The player isn't banned",
"commands.pardonip.invalid": "Invalid IP address",
"commands.pardonip.failed": "Nothing changed. That IP isn't banned",
"commands.particle.failed": "The particle was not visible for anybody",
- "commands.placefeature.failed": "Failed to place feature",
- "commands.placefeature.invalid": "There is no feature with type \"%s\"",
- "commands.placefeature.success": "Placed \"%s\" at %s, %s, %s",
+ "commands.place.feature.failed": "Failed to place feature",
+ "commands.place.feature.invalid": "There is no feature with type \"%s\"",
+ "commands.place.feature.success": "Placed \"%s\" at %s, %s, %s",
+ "commands.place.jigsaw.failed": "Failed to generate jigsaw",
+ "commands.place.jigsaw.invalid": "There is no template pool with type \"%s\"",
+ "commands.place.jigsaw.success": "Generated jigsaw at %s, %s, %s",
+ "commands.place.structure.failed": "Failed to place structure",
+ "commands.place.structure.invalid": "There is no structure with type \"%s\"",
+ "commands.place.structure.success": "Generated structure \"%s\" at %s, %s, %s",
+ "commands.place.template.failed": "Failed to place template",
+ "commands.place.template.invalid": "There is no template with id \"%s\"",
+ "commands.place.template.success": "Loaded template \"%s\" at %s, %s, %s",
"commands.playsound.failed": "The sound is too far away to be heard",
"commands.recipe.give.failed": "No new recipes were learned",
"commands.recipe.take.failed": "No recipes could be forgotten",
@@ -4924,9 +5325,7 @@
"argument.dimension.invalid": "Unknown dimension '%s'",
"argument.component.invalid": "Invalid chat component: %s",
"argument.anchor.invalid": "Invalid entity anchor position %s",
- "enchantment.unknown": "Unknown enchantment: %s",
"lectern.take_book": "Take Book",
- "effect.effectNotFound": "Unknown effect: %s",
"arguments.objective.notFound": "Unknown scoreboard objective '%s'",
"arguments.objective.readonly": "Scoreboard objective '%s' is read-only",
"argument.criteria.invalid": "Unknown criterion '%s'",
@@ -4934,7 +5333,7 @@
"argument.id.unknown": "Unknown ID: %s",
"advancement.advancementNotFound": "Unknown advancement: %s",
"recipe.notFound": "Unknown recipe: %s",
- "entity.notFound": "Unknown entity: %s",
+ "entity.not_summonable": "Can't summon entity of type %s",
"predicate.unknown": "Unknown predicate: %s",
"item_modifier.unknown": "Unknown item modifier: %s",
"argument.scoreboardDisplaySlot.invalid": "Unknown display slot '%s'",
@@ -4968,6 +5367,7 @@
"commands.clone.toobig": "Too many blocks in the specified area (maximum %s, specified %s)",
"commands.datapack.unknown": "Unknown data pack '%s'",
"commands.datapack.enable.failed": "Pack '%s' is already enabled!",
+ "commands.datapack.enable.failed.no_flags": "Pack '%s' cannot be enabled, since required flags are not enabled in this world: %s!",
"commands.datapack.disable.failed": "Pack '%s' is not enabled!",
"commands.difficulty.failure": "The difficulty did not change; it is already set to %s",
"commands.enchant.failed.entity": "%s is not a valid entity for this command",
@@ -4980,6 +5380,9 @@
"commands.execute.conditional.fail": "Test failed",
"commands.execute.conditional.fail_count": "Test failed, count: %s",
"commands.fill.toobig": "Too many blocks in the specified area (maximum %s, specified %s)",
+ "commands.fillbiome.toobig": "Too many blocks in the specified volume (maximum %s, specified %s)",
+ "commands.fillbiome.success": "Biomes set between %s, %s, %s and %s, %s, %s",
+ "commands.fillbiome.success.count": "%s biome entries set between %s, %s, %s and %s, %s, %s",
"commands.publish.alreadyPublished": "Multiplayer game is already hosted on port %s",
"commands.scoreboard.players.get.null": "Can't get value of %s for %s; none is set",
"commands.spreadplayers.failed.teams": "Could not spread %s teams around %s, %s (too many entities for space - try using spread of at most %s)",
@@ -5023,6 +5426,7 @@
"biome.minecraft.crimson_forest": "Crimson Forest",
"biome.minecraft.dark_forest": "Dark Forest",
"biome.minecraft.deep_cold_ocean": "Deep Cold Ocean",
+ "biome.minecraft.deep_dark": "Deep Dark",
"biome.minecraft.deep_frozen_ocean": "Deep Frozen Ocean",
"biome.minecraft.deep_lukewarm_ocean": "Deep Lukewarm Ocean",
"biome.minecraft.deep_ocean": "Deep Ocean",
@@ -5046,6 +5450,7 @@
"biome.minecraft.jungle": "Jungle",
"biome.minecraft.lukewarm_ocean": "Lukewarm Ocean",
"biome.minecraft.lush_caves": "Lush Caves",
+ "biome.minecraft.mangrove_swamp": "Mangrove Swamp",
"biome.minecraft.meadow": "Meadow",
"biome.minecraft.mushroom_fields": "Mushroom Fields",
"biome.minecraft.nether_wastes": "Nether Wastes",
@@ -5116,7 +5521,8 @@
"gamerule.doPatrolSpawning": "Spawn pillager patrols",
"gamerule.doTileDrops": "Drop blocks",
"gamerule.doTileDrops.description": "Controls resource drops from blocks, including experience orbs",
- "gamerule.doTraderSpawning": "Spawn wandering traders",
+ "gamerule.doTraderSpawning": "Spawn Wandering Traders",
+ "gamerule.doWardenSpawning": "Spawn Wardens",
"gamerule.doWeatherCycle": "Update weather",
"gamerule.drowningDamage": "Deal drowning damage",
"gamerule.fallDamage": "Deal fall damage",
@@ -5142,6 +5548,20 @@
"gamerule.spectatorsGenerateChunks": "Allow spectators to generate terrain",
"gamerule.universalAnger": "Universal anger",
"gamerule.universalAnger.description": "Angered neutral mobs attack any nearby player, not just the player that angered them. Works best if forgiveDeadPlayers is disabled.",
+ "gamerule.blockExplosionDropDecay": "In block interaction explosions, some blocks won't drop their loot",
+ "gamerule.blockExplosionDropDecay.description": "Some of the drops from blocks destroyed by explosions caused by block interactions are lost in the explosion.",
+ "gamerule.mobExplosionDropDecay": "In mob explosions, some blocks won't drop their loot",
+ "gamerule.mobExplosionDropDecay.description": "Some of the drops from blocks destroyed by explosions caused by mobs are lost in the explosion.",
+ "gamerule.tntExplosionDropDecay": "In TNT explosions, some blocks won't drop their loot",
+ "gamerule.tntExplosionDropDecay.description": "Some of the drops from blocks destroyed by explosions caused by TNT are lost in the explosion.",
+ "gamerule.snowAccumulationHeight": "Snow accumulation height",
+ "gamerule.snowAccumulationHeight.description": "When it snows, layers of snow form on the ground up to at most this number of layers.",
+ "gamerule.waterSourceConversion": "Water converts to source",
+ "gamerule.waterSourceConversion.description": "When flowing water is surrounded on two sides by water sources it converts into a source.",
+ "gamerule.lavaSourceConversion": "Lava converts to source",
+ "gamerule.lavaSourceConversion.description": "When flowing lava is surrounded on two sides by lava sources it converts into a source.",
+ "gamerule.globalSoundEvents": "Global sound events",
+ "gamerule.globalSoundEvents.description": "When certain game events happen, like a boss spawning, the sound is heard everywhere.",
"gamerule.category.chat": "Chat",
"gamerule.category.spawning": "Spawning",
"gamerule.category.updates": "World Updates",
@@ -5150,6 +5570,7 @@
"gamerule.category.player": "Player",
"gamerule.category.misc": "Miscellaneous",
"pack.source.builtin": "built-in",
+ "pack.source.feature": "feature",
"pack.source.world": "world",
"pack.source.local": "local",
"pack.source.server": "server",
@@ -5161,5 +5582,241 @@
"sleep.skipping_night": "Sleeping through this night",
"compliance.playtime.greaterThan24Hours": "You've been playing for greater than 24 hours",
"compliance.playtime.message": "Excessive gaming may interfere with normal daily life",
- "compliance.playtime.hours": "You've been playing for %s hour(s)"
-}
+ "compliance.playtime.hours": "You've been playing for %s hour(s)",
+ "outOfMemory.title": "Out of memory!",
+ "outOfMemory.message": "Minecraft has run out of memory.\n\nThis could be caused by a bug in the game or by the Java Virtual Machine not being allocated enough memory.\n\nTo prevent level corruption, the current game has quit. We've tried to free up enough memory to let you go back to the main menu and back to playing, but this may not have worked.\n\nPlease restart the game if you see this message again.",
+ "mco.gui.ok": "Ok",
+ "mco.gui.button": "Button",
+ "mco.terms.buttons.agree": "Agree",
+ "mco.terms.buttons.disagree": "Don't agree",
+ "mco.terms.title": "Realms Terms of Service",
+ "mco.terms.sentence.1": "I agree to the Minecraft Realms",
+ "mco.terms.sentence.2": "Terms of Service",
+ "mco.selectServer.play": "Play",
+ "mco.selectServer.configure": "Configure",
+ "mco.selectServer.configureRealm": "Configure realm",
+ "mco.selectServer.leave": "Leave realm",
+ "mco.selectServer.create": "Create realm",
+ "mco.selectServer.purchase": "Add Realm",
+ "mco.selectServer.buy": "Buy a realm!",
+ "mco.selectServer.trial": "Get a trial!",
+ "mco.selectServer.close": "Close",
+ "mco.selectServer.expiredTrial": "Your trial has ended",
+ "mco.selectServer.expiredList": "Your subscription has expired",
+ "mco.selectServer.expiredSubscribe": "Subscribe",
+ "mco.selectServer.expiredRenew": "Renew",
+ "mco.selectServer.expired": "Expired realm",
+ "mco.selectServer.open": "Open realm",
+ "mco.selectServer.closed": "Closed realm",
+ "mco.selectServer.openserver": "Open realm",
+ "mco.selectServer.closeserver": "Close realm",
+ "mco.selectServer.minigame": "Minigame:",
+ "mco.selectServer.uninitialized": "Click to start your new realm!",
+ "mco.selectServer.expires.days": "Expires in %s days",
+ "mco.selectServer.expires.day": "Expires in a day",
+ "mco.selectServer.expires.soon": "Expires soon",
+ "mco.selectServer.note": "Note:",
+ "mco.selectServer.mapOnlySupportedForVersion": "This map is unsupported in %s",
+ "mco.selectServer.minigameNotSupportedInVersion": "Can't play this minigame in %s",
+ "mco.selectServer.popup": "Realms is a safe, simple way to enjoy an online Minecraft world with up to ten friends at a time. It supports loads of minigames and plenty of custom worlds! Only the owner of the realm needs to pay.",
+ "mco.configure.world.settings.title": "Settings",
+ "mco.configure.world.title": "Configure realm:",
+ "mco.configure.worlds.title": "Worlds",
+ "mco.configure.world.name": "Realm name",
+ "mco.configure.world.description": "Realm description",
+ "mco.configure.world.location": "Location",
+ "mco.configure.world.invited": "Invited",
+ "mco.configure.world.invite.narration": "You have %s new invites",
+ "mco.configure.world.buttons.edit": "Settings",
+ "mco.configure.world.buttons.done": "Done",
+ "mco.configure.world.buttons.delete": "Delete",
+ "mco.configure.world.buttons.open": "Open realm",
+ "mco.configure.world.buttons.close": "Close realm",
+ "mco.configure.world.buttons.invite": "Invite player",
+ "mco.configure.world.buttons.activity": "Player activity",
+ "mco.configure.world.activityfeed.disabled": "Player feed temporarily disabled",
+ "mco.configure.world.buttons.moreoptions": "More options",
+ "mco.configure.world.invite.profile.name": "Name",
+ "mco.configure.world.uninvite.question": "Are you sure that you want to uninvite",
+ "mco.configure.world.status": "Status",
+ "mco.configure.world.invites.ops.tooltip": "Operator",
+ "mco.configure.world.invites.normal.tooltip": "Normal user",
+ "mco.configure.world.invites.remove.tooltip": "Remove",
+ "mco.configure.world.closing": "Closing the realm...",
+ "mco.configure.world.opening": "Opening the realm...",
+ "mco.configure.world.buttons.players": "Players",
+ "mco.configure.world.buttons.settings": "Settings",
+ "mco.configure.world.buttons.subscription": "Subscription",
+ "mco.configure.world.buttons.options": "World options",
+ "mco.configure.world.backup": "World backups",
+ "mco.configure.world.buttons.resetworld": "Reset world",
+ "mco.configure.world.buttons.switchminigame": "Switch minigame",
+ "mco.configure.current.minigame": "Current",
+ "mco.configure.world.subscription.title": "Your subscription",
+ "mco.configure.world.subscription.timeleft": "Time left",
+ "mco.configure.world.subscription.unknown": "Unknown",
+ "mco.configure.world.subscription.recurring.daysleft": "Renewed automatically in",
+ "mco.configure.world.subscription.less_than_a_day": "Less than a day",
+ "mco.configure.world.subscription.expired": "Expired",
+ "mco.configure.world.subscription.start": "Start date",
+ "mco.configure.world.subscription.extend": "Extend subscription",
+ "mco.configure.world.subscription.day": "day",
+ "mco.configure.world.subscription.month": "month",
+ "mco.configure.world.subscription.days": "days",
+ "mco.configure.world.subscription.months": "months",
+ "mco.configure.world.pvp": "PVP",
+ "mco.configure.world.spawn_toggle.title": "Warning!",
+ "mco.configure.world.spawn_toggle.message": "Turning this option off will REMOVE ALL existing entities of that type",
+ "mco.configure.world.spawn_toggle.message.npc": "Turning this option off will REMOVE ALL existing entities of that type, like Villagers",
+ "mco.configure.world.spawnAnimals": "Spawn animals",
+ "mco.configure.world.spawnNPCs": "Spawn NPCs",
+ "mco.configure.world.spawnMonsters": "Spawn monsters",
+ "mco.configure.world.spawnProtection": "Spawn protection",
+ "mco.configure.world.commandBlocks": "Command blocks",
+ "mco.configure.world.forceGameMode": "Force game mode",
+ "mco.configure.world.slot": "World %s",
+ "mco.configure.world.slot.empty": "Empty",
+ "mco.create.world.wait": "Creating the realm...",
+ "mco.create.world.error": "You must enter a name!",
+ "mco.create.world.subtitle": "Optionally, select what world to put on your new realm",
+ "mco.create.world.skip": "Skip",
+ "mco.reset.world.title": "Reset world",
+ "mco.reset.world.warning": "This will replace the current world of your realm",
+ "mco.reset.world.seed": "Seed (Optional)",
+ "mco.reset.world.resetting.screen.title": "Resetting world...",
+ "mco.reset.world.generate": "New world",
+ "mco.reset.world.upload": "Upload world",
+ "mco.reset.world.adventure": "Adventures",
+ "mco.reset.world.template": "World templates",
+ "mco.reset.world.experience": "Experiences",
+ "mco.reset.world.inspiration": "Inspiration",
+ "mco.minigame.world.title": "Switch realm to minigame",
+ "mco.minigame.world.info.line1": "This will temporarily replace your world with a minigame!",
+ "mco.minigame.world.info.line2": "You can later return to your original world without losing anything.",
+ "mco.minigame.world.selected": "Selected minigame:",
+ "mco.minigame.world.noSelection": "Please make a selection",
+ "mco.minigame.world.startButton": "Switch",
+ "mco.minigame.world.starting.screen.title": "Starting minigame...",
+ "mco.minigame.world.changeButton": "Select another minigame",
+ "mco.minigame.world.stopButton": "End minigame",
+ "mco.minigame.world.switch.title": "Switch minigame",
+ "mco.minigame.world.switch.new": "Select another minigame?",
+ "mco.minigame.world.restore.question.line1": "The minigame will end and your realm will be restored.",
+ "mco.minigame.world.restore.question.line2": "Are you sure you want to continue?",
+ "mco.minigame.world.restore": "Ending minigame...",
+ "mco.configure.world.slot.tooltip": "Switch to world",
+ "mco.configure.world.slot.tooltip.minigame": "Switch to minigame",
+ "mco.configure.world.slot.tooltip.active": "Join",
+ "mco.configure.world.close.question.line1": "Your realm will become unavailable.",
+ "mco.configure.world.close.question.line2": "Are you sure you want to continue?",
+ "mco.configure.world.leave.question.line1": "If you leave this realm you won't see it unless you are invited again",
+ "mco.configure.world.leave.question.line2": "Are you sure you want to continue?",
+ "mco.configure.world.resourcepack.question.line1": "You need a custom resource pack to play on this realm",
+ "mco.configure.world.resourcepack.question.line2": "Do you want to download it and play?",
+ "mco.configure.world.reset.question.line1": "Your world will be regenerated and your current world will be lost",
+ "mco.configure.world.reset.question.line2": "Are you sure you want to continue?",
+ "mco.configure.world.restore.question.line1": "Your world will be restored to date '%s' (%s)",
+ "mco.configure.world.restore.question.line2": "Are you sure you want to continue?",
+ "mco.configure.world.restore.download.question.line1": "The world will be downloaded and added to your single player worlds.",
+ "mco.configure.world.restore.download.question.line2": "Do you want to continue?",
+ "mco.configure.world.slot.switch.question.line1": "Your realm will be switched to another world",
+ "mco.configure.world.slot.switch.question.line2": "Are you sure you want to continue?",
+ "mco.configure.world.switch.slot": "Create world",
+ "mco.configure.world.switch.slot.subtitle": "This world is empty, choose how to create your world",
+ "mco.minigame.world.slot.screen.title": "Switching world...",
+ "mco.configure.world.edit.subscreen.adventuremap": "Some settings are disabled since your current world is an adventure",
+ "mco.configure.world.edit.subscreen.experience": "Some settings are disabled since your current world is an experience",
+ "mco.configure.world.edit.subscreen.inspiration": "Some settings are disabled since your current world is an inspiration",
+ "mco.configure.world.edit.slot.name": "World name",
+ "mco.configure.world.players.title": "Players",
+ "mco.configure.world.players.error": "A player with the provided name does not exist",
+ "mco.configure.world.delete.button": "Delete realm",
+ "mco.configure.world.delete.question.line1": "Your realm will be permanently deleted",
+ "mco.configure.world.delete.question.line2": "Are you sure you want to continue?",
+ "mco.connect.connecting": "Connecting to the realm...",
+ "mco.connect.authorizing": "Logging in...",
+ "mco.connect.failed": "Failed to connect to the realm",
+ "mco.connect.success": "Done",
+ "mco.create.world": "Create",
+ "mco.create.world.reset.title": "Creating world...",
+ "mco.client.incompatible.title": "Client incompatible!",
+ "mco.client.incompatible.msg.line1": "Your client is not compatible with Realms.",
+ "mco.client.incompatible.msg.line2": "Please use the most recent version of Minecraft.",
+ "mco.client.incompatible.msg.line3": "Realms is not compatible with snapshot versions.",
+ "mco.backup.button.restore": "Restore",
+ "mco.backup.generate.world": "Generate world",
+ "mco.backup.restoring": "Restoring your realm",
+ "mco.backup.button.download": "Download latest",
+ "mco.backup.changes.tooltip": "Changes",
+ "mco.backup.nobackups": "This realm doesn't have any backups currently.",
+ "mco.backup.button.upload": "Upload world",
+ "mco.backup.button.reset": "Reset world",
+ "mco.download.title": "Downloading latest world",
+ "mco.download.cancelled": "Download cancelled",
+ "mco.download.failed": "Download failed",
+ "mco.download.done": "Download done",
+ "mco.download.downloading": "Downloading",
+ "mco.download.extracting": "Extracting",
+ "mco.download.preparing": "Preparing download",
+ "mco.download.confirmation.line1": "The world you are going to download is larger than %s",
+ "mco.download.confirmation.line2": "You won't be able to upload this world to your realm again",
+ "mco.template.title": "World templates",
+ "mco.template.title.minigame": "Minigames",
+ "mco.template.button.select": "Select",
+ "mco.template.button.trailer": "Trailer",
+ "mco.template.button.publisher": "Publisher",
+ "mco.template.default.name": "World template",
+ "mco.template.name": "Template",
+ "mco.template.info.tooltip": "Publisher website",
+ "mco.template.trailer.tooltip": "Map trailer",
+ "mco.template.select.none": "Oops, it looks like this content category is currently empty.\nPlease check back later for new content, or if you're a creator,\n%s.",
+ "mco.template.select.none.linkTitle": "consider submitting something yourself",
+ "mco.template.select.failure": "We couldn't retrieve the list of content for this category.\nPlease check your internet connection, or try again later.",
+ "mco.template.select.narrate.authors": "Authors: %s",
+ "mco.template.select.narrate.version": "version %s",
+ "mco.invites.button.accept": "Accept",
+ "mco.invites.button.reject": "Reject",
+ "mco.invites.title": "Pending Invites",
+ "mco.invites.pending": "New invites!",
+ "mco.invites.nopending": "No pending invites!",
+ "mco.upload.select.world.title": "Upload world",
+ "mco.upload.select.world.subtitle": "Please select a singleplayer world to upload",
+ "mco.upload.select.world.none": "No singleplayer worlds found!",
+ "mco.upload.button.name": "Upload",
+ "mco.upload.verifying": "Verifying your world",
+ "mco.upload.preparing": "Preparing your world",
+ "mco.upload.close.failure": "Could not close your realm, please try again later",
+ "mco.upload.size.failure.line1": "'%s' is too big!",
+ "mco.upload.size.failure.line2": "It is %s. The maximum allowed size is %s.",
+ "mco.upload.uploading": "Uploading '%s'",
+ "mco.upload.done": "Upload done",
+ "mco.upload.failed": "Upload failed! (%s)",
+ "mco.upload.cancelled": "Upload cancelled",
+ "mco.upload.hardcore": "Hardcore worlds can't be uploaded!",
+ "mco.activity.title": "Player activity",
+ "mco.activity.noactivity": "No activity for the past %s days",
+ "mco.errorMessage.6001": "Client outdated",
+ "mco.errorMessage.6002": "Terms of service not accepted",
+ "mco.errorMessage.6003": "Download limit reached",
+ "mco.errorMessage.6004": "Upload limit reached",
+ "mco.errorMessage.connectionFailure": "An error occurred, please try again later.",
+ "mco.errorMessage.serviceBusy": "Realms is busy at the moment.\nPlease try connecting to your Realm again in a couple of minutes.",
+ "mco.trial.message.line1": "Want to get your own realm?",
+ "mco.trial.message.line2": "Click here for more info!",
+ "mco.brokenworld.play": "Play",
+ "mco.brokenworld.download": "Download",
+ "mco.brokenworld.downloaded": "Downloaded",
+ "mco.brokenworld.reset": "Reset",
+ "mco.brokenworld.title": "Your current world is no longer supported",
+ "mco.brokenworld.message.line1": "Please reset or select another world.",
+ "mco.brokenworld.message.line2": "You can also choose to download the world to singleplayer.",
+ "mco.brokenworld.minigame.title": "This minigame is no longer supported",
+ "mco.brokenworld.nonowner.title": "World is out of date",
+ "mco.brokenworld.nonowner.error": "Please wait for the realm owner to reset the world",
+ "mco.error.invalid.session.title": "Invalid session",
+ "mco.error.invalid.session.message": "Please try restarting Minecraft",
+ "mco.news": "Realms news",
+ "mco.account.privacyinfo": "Mojang implements certain procedures to help protect children and their privacy including complying with the Children\u2019s Online Privacy Protection Act (COPPA) and General Data Protection Regulation (GDPR).\n\nYou may need to obtain parental consent before accessing your Realms account.\n\nIf you have an older Minecraft account (you log in with your username), you need to migrate the account to a Mojang account in order to access Realms.",
+ "mco.account.update": "Update account",
+ "mco.account.privacy.info": "Read more about Mojang and privacy laws"
+}
\ No newline at end of file
diff --git a/azalea-physics/src/collision/blocks.rs b/azalea-physics/src/collision/blocks.rs
old mode 100755
new mode 100644
index b0637a59..73b96454
--- a/azalea-physics/src/collision/blocks.rs
+++ b/azalea-physics/src/collision/blocks.rs
@@ -17,7 +17,9 @@ pub trait BlockWithShape {
static SHAPE0: Lazy = Lazy::new(|| collision::empty_shape());
static SHAPE1: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 1., 1.));
-static SHAPE2: Lazy = Lazy::new(|| {
+static SHAPE2: Lazy =
+ Lazy::new(|| collision::box_shape(0.4375, 0., 0.4375, 0.5625, 1., 0.5625));
+static SHAPE3: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 0.1875, 0.5625, 0.1875);
let s = Shapes::or(s, collision::box_shape(0.8125, 0., 0., 1., 0.5625, 0.1875));
let s = Shapes::or(s, collision::box_shape(0., 0.1875, 0.1875, 1., 0.5625, 1.));
@@ -26,7 +28,7 @@ static SHAPE2: Lazy = Lazy::new(|| {
collision::box_shape(0.1875, 0.1875, 0., 0.8125, 0.5625, 0.1875),
)
});
-static SHAPE3: Lazy = Lazy::new(|| {
+static SHAPE4: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.8125, 0.1875, 0.5625, 1.);
let s = Shapes::or(s, collision::box_shape(0.8125, 0., 0.8125, 1., 0.5625, 1.));
let s = Shapes::or(s, collision::box_shape(0., 0.1875, 0., 1., 0.5625, 0.8125));
@@ -35,7 +37,7 @@ static SHAPE3: Lazy = Lazy::new(|| {
collision::box_shape(0.1875, 0.1875, 0.8125, 0.8125, 0.5625, 1.),
)
});
-static SHAPE4: Lazy = Lazy::new(|| {
+static SHAPE5: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 0.1875, 0.5625, 0.1875);
let s = Shapes::or(s, collision::box_shape(0., 0., 0.8125, 0.1875, 0.5625, 1.));
let s = Shapes::or(
@@ -51,7 +53,7 @@ static SHAPE4: Lazy = Lazy::new(|| {
collision::box_shape(0.1875, 0.1875, 0.8125, 1., 0.5625, 1.),
)
});
-static SHAPE5: Lazy = Lazy::new(|| {
+static SHAPE6: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.8125, 0., 0., 1., 0.5625, 0.1875);
let s = Shapes::or(s, collision::box_shape(0.8125, 0., 0.8125, 1., 0.5625, 1.));
let s = Shapes::or(s, collision::box_shape(0., 0.1875, 0., 0.8125, 0.5625, 1.));
@@ -60,363 +62,385 @@ static SHAPE5: Lazy = Lazy::new(|| {
collision::box_shape(0.8125, 0.1875, 0.1875, 1., 0.5625, 0.8125),
)
});
-static SHAPE6: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0.25, 1., 1., 1.));
-static SHAPE7: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 0.75, 1., 1.));
-static SHAPE8: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 1., 0.75));
-static SHAPE9: Lazy = Lazy::new(|| collision::box_shape(0.25, 0., 0., 1., 1., 1.));
-static SHAPE10: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.75, 1.));
-static SHAPE11: Lazy = Lazy::new(|| collision::box_shape(0., 0.25, 0., 1., 1., 1.));
-static SHAPE12: Lazy = Lazy::new(|| {
+static SHAPE7: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.125, 1.));
+static SHAPE8: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.5, 1.));
+static SHAPE9: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0.25, 1., 1., 1.));
+static SHAPE10: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 0.75, 1., 1.));
+static SHAPE11: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 1., 0.75));
+static SHAPE12: Lazy = Lazy::new(|| collision::box_shape(0.25, 0., 0., 1., 1., 1.));
+static SHAPE13: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.75, 1.));
+static SHAPE14: Lazy = Lazy::new(|| collision::box_shape(0., 0.25, 0., 1., 1., 1.));
+static SHAPE15: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 1., 0.25);
Shapes::or(
s,
collision::box_shape(0.375, 0.375, 0.25, 0.625, 0.625, 1.),
)
});
-static SHAPE13: Lazy = Lazy::new(|| {
+static SHAPE16: Lazy =
+ Lazy::new(|| collision::box_shape(0.375, 0.375, 0., 0.625, 0.625, 1.));
+static SHAPE17: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 1., 0.25);
Shapes::or(
s,
collision::box_shape(0.375, 0.375, 0.25, 0.625, 0.625, 1.25),
)
});
-static SHAPE14: Lazy = Lazy::new(|| {
+static SHAPE18: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.75, 0., 0., 1., 1., 1.);
Shapes::or(
s,
collision::box_shape(0., 0.375, 0.375, 0.75, 0.625, 0.625),
)
});
-static SHAPE15: Lazy = Lazy::new(|| {
+static SHAPE19: Lazy =
+ Lazy::new(|| collision::box_shape(0., 0.375, 0.375, 1., 0.625, 0.625));
+static SHAPE20: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.75, 0., 0., 1., 1., 1.);
Shapes::or(
s,
collision::box_shape(-0.25, 0.375, 0.375, 0.75, 0.625, 0.625),
)
});
-static SHAPE16: Lazy = Lazy::new(|| {
+static SHAPE21: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.75, 1., 1., 1.);
Shapes::or(
s,
collision::box_shape(0.375, 0.375, 0., 0.625, 0.625, 0.75),
)
});
-static SHAPE17: Lazy = Lazy::new(|| {
+static SHAPE22: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.75, 1., 1., 1.);
Shapes::or(
s,
collision::box_shape(0.375, 0.375, -0.25, 0.625, 0.625, 0.75),
)
});
-static SHAPE18: Lazy = Lazy::new(|| {
+static SHAPE23: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 0.25, 1., 1.);
Shapes::or(
s,
collision::box_shape(0.25, 0.375, 0.375, 1., 0.625, 0.625),
)
});
-static SHAPE19: Lazy = Lazy::new(|| {
+static SHAPE24: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 0.25, 1., 1.);
Shapes::or(
s,
collision::box_shape(0.25, 0.375, 0.375, 1.25, 0.625, 0.625),
)
});
-static SHAPE20: Lazy = Lazy::new(|| {
+static SHAPE25: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.375, 0., 0.375, 0.625, 1., 0.625);
let s = Shapes::or(s, collision::box_shape(0., 0.75, 0., 0.375, 1., 1.));
let s = Shapes::or(s, collision::box_shape(0.375, 0.75, 0., 1., 1., 0.375));
let s = Shapes::or(s, collision::box_shape(0.375, 0.75, 0.625, 1., 1., 1.));
Shapes::or(s, collision::box_shape(0.625, 0.75, 0.375, 1., 1., 0.625))
});
-static SHAPE21: Lazy = Lazy::new(|| {
+static SHAPE26: Lazy =
+ Lazy::new(|| collision::box_shape(0.375, 0., 0.375, 0.625, 1., 0.625));
+static SHAPE27: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.375, -0.25, 0.375, 0.625, 1., 0.625);
let s = Shapes::or(s, collision::box_shape(0., 0.75, 0., 0.375, 1., 1.));
let s = Shapes::or(s, collision::box_shape(0.375, 0.75, 0., 1., 1., 0.375));
let s = Shapes::or(s, collision::box_shape(0.375, 0.75, 0.625, 1., 1., 1.));
Shapes::or(s, collision::box_shape(0.625, 0.75, 0.375, 1., 1., 0.625))
});
-static SHAPE22: Lazy = Lazy::new(|| {
+static SHAPE28: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.25, 1.);
Shapes::or(
s,
collision::box_shape(0.375, 0.25, 0.375, 0.625, 1., 0.625),
)
});
-static SHAPE23: Lazy = Lazy::new(|| {
+static SHAPE29: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.25, 1.));
+static SHAPE30: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.25, 1.);
Shapes::or(
s,
collision::box_shape(0.375, 0.25, 0.375, 0.625, 1.25, 0.625),
)
});
-static SHAPE24: Lazy = Lazy::new(|| {
+static SHAPE31: Lazy =
+ Lazy::new(|| collision::box_shape(0.3125, 0., 0.3125, 0.6875, 0.375, 0.6875));
+static SHAPE32: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.0625, 1.));
+static SHAPE33: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 1., 0.5);
Shapes::or(s, collision::box_shape(0., 0.5, 0.5, 1., 1., 1.))
});
-static SHAPE25: Lazy = Lazy::new(|| {
+static SHAPE34: Lazy = Lazy::new(|| collision::box_shape(0., 0.5, 0., 1., 1., 1.));
+static SHAPE35: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 0.5, 1., 1.);
let s = Shapes::or(s, collision::box_shape(0.5, 0., 0., 1., 1., 0.5));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0.5, 1., 1., 1.))
});
-static SHAPE26: Lazy = Lazy::new(|| {
+static SHAPE36: Lazy = Lazy::new(|| {
+ let s = collision::box_shape(0., 0., 0., 0.5, 1., 1.);
+ Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 1.))
+});
+static SHAPE37: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 1., 0.5);
let s = Shapes::or(s, collision::box_shape(0.5, 0., 0.5, 1., 1., 1.));
Shapes::or(s, collision::box_shape(0., 0.5, 0.5, 0.5, 1., 1.))
});
-static SHAPE27: Lazy = Lazy::new(|| {
+static SHAPE38: Lazy = Lazy::new(|| {
+ let s = collision::box_shape(0.5, 0., 0., 1., 1., 1.);
+ Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 1.))
+});
+static SHAPE39: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 0.5, 1., 0.5);
let s = Shapes::or(s, collision::box_shape(0., 0.5, 0.5, 1., 1., 1.));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 0.5))
});
-static SHAPE28: Lazy = Lazy::new(|| {
+static SHAPE40: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.5, 0., 0., 1., 1., 0.5);
let s = Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 1.));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0.5, 1., 1., 1.))
});
-static SHAPE29: Lazy = Lazy::new(|| {
+static SHAPE41: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
Shapes::or(s, collision::box_shape(0., 0.5, 0., 1., 1., 0.5))
});
-static SHAPE30: Lazy = Lazy::new(|| {
+static SHAPE42: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
let s = Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 1.));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 0.5))
});
-static SHAPE31: Lazy = Lazy::new(|| {
+static SHAPE43: Lazy = Lazy::new(|| {
+ let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
+ Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 1.))
+});
+static SHAPE44: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
let s = Shapes::or(s, collision::box_shape(0., 0.5, 0., 1., 1., 0.5));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0.5, 1., 1., 1.))
});
-static SHAPE32: Lazy = Lazy::new(|| {
+static SHAPE45: Lazy = Lazy::new(|| {
+ let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
+ Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 1.))
+});
+static SHAPE46: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 0.5))
});
-static SHAPE33: Lazy = Lazy::new(|| {
+static SHAPE47: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 0.5))
});
-static SHAPE34: Lazy = Lazy::new(|| {
+static SHAPE48: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.5, 1., 1., 1.);
Shapes::or(s, collision::box_shape(0., 0.5, 0., 1., 1., 0.5))
});
-static SHAPE35: Lazy = Lazy::new(|| {
+static SHAPE49: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.5, 1., 1., 1.);
let s = Shapes::or(s, collision::box_shape(0.5, 0., 0., 1., 1., 0.5));
Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 0.5))
});
-static SHAPE36: Lazy = Lazy::new(|| {
+static SHAPE50: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 0.5, 1., 1.);
let s = Shapes::or(s, collision::box_shape(0.5, 0., 0.5, 1., 1., 1.));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 0.5))
});
-static SHAPE37: Lazy = Lazy::new(|| {
+static SHAPE51: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.5, 0., 0.5, 1., 1., 1.);
let s = Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 1.));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 0.5))
});
-static SHAPE38: Lazy = Lazy::new(|| {
+static SHAPE52: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.5, 0.5, 1., 1.);
let s = Shapes::or(s, collision::box_shape(0., 0.5, 0., 1., 1., 0.5));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0.5, 1., 1., 1.))
});
-static SHAPE39: Lazy = Lazy::new(|| {
+static SHAPE53: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
Shapes::or(s, collision::box_shape(0., 0.5, 0.5, 1., 1., 1.))
});
-static SHAPE40: Lazy = Lazy::new(|| {
+static SHAPE54: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
let s = Shapes::or(s, collision::box_shape(0., 0.5, 0.5, 1., 1., 1.));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 0.5))
});
-static SHAPE41: Lazy = Lazy::new(|| {
+static SHAPE55: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
let s = Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 1.));
Shapes::or(s, collision::box_shape(0.5, 0.5, 0.5, 1., 1., 1.))
});
-static SHAPE42: Lazy = Lazy::new(|| {
+static SHAPE56: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
Shapes::or(s, collision::box_shape(0.5, 0.5, 0.5, 1., 1., 1.))
});
-static SHAPE43: Lazy = Lazy::new(|| {
+static SHAPE57: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
Shapes::or(s, collision::box_shape(0., 0.5, 0.5, 0.5, 1., 1.))
});
-static SHAPE44: Lazy = Lazy::new(|| {
- let s = collision::box_shape(0., 0., 0., 0.5, 1., 1.);
- Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 1.))
-});
-static SHAPE45: Lazy = Lazy::new(|| {
- let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
- Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 1.))
-});
-static SHAPE46: Lazy = Lazy::new(|| {
- let s = collision::box_shape(0.5, 0., 0., 1., 1., 1.);
- Shapes::or(s, collision::box_shape(0., 0.5, 0., 0.5, 1., 1.))
-});
-static SHAPE47: Lazy = Lazy::new(|| {
- let s = collision::box_shape(0., 0., 0., 1., 0.5, 1.);
- Shapes::or(s, collision::box_shape(0.5, 0.5, 0., 1., 1., 1.))
-});
-static SHAPE48: Lazy =
+static SHAPE58: Lazy =
Lazy::new(|| collision::box_shape(0.0625, 0., 0.0625, 0.9375, 0.875, 0.9375));
-static SHAPE49: Lazy =
+static SHAPE59: Lazy =
+ Lazy::new(|| collision::box_shape(0.0625, 0., 0.0625, 0.9375, 1., 0.9375));
+static SHAPE60: Lazy =
Lazy::new(|| collision::box_shape(0.0625, 0., 0.0625, 1., 0.875, 0.9375));
-static SHAPE50: Lazy =
+static SHAPE61: Lazy =
Lazy::new(|| collision::box_shape(0., 0., 0.0625, 0.9375, 0.875, 0.9375));
-static SHAPE51: Lazy =
+static SHAPE62: Lazy =
Lazy::new(|| collision::box_shape(0.0625, 0., 0., 0.9375, 0.875, 0.9375));
-static SHAPE52: Lazy =
+static SHAPE63: Lazy =
Lazy::new(|| collision::box_shape(0.0625, 0., 0.0625, 0.9375, 0.875, 1.));
-static SHAPE53: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.9375, 1.));
-static SHAPE54: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 0.1875, 1., 1.));
-static SHAPE55: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0.8125, 1., 1., 1.));
-static SHAPE56: Lazy = Lazy::new(|| collision::box_shape(0.8125, 0., 0., 1., 1., 1.));
-static SHAPE57: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 1., 0.1875));
-static SHAPE58: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.125, 1.));
-static SHAPE59: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.25, 1.));
-static SHAPE60: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.375, 1.));
-static SHAPE61: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.5, 1.));
-static SHAPE62: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.625, 1.));
-static SHAPE63: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.875, 1.));
-static SHAPE64: Lazy =
+static SHAPE64: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.375, 1.));
+static SHAPE65: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.625, 1.));
+static SHAPE66: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.875, 1.));
+static SHAPE67: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.9375, 1.));
+static SHAPE68: Lazy =
+ Lazy::new(|| collision::box_shape(0.25, 0., 0.25, 0.75, 1., 0.75));
+static SHAPE69: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 0.1875, 1., 1.));
+static SHAPE70: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0.8125, 1., 1., 1.));
+static SHAPE71: Lazy = Lazy::new(|| collision::box_shape(0.8125, 0., 0., 1., 1., 1.));
+static SHAPE72: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 1., 0.1875));
+static SHAPE73: Lazy =
+ Lazy::new(|| collision::box_shape(0.1875, 0., 0.1875, 0.8125, 1., 0.8125));
+static SHAPE74: Lazy =
+ Lazy::new(|| collision::box_shape(0., 0.875, 0.375, 1., 1., 0.625));
+static SHAPE75: Lazy =
+ Lazy::new(|| collision::box_shape(0.375, 0.875, 0., 0.625, 1., 1.));
+static SHAPE76: Lazy =
Lazy::new(|| collision::box_shape(0.0625, 0., 0.0625, 0.9375, 0.9375, 0.9375));
-static SHAPE65: Lazy = Lazy::new(|| {
+static SHAPE77: Lazy =
+ Lazy::new(|| collision::box_shape(0.125, 0., 0.125, 0.875, 1., 0.875));
+static SHAPE78: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.375, 1., 1.5, 0.625);
let s = Shapes::or(s, collision::box_shape(0.375, 0., 0., 0.625, 1.5, 0.375));
Shapes::or(s, collision::box_shape(0.375, 0., 0.625, 0.625, 1.5, 1.))
});
-static SHAPE66: Lazy = Lazy::new(|| {
+static SHAPE79: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.375, 0., 0., 0.625, 1.5, 1.);
Shapes::or(s, collision::box_shape(0.625, 0., 0.375, 1., 1.5, 0.625))
});
-static SHAPE67: Lazy = Lazy::new(|| {
+static SHAPE80: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.375, 1., 1.5, 0.625);
Shapes::or(s, collision::box_shape(0.375, 0., 0., 0.625, 1.5, 0.375))
});
-static SHAPE68: Lazy = Lazy::new(|| {
+static SHAPE81: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.375, 0., 0., 0.625, 1.5, 0.625);
Shapes::or(s, collision::box_shape(0.625, 0., 0.375, 1., 1.5, 0.625))
});
-static SHAPE69: Lazy = Lazy::new(|| {
+static SHAPE82: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.375, 1., 1.5, 0.625);
Shapes::or(s, collision::box_shape(0.375, 0., 0.625, 0.625, 1.5, 1.))
});
-static SHAPE70: Lazy = Lazy::new(|| {
+static SHAPE83: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.375, 0., 0.375, 0.625, 1.5, 1.);
Shapes::or(s, collision::box_shape(0.625, 0., 0.375, 1., 1.5, 0.625))
});
-static SHAPE71: Lazy =
+static SHAPE84: Lazy =
Lazy::new(|| collision::box_shape(0., 0., 0.375, 1., 1.5, 0.625));
-static SHAPE72: Lazy =
+static SHAPE85: Lazy =
Lazy::new(|| collision::box_shape(0.375, 0., 0.375, 1., 1.5, 0.625));
-static SHAPE73: Lazy = Lazy::new(|| {
+static SHAPE86: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.375, 0.625, 1.5, 0.625);
let s = Shapes::or(s, collision::box_shape(0.375, 0., 0., 0.625, 1.5, 0.375));
Shapes::or(s, collision::box_shape(0.375, 0., 0.625, 0.625, 1.5, 1.))
});
-static SHAPE74: Lazy =
+static SHAPE87: Lazy =
Lazy::new(|| collision::box_shape(0.375, 0., 0., 0.625, 1.5, 1.));
-static SHAPE75: Lazy = Lazy::new(|| {
+static SHAPE88: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.375, 0.625, 1.5, 0.625);
Shapes::or(s, collision::box_shape(0.375, 0., 0., 0.625, 1.5, 0.375))
});
-static SHAPE76: Lazy =
+static SHAPE89: Lazy =
Lazy::new(|| collision::box_shape(0.375, 0., 0., 0.625, 1.5, 0.625));
-static SHAPE77: Lazy = Lazy::new(|| {
+static SHAPE90: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.375, 0.625, 1.5, 0.625);
Shapes::or(s, collision::box_shape(0.375, 0., 0.625, 0.625, 1.5, 1.))
});
-static SHAPE78: Lazy =
+static SHAPE91: Lazy =
Lazy::new(|| collision::box_shape(0.375, 0., 0.375, 0.625, 1.5, 1.));
-static SHAPE79: Lazy =
+static SHAPE92: Lazy =
Lazy::new(|| collision::box_shape(0., 0., 0.375, 0.625, 1.5, 0.625));
-static SHAPE80: Lazy =
+static SHAPE93: Lazy =
Lazy::new(|| collision::box_shape(0.375, 0., 0.375, 0.625, 1.5, 0.625));
-static SHAPE81: Lazy =
+static SHAPE94: Lazy =
Lazy::new(|| collision::box_shape(0.0625, 0., 0.0625, 0.9375, 0.5, 0.9375));
-static SHAPE82: Lazy =
+static SHAPE95: Lazy =
Lazy::new(|| collision::box_shape(0.1875, 0., 0.0625, 0.9375, 0.5, 0.9375));
-static SHAPE83: Lazy =
+static SHAPE96: Lazy =
Lazy::new(|| collision::box_shape(0.3125, 0., 0.0625, 0.9375, 0.5, 0.9375));
-static SHAPE84: Lazy =
+static SHAPE97: Lazy =
Lazy::new(|| collision::box_shape(0.4375, 0., 0.0625, 0.9375, 0.5, 0.9375));
-static SHAPE85: Lazy =
+static SHAPE98: Lazy =
Lazy::new(|| collision::box_shape(0.5625, 0., 0.0625, 0.9375, 0.5, 0.9375));
-static SHAPE86: Lazy =
+static SHAPE99: Lazy =
Lazy::new(|| collision::box_shape(0.6875, 0., 0.0625, 0.9375, 0.5, 0.9375));
-static SHAPE87: Lazy =
+static SHAPE100: Lazy =
Lazy::new(|| collision::box_shape(0.8125, 0., 0.0625, 0.9375, 0.5, 0.9375));
-static SHAPE88: Lazy = Lazy::new(|| collision::box_shape(0., 0.8125, 0., 1., 1., 1.));
-static SHAPE89: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.1875, 1.));
-static SHAPE90: Lazy = Lazy::new(|| {
+static SHAPE101: Lazy = Lazy::new(|| collision::box_shape(0., 0.8125, 0., 1., 1., 1.));
+static SHAPE102: Lazy = Lazy::new(|| collision::box_shape(0., 0., 0., 1., 0.1875, 1.));
+static SHAPE103: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.4375, 1., 1., 0.5625);
let s = Shapes::or(s, collision::box_shape(0.4375, 0., 0., 0.5625, 1., 0.4375));
Shapes::or(s, collision::box_shape(0.4375, 0., 0.5625, 0.5625, 1., 1.))
});
-static SHAPE91: Lazy = Lazy::new(|| {
+static SHAPE104: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.4375, 0., 0., 0.5625, 1., 1.);
Shapes::or(s, collision::box_shape(0.5625, 0., 0.4375, 1., 1., 0.5625))
});
-static SHAPE92: Lazy = Lazy::new(|| {
+static SHAPE105: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.4375, 1., 1., 0.5625);
Shapes::or(s, collision::box_shape(0.4375, 0., 0., 0.5625, 1., 0.4375))
});
-static SHAPE93: Lazy = Lazy::new(|| {
+static SHAPE106: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.4375, 0., 0., 0.5625, 1., 0.5625);
Shapes::or(s, collision::box_shape(0.5625, 0., 0.4375, 1., 1., 0.5625))
});
-static SHAPE94: Lazy = Lazy::new(|| {
+static SHAPE107: Lazy = Lazy::new(|| {
let s = collision::box_shape(0., 0., 0.4375, 1., 1., 0.5625);
Shapes::or(s, collision::box_shape(0.4375, 0., 0.5625, 0.5625, 1., 1.))
});
-static SHAPE95: Lazy = Lazy::new(|| {
+static SHAPE108: Lazy = Lazy::new(|| {
let s = collision::box_shape(0.4375, 0., 0.4375, 0.5625, 1., 1.);
Shapes::or(s, collision::box_shape(0.5625, 0., 0.4375, 1., 1., 0.5625))
});
-static SHAPE96: Lazy =
+static SHAPE109: Lazy =
Lazy::new(|| collision::box_shape(0., 0., 0.4375, 1., 1., 0.5625));
-static SHAPE97: Lazy