diff --git a/Cargo.lock b/Cargo.lock index 627198f18..5b0c3fb4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -411,19 +411,6 @@ dependencies = [ "rand_core 0.10.1", ] -[[package]] -name = "chrono" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-link", -] - [[package]] name = "ciborium" version = "0.2.2" @@ -463,9 +450,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", ] @@ -2840,7 +2827,6 @@ dependencies = [ "base64 0.22.1", "bitflags 2.11.1", "bytes", - "chrono", "console-subscriber", "crossbeam", "flate2", @@ -4326,9 +4312,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", @@ -4894,9 +4880,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] diff --git a/Cargo.toml b/Cargo.toml index f74c54fd6..8a4c8dc40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,6 @@ bytes = "1.11" futures = { version = "0.3", default-features = false, features = ["executor"] } rayon = "1.12" crossbeam = "0.8" -chrono = "0.4" uuid = { version = "1.23", features = ["serde", "v3", "v4"] } serde = { version = "1.0", features = ["derive"] } diff --git a/pumpkin-codegen/Cargo.lock b/pumpkin-codegen/Cargo.lock index 7fe976440..00096bde7 100644 --- a/pumpkin-codegen/Cargo.lock +++ b/pumpkin-codegen/Cargo.lock @@ -906,9 +906,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.51.0" +version = "1.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" +checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776" dependencies = [ "pin-project-lite", ] diff --git a/pumpkin-protocol/Cargo.toml b/pumpkin-protocol/Cargo.toml index 131ed6822..10a7b6f21 100644 --- a/pumpkin-protocol/Cargo.toml +++ b/pumpkin-protocol/Cargo.toml @@ -21,7 +21,7 @@ pumpkin-util.workspace = true uuid.workspace = true serde.workspace = true thiserror.workspace = true -tokio.workspace = true +tokio = { workspace = true, features = ["net"] } bytes.workspace = true # encryption diff --git a/pumpkin-protocol/fuzz/Cargo.lock b/pumpkin-protocol/fuzz/Cargo.lock index 511911487..45d3c7294 100644 --- a/pumpkin-protocol/fuzz/Cargo.lock +++ b/pumpkin-protocol/fuzz/Cargo.lock @@ -10,13 +10,13 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +checksum = "66bd29a732b644c0431c6140f370d097879203d79b80c94a6747ba0872adaef8" dependencies = [ - "cfg-if", "cipher", - "cpufeatures 0.2.17", + "cpubits", + "cpufeatures 0.3.0", ] [[package]] @@ -69,9 +69,9 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "block-buffer" @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ "hybrid-array", ] @@ -105,9 +105,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cc" -version = "1.2.56" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "jobserver", @@ -123,9 +123,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfb8" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "014c0a0e1ad0dae6a86c082db2f9bd7fe8c2c734227047d0d8b4d4a3a094a1e1" +checksum = "c22e6368a74b7dd7039e10da9f0300ab4520584f2960048a5a4a4e51f8e4e183" dependencies = [ "cipher", ] @@ -144,16 +144,16 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] name = "cipher" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" dependencies = [ - "crypto-common 0.1.7", + "crypto-common 0.2.1", "inout", ] @@ -163,7 +163,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -194,6 +194,12 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" +[[package]] +name = "cpubits" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef0c543070d296ea414df2dd7625d1b24866ce206709d8a4a424f28377f5861" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -313,9 +319,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", @@ -323,9 +329,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "211f05e03c7d03754740fd9e585de910a095d6b99f8bcfffdef8319fa02a8331" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" dependencies = [ "hybrid-array", ] @@ -363,19 +369,19 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid 0.9.6", - "crypto-common 0.1.7", + "crypto-common 0.1.6", "subtle", ] [[package]] name = "digest" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bf3682cdec91817be507e4aa104314898b95b84d74f3d43882210101a545b6" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" dependencies = [ - "block-buffer 0.11.0", + "block-buffer 0.12.0", "const-oid 0.10.2", - "crypto-common 0.2.0", + "crypto-common 0.2.1", ] [[package]] @@ -444,14 +450,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "ff" @@ -575,9 +581,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -603,20 +609,20 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", - "rand_core 0.10.0", + "r-efi 6.0.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -649,9 +655,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" @@ -685,9 +691,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.7" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" dependencies = [ "typenum", ] @@ -700,23 +706,23 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] [[package]] name = "inout" -version = "0.1.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -730,9 +736,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jobserver" @@ -746,9 +752,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.88" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e709f3e3d22866f9c25b3aff01af289b18422cc8b4262fb19103ee80fe513d" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ "once_cell", "wasm-bindgen", @@ -762,9 +768,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.182" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libfuzzer-sys" @@ -803,9 +809,9 @@ dependencies = [ [[package]] name = "lz4_flex" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +checksum = "373f5eceeeab7925e0c1098212f2fbc4d416adec9d35051a6ab251e824c1854a" [[package]] name = "md-5" @@ -841,13 +847,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -882,9 +888,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "p384" @@ -975,9 +981,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkcs8" @@ -1105,6 +1111,7 @@ dependencies = [ "bytes", "cfb8", "flate2", + "hybrid-array", "pumpkin-data", "pumpkin-macros", "pumpkin-nbt", @@ -1171,6 +1178,7 @@ dependencies = [ "pumpkin-nbt", "pumpkin-util", "rand", + "rayon", "rustc-hash", "ruzstd", "serde", @@ -1185,9 +1193,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -1199,14 +1207,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "rand" -version = "0.10.0" +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20", - "getrandom 0.4.1", - "rand_core 0.10.0", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -1220,9 +1234,29 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] [[package]] name = "redox_syscall" @@ -1286,9 +1320,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -1361,7 +1395,7 @@ checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "digest 0.11.0", + "digest 0.11.2", ] [[package]] @@ -1392,9 +1426,9 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "siphasher" @@ -1425,12 +1459,12 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys", ] [[package]] @@ -1500,9 +1534,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.50.0" +version = "1.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776" dependencies = [ "bytes", "libc", @@ -1512,14 +1546,14 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -1542,9 +1576,9 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "994b95d9e7bae62b34bab0e2a4510b801fa466066a6a8b2b57361fa1eba068ee" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "indexmap", "serde_core", @@ -1566,9 +1600,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ca317ebc49f06bd748bfba29533eac9485569dc9bf80b849024b025e814fb9" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow", ] @@ -1646,11 +1680,11 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "js-sys", "md-5", "serde_core", @@ -1689,9 +1723,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.111" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1adf1535672f5b7824f817792b1afd731d7e843d2d04ec8f27e8cb51edd8ac" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -1702,9 +1736,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.111" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e638317c08b21663aed4d2b9a2091450548954695ff4efa75bff5fa546b3b1" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1712,9 +1746,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.111" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c64760850114d03d5f65457e96fc988f11f01d38fbaa51b254e4ab5809102af" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -1725,9 +1759,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.111" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60eecd4fe26177cfa3339eb00b4a36445889ba3ad37080c2429879718e20ca41" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] @@ -1772,15 +1806,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -1790,71 +1815,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "1.0.1" diff --git a/pumpkin-protocol/fuzz/Cargo.toml b/pumpkin-protocol/fuzz/Cargo.toml index 1ba419192..69481c98c 100644 --- a/pumpkin-protocol/fuzz/Cargo.toml +++ b/pumpkin-protocol/fuzz/Cargo.toml @@ -35,3 +35,17 @@ path = "fuzz_targets/decoder_bedrock.rs" test = false doc = false bench = false + +[[bin]] +name = "encoder_java" +path = "fuzz_targets/encoder_java.rs" +test = false +doc = false +bench = false + +[[bin]] +name = "encoder_bedrock" +path = "fuzz_targets/encoder_bedrock.rs" +test = false +doc = false +bench = false diff --git a/pumpkin-protocol/fuzz/fuzz_targets/encoder_bedrock.rs b/pumpkin-protocol/fuzz/fuzz_targets/encoder_bedrock.rs new file mode 100644 index 000000000..6a3bb527f --- /dev/null +++ b/pumpkin-protocol/fuzz/fuzz_targets/encoder_bedrock.rs @@ -0,0 +1,43 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; +use pumpkin_protocol::bedrock::packet_encoder::UDPNetworkEncoder; +use pumpkin_protocol::bedrock::SubClient; + +fuzz_target!(|data: &[u8]| { + if data.len() < 10 { + return; + } + + let compression_threshold = data[0] as usize; + let compression_level = (data[1] % 10) as u32; + let packet_id = u16::from_be_bytes([data[2], data[3]]); + let sender = match data[4] % 4 { + 0 => SubClient::Main, + 1 => SubClient::SubClient0, + 2 => SubClient::SubClient1, + _ => SubClient::SubClietn2, + }; + let target = match data[5] % 4 { + 0 => SubClient::Main, + 1 => SubClient::SubClient0, + 2 => SubClient::SubClient1, + _ => SubClient::SubClietn2, + }; + let use_compression = data[6] % 2 == 0; + let packet_payload = &data[7..]; + + let mut encoder = UDPNetworkEncoder::new(); + + if use_compression { + encoder.set_compression((compression_threshold, compression_level)); + } + + let mut out = Vec::new(); + let _ = encoder.write_game_packet( + packet_id, + sender, + target, + packet_payload, + &mut out + ); +}); diff --git a/pumpkin-protocol/fuzz/fuzz_targets/encoder_java.rs b/pumpkin-protocol/fuzz/fuzz_targets/encoder_java.rs new file mode 100644 index 000000000..a300bd165 --- /dev/null +++ b/pumpkin-protocol/fuzz/fuzz_targets/encoder_java.rs @@ -0,0 +1,59 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; +use pumpkin_protocol::java::packet_encoder::TCPNetworkEncoder; +use pumpkin_protocol::codec::var_int::VarInt; +use pumpkin_protocol::ser::NetworkWriteExt; +use pumpkin_protocol::ServerPacket; +use pumpkin_protocol::java::client::play::CPlayerPosition; +use pumpkin_protocol::packet::MultiVersionJavaPacket; +use pumpkin_protocol::ClientPacket; +use pumpkin_util::version::MinecraftVersion; +use std::io::Cursor; +use tokio::runtime::Runtime; + +const TARGET_VERSION: MinecraftVersion = MinecraftVersion::V_1_21_4; + +fuzz_target!(|data: &[u8]| { + if data.len() < 20 { + return; + } + + let compression_threshold = data[0] as usize; + let compression_level = (data[1] % 10) as u32; + let encryption_key: [u8; 16] = data[2..18].try_into().unwrap(); + let use_compression = data[18] % 2 == 0; + let use_encryption = data[19] % 2 == 0; + let packet_data = &data[20..]; + + let rt = Runtime::new().unwrap(); + rt.block_on(async { + let mut out = Vec::new(); + let mut encoder = TCPNetworkEncoder::new(&mut out); + + if use_compression { + encoder.set_compression((compression_threshold, compression_level)); + } + if use_encryption { + encoder.set_encryption(&encryption_key); + } + + // 1. Fuzz with raw bytes (simulating various packet payloads) + let mut buf = Vec::new(); + let packet_id = if packet_data.is_empty() { 0 } else { packet_data[0] as i32 }; + let _ = buf.write_var_int(&VarInt(packet_id)); + buf.extend_from_slice(packet_data); + let _ = encoder.write_packet(buf.into()).await; + + // 2. Fuzz with actual packets if they can be partially read + let mut cursor = Cursor::new(packet_data); + if let Ok(packet) = CPlayerPosition::read(&mut cursor, &TARGET_VERSION) { + let mut packet_buf = Vec::new(); + let id = CPlayerPosition::to_id(TARGET_VERSION); + let _ = packet_buf.write_var_int(&VarInt(id)); + let _ = packet.write_packet_data(&mut packet_buf, &TARGET_VERSION); + let _ = encoder.write_packet(packet_buf.into()).await; + } + + let _ = encoder.flush().await; + }); +}); diff --git a/pumpkin-protocol/src/java/packet_decoder.rs b/pumpkin-protocol/src/java/packet_decoder.rs index 3b6a27f4d..3141f8a88 100644 --- a/pumpkin-protocol/src/java/packet_decoder.rs +++ b/pumpkin-protocol/src/java/packet_decoder.rs @@ -157,7 +157,9 @@ impl TCPNetworkDecoder { let payload_len_hint = expected_packet_data_len.saturating_sub(packet_id_len); self.payload_scratch.clear(); self.payload_scratch.reserve(payload_len_hint); - loop { + + let mut total_read = 0; + while total_read < payload_len_hint { let bytes_read = reader .read_buf(&mut self.payload_scratch) .await @@ -165,6 +167,7 @@ impl TCPNetworkDecoder { if bytes_read == 0 { break; } + total_read += bytes_read; } if let Some(expected_uncompressed_packet_data_len) = expected_uncompressed_packet_data_len { diff --git a/pumpkin-world/src/block/entities/daylight_detector.rs b/pumpkin-world/src/block/entities/daylight_detector.rs index c710d2bc6..d93689b52 100644 --- a/pumpkin-world/src/block/entities/daylight_detector.rs +++ b/pumpkin-world/src/block/entities/daylight_detector.rs @@ -103,8 +103,7 @@ impl DaylightDetectorBlockEntity { let sky_light_level = level .light_engine .get_sky_light_level(level, block_pos) - .await - .unwrap(); + .await; let mut power = sky_light_level - ambient_darkness; diff --git a/pumpkin-world/src/chunk/format/anvil.rs b/pumpkin-world/src/chunk/format/anvil.rs index 71f5e6c64..c45827c1f 100644 --- a/pumpkin-world/src/chunk/format/anvil.rs +++ b/pumpkin-world/src/chunk/format/anvil.rs @@ -38,8 +38,8 @@ pub const CHUNK_COUNT: usize = REGION_SIZE * REGION_SIZE; /// The number of bytes in a sector (4 KiB) const SECTOR_BYTES: usize = 4096; -// 26.1 -pub const WORLD_DATA_VERSION: i32 = 4786; +// 26.1.2 +pub const WORLD_DATA_VERSION: i32 = 4790; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] diff --git a/pumpkin-world/src/lighting/runtime.rs b/pumpkin-world/src/lighting/runtime.rs index 10aeba9c4..c8b6cc416 100644 --- a/pumpkin-world/src/lighting/runtime.rs +++ b/pumpkin-world/src/lighting/runtime.rs @@ -136,14 +136,14 @@ impl DynamicLightEngine { let new_light = light_level.saturating_sub(opacity); // Only propagate if new light is brighter than current light - if new_light > neighbor_light { - self.set_block_light_level(level, &neighbor_pos, new_light) + if new_light > neighbor_light + && self + .set_block_light_level(level, &neighbor_pos, new_light) .await - .unwrap(); - - if new_light > 1 { - self.queue_block_light_increase(neighbor_pos, new_light); - } + .is_ok() + && new_light > 1 + { + self.queue_block_light_increase(neighbor_pos, new_light); } } } @@ -301,29 +301,27 @@ impl DynamicLightEngine { for dir in BlockDirection::all() { let neighbor_pos = pos.offset(dir.to_offset()); - if let Some(neighbor_light) = self.get_sky_light_level(level, &neighbor_pos).await { - let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state(); - let opacity = neighbor_state.opacity; + let neighbor_light = self.get_sky_light_level(level, &neighbor_pos).await; + let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state(); + let opacity = neighbor_state.opacity; - // Calculate new light level for neighbor - let new_light = if light_level == 15 && dir == BlockDirection::Down && opacity == 0 - { - // Special case: Sky light at 15 propagates down as 15 through transparent blocks - 15 - } else { - // Normal propagation: reduce by 1 for distance, then by opacity - light_level.saturating_sub(1).saturating_sub(opacity) - }; + // Calculate new light level for neighbor + let new_light = if light_level == 15 && dir == BlockDirection::Down && opacity == 0 { + // Special case: Sky light at 15 propagates down as 15 through transparent blocks + 15 + } else { + // Normal propagation: reduce by 1 for distance, then by opacity + light_level.saturating_sub(1).saturating_sub(opacity) + }; - // Only propagate if new light is brighter than current light - if new_light > neighbor_light { - self.set_sky_light_level(level, &neighbor_pos, new_light) - .await - .unwrap(); + // Only propagate if new light is brighter than current light + if new_light > neighbor_light { + self.set_sky_light_level(level, &neighbor_pos, new_light) + .await + .unwrap(); - if new_light > 0 { - self.queue_sky_light_increase(neighbor_pos, new_light); - } + if new_light > 0 { + self.queue_sky_light_increase(neighbor_pos, new_light); } } } @@ -338,33 +336,31 @@ impl DynamicLightEngine { for dir in BlockDirection::all() { let neighbor_pos = pos.offset(dir.to_offset()); - if let Some(neighbor_light) = self.get_sky_light_level(level, &neighbor_pos).await { - if neighbor_light == 0 { - continue; // Already dark - } + let neighbor_light = self.get_sky_light_level(level, &neighbor_pos).await; + if neighbor_light == 0 { + continue; // Already dark + } - let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state(); - let opacity = neighbor_state.opacity; + let neighbor_state = level.get_block_state(&neighbor_pos).await.to_state(); + let opacity = neighbor_state.opacity; - // Calculate what we would have given this neighbor - let expected = if removed_light == 15 && dir == BlockDirection::Down && opacity == 0 - { - 15 - } else { - removed_light.saturating_sub(1).saturating_sub(opacity) - }; + // Calculate what we would have given this neighbor + let expected = if removed_light == 15 && dir == BlockDirection::Down && opacity == 0 { + 15 + } else { + removed_light.saturating_sub(1).saturating_sub(opacity) + }; - if neighbor_light == expected || neighbor_light < removed_light { - // This neighbor was lit by us, darken it - self.set_sky_light_level(level, &neighbor_pos, 0) - .await - .unwrap(); - self.queue_sky_light_decrease(neighbor_pos, neighbor_light); - } else if neighbor_light > removed_light { - // Neighbor has brighter light from another source - // Re-propagate from it to fill in the gap we left - self.queue_sky_light_increase(neighbor_pos, neighbor_light); - } + if neighbor_light == expected || neighbor_light < removed_light { + // This neighbor was lit by us, darken it + self.set_sky_light_level(level, &neighbor_pos, 0) + .await + .unwrap(); + self.queue_sky_light_decrease(neighbor_pos, neighbor_light); + } else if neighbor_light > removed_light { + // Neighbor has brighter light from another source + // Re-propagate from it to fill in the gap we left + self.queue_sky_light_increase(neighbor_pos, neighbor_light); } } } @@ -382,7 +378,7 @@ impl DynamicLightEngine { LightingEngineConfig::Default => {} } - let current_light = self.get_sky_light_level(level, &pos).await.unwrap_or(0); + let current_light = self.get_sky_light_level(level, &pos).await; let block_state = level.get_block_state(&pos).await.to_state(); let opacity = block_state.opacity; @@ -404,20 +400,17 @@ impl DynamicLightEngine { for dir in BlockDirection::all() { let neighbor_pos = pos.offset(dir.to_offset()); - if let Some(neighbor_light) = - self.get_sky_light_level(level, &neighbor_pos).await - { - // Calculate potential light from this neighbor - let potential = if neighbor_light == 15 && dir == BlockDirection::Up { - // Sky light at 15 from above stays 15 - 15 - } else { - // Normal decay - neighbor_light.saturating_sub(1) - }; + let neighbor_light = self.get_sky_light_level(level, &neighbor_pos).await; + // Calculate potential light from this neighbor + let potential = if neighbor_light == 15 && dir == BlockDirection::Up { + // Sky light at 15 from above stays 15 + 15 + } else { + // Normal decay + neighbor_light.saturating_sub(1) + }; - best_light = best_light.max(potential); - } + best_light = best_light.max(potential); } // Apply opacity to the best incoming light @@ -459,20 +452,22 @@ impl DynamicLightEngine { level: &Arc, position: &BlockPos, ) -> Option { - let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); - let chunk = level.get_chunk(chunk_coordinate).await; + let (chunk_pos, relative) = position.chunk_and_chunk_relative_position(); - let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE; - // Bounds check for section index (lock the light engine) - let light_engine = chunk.light_engine.lock().unwrap(); - if section_index >= light_engine.block_light.len() { - return None; - } - Some(light_engine.block_light[section_index].get( - relative.x as usize, - (relative.y - chunk.section.min_y) as usize % BlockPalette::SIZE, - relative.z as usize, - )) + let chunk = level.get_chunk(chunk_pos).await; + + let section_idx = (relative.y - chunk.section.min_y) as usize / 16; + let light_engine = chunk.light_engine.lock().ok()?; + + light_engine + .block_light + .get(section_idx)? + .get( + relative.x as usize, + (relative.y - chunk.section.min_y) as usize % 16, + relative.z as usize, + ) + .into() } pub async fn set_block_light_level( @@ -503,20 +498,22 @@ impl DynamicLightEngine { Ok(()) } - pub async fn get_sky_light_level(&self, level: &Arc, position: &BlockPos) -> Option { + pub async fn get_sky_light_level(&self, level: &Arc, position: &BlockPos) -> u8 { let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position(); let chunk = level.get_chunk(chunk_coordinate).await; let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE; - // Bounds check for section index (lock the light engine) + let light_engine = chunk.light_engine.lock().unwrap(); + // Bounds check for section index (lock the light engine) if section_index >= light_engine.sky_light.len() { - return None; + return 15; } - Some(light_engine.sky_light[section_index].get( + + light_engine.sky_light[section_index].get( relative.x as usize, (relative.y - chunk.section.min_y) as usize % BlockPalette::SIZE, relative.z as usize, - )) + ) } pub async fn set_sky_light_level( diff --git a/pumpkin-world/src/tick/mod.rs b/pumpkin-world/src/tick/mod.rs index 3d31b82c5..8b545ca63 100644 --- a/pumpkin-world/src/tick/mod.rs +++ b/pumpkin-world/src/tick/mod.rs @@ -5,6 +5,7 @@ use pumpkin_util::{ math::position::BlockPos, resource_location::{FromResourceLocation, ResourceLocation, ToResourceLocation}, }; +use serde::de::Error; use serde::{Deserialize, Deserializer, Serialize, Serializer}; pub mod scheduler; @@ -134,23 +135,36 @@ where where D: Deserializer<'de>, { - NbtCompound::deserialize(deserializer).map(|nbt| { - let x = nbt.get_int("x").unwrap(); - let y = nbt.get_int("y").unwrap(); - let z = nbt.get_int("z").unwrap(); - let delay = nbt.get_int("t").unwrap() as u8; - let priority = TickPriority::try_from(nbt.get_int("p").unwrap()).unwrap(); - let value = T::from_resource_location( - &ResourceLocation::from_str(nbt.get_string("i").unwrap()).unwrap(), - ) - .unwrap(); + let nbt = NbtCompound::deserialize(deserializer)?; - Self { - delay, - priority, - position: BlockPos::new(x, y, z), - value, - } + let get_int = |key| nbt.get_int(key).ok_or_else(|| D::Error::missing_field(key)); + let get_str = |key| { + nbt.get_string(key) + .ok_or_else(|| D::Error::missing_field(key)) + }; + + let x = get_int("x")?; + let y = get_int("y")?; + let z = get_int("z")?; + + let delay = get_int("t")? as u8; + + let priority = TickPriority::try_from(get_int("p")?) + .map_err(|_| D::Error::custom("Invalid tick priority"))?; + + let res_loc_str = get_str("i")?; + let res_loc = ResourceLocation::from_str(res_loc_str).map_err(|e| { + D::Error::custom(format!("Invalid ResourceLocation '{res_loc_str}': {e}")) + })?; + + let value = T::from_resource_location(&res_loc) + .ok_or_else(|| D::Error::custom(format!("Unknown tick type: {res_loc_str}")))?; + + Ok(Self { + delay, + priority, + position: BlockPos::new(x, y, z), + value, }) } } diff --git a/pumpkin-world/src/world_info/mod.rs b/pumpkin-world/src/world_info/mod.rs index 1af3e6378..287a168e5 100644 --- a/pumpkin-world/src/world_info/mod.rs +++ b/pumpkin-world/src/world_info/mod.rs @@ -11,7 +11,7 @@ pub mod anvil; // Constraint: disk biome palette serialization changed in 1.21.5 pub const MINIMUM_SUPPORTED_WORLD_DATA_VERSION: i32 = 4435; // 1.21.9 -pub const MAXIMUM_SUPPORTED_WORLD_DATA_VERSION: i32 = 4786; // 26.1 +pub const MAXIMUM_SUPPORTED_WORLD_DATA_VERSION: i32 = 4790; // 26.1.2 pub const MINIMUM_SUPPORTED_LEVEL_VERSION: i32 = 19132; // 1.21.9 pub const MAXIMUM_SUPPORTED_LEVEL_VERSION: i32 = 19133; // 1.21.9 diff --git a/pumpkin/Cargo.toml b/pumpkin/Cargo.toml index b9ee47026..df41312f0 100644 --- a/pumpkin/Cargo.toml +++ b/pumpkin/Cargo.toml @@ -79,7 +79,6 @@ base64.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -chrono.workspace = true time = { workspace = true, features = ["parsing", "macros", "local-offset"] } # plugins diff --git a/pumpkin/src/command/client_suggestions.rs b/pumpkin/src/command/client_suggestions.rs index 9b66a7e9c..f69d784da 100644 --- a/pumpkin/src/command/client_suggestions.rs +++ b/pumpkin/src/command/client_suggestions.rs @@ -174,7 +174,7 @@ pub async fn send_c_commands_packet( root_node.children = first.into_boxed_slice(); } - let packet = CCommands::new(proto_nodes.into(), root_node_index.try_into().unwrap()); + let packet = CCommands::new(proto_nodes.into(), VarInt(root_node_index as i32)); player.client.enqueue_packet(&packet).await; } @@ -207,15 +207,19 @@ struct ProtoNodeBuilder<'a> { impl<'a> ProtoNodeBuilder<'a> { fn build(self, buffer: &mut Vec>) -> usize { - let mut children = Vec::with_capacity(self.child_nodes.len()); - for node in self.child_nodes { - let i = node.build(buffer); - children.push(i.try_into().unwrap()); - } + let children: Box<[VarInt]> = self + .child_nodes + .into_iter() + .map(|node| { + node.build(buffer) + .try_into() + .expect("Buffer index exceeded i32 bounds") + }) + .collect(); let i = buffer.len(); buffer.push(ProtoNode { - children: children.into(), + children, node_type: self.node_type, }); i diff --git a/pumpkin/src/command/commands/bossbar.rs b/pumpkin/src/command/commands/bossbar.rs index fce4f0cf2..a1f1d4b43 100644 --- a/pumpkin/src/command/commands/bossbar.rs +++ b/pumpkin/src/command/commands/bossbar.rs @@ -17,7 +17,6 @@ use crate::world::custom_bossbar::BossbarUpdateError; use pumpkin_data::translation; use pumpkin_util::text::TextComponent; use pumpkin_util::text::hover::HoverEvent; -use std::fmt::Write as _; use uuid::Uuid; const NAMES: [&str; 1] = ["bossbar"]; @@ -642,12 +641,10 @@ fn handle_bossbar_error(error: BossbarUpdateError) -> CommandError { )) } BossbarUpdateError::NoChanges(value, variation) => { - let mut key = "commands.bossbar.set.".to_string(); - key.push_str(value); - key.push_str(".unchanged"); - if let Some(variation) = variation { - write!(key, ".{variation}").unwrap(); - } + let key = variation.map_or_else( + || format!("commands.bossbar.set.{value}.unchanged"), + |var| format!("commands.bossbar.set.{value}.unchanged.{var}"), + ); CommandError::CommandFailed(TextComponent::translate(key, [])) } diff --git a/pumpkin/src/command/commands/experience.rs b/pumpkin/src/command/commands/experience.rs index 3a113476a..1b63aff97 100644 --- a/pumpkin/src/command/commands/experience.rs +++ b/pumpkin/src/command/commands/experience.rs @@ -41,161 +41,85 @@ enum ExpType { struct Executor { mode: Mode, - exp_type: Option, + exp_type: ExpType, } impl Executor { - async fn handle_query( - &self, - sender: &CommandSender, - target: &Player, - exp_type: ExpType, - ) -> i32 { - match exp_type { - ExpType::Levels => { - let level = target.experience_level.load(Ordering::Relaxed); - sender - .send_message(TextComponent::translate( - "commands.experience.query.levels", - [ - target.get_display_name().await, - TextComponent::text(level.to_string()), - ], - )) - .await; - level - } - ExpType::Points => { - let points = target.experience_points.load(Ordering::Relaxed); - sender - .send_message(TextComponent::translate( - "commands.experience.query.points", - [ - target.get_display_name().await, - TextComponent::text(points.to_string()), - ], - )) - .await; - points - } - } + async fn handle_query(&self, sender: &CommandSender, target: &Player) -> i32 { + let (val, translation_key) = match self.exp_type { + ExpType::Levels => ( + target.experience_level.load(Ordering::Relaxed), + "commands.experience.query.levels", + ), + ExpType::Points => ( + target.experience_points.load(Ordering::Relaxed), + "commands.experience.query.points", + ), + }; + + sender + .send_message(TextComponent::translate( + translation_key, + [ + target.get_display_name().await, + TextComponent::text(val.to_string()), + ], + )) + .await; + + val } fn get_success_message( - mode: Mode, - exp_type: ExpType, + &self, amount: i32, - targets_len: usize, - target_name: Option, + targets: &[Arc], + first_target_name: TextComponent, ) -> TextComponent { - match (mode, exp_type) { - (Mode::Add, ExpType::Points) => { - if targets_len > 1 { - TextComponent::translate( - "commands.experience.add.points.success.multiple", - [ - TextComponent::text(amount.to_string()), - TextComponent::text(targets_len.to_string()), - ], - ) - } else { - TextComponent::translate( - "commands.experience.add.points.success.single", - [ - TextComponent::text(amount.to_string()), - target_name.unwrap(), - ], - ) - } - } - (Mode::Add, ExpType::Levels) => { - if targets_len > 1 { - TextComponent::translate( - "commands.experience.add.levels.success.multiple", - [ - TextComponent::text(amount.to_string()), - TextComponent::text(targets_len.to_string()), - ], - ) - } else { - TextComponent::translate( - "commands.experience.add.levels.success.single", - [ - TextComponent::text(amount.to_string()), - target_name.unwrap(), - ], - ) - } - } - (Mode::Set, ExpType::Points) => { - if targets_len > 1 { - TextComponent::translate( - "commands.experience.set.points.success.multiple", - [ - TextComponent::text(amount.to_string()), - TextComponent::text(targets_len.to_string()), - ], - ) - } else { - TextComponent::translate( - "commands.experience.set.points.success.single", - [ - TextComponent::text(amount.to_string()), - target_name.unwrap(), - ], - ) - } - } - (Mode::Set, ExpType::Levels) => { - if targets_len > 1 { - TextComponent::translate( - "commands.experience.set.levels.success.multiple", - [ - TextComponent::text(amount.to_string()), - TextComponent::text(targets_len.to_string()), - ], - ) - } else { - TextComponent::translate( - "commands.experience.set.levels.success.single", - [ - TextComponent::text(amount.to_string()), - target_name.unwrap(), - ], - ) - } - } - (Mode::Query, _) => unreachable!("Query mode doesn't use success messages"), + let type_str = match self.exp_type { + ExpType::Points => "points", + ExpType::Levels => "levels", + }; + let mode_str = match self.mode { + Mode::Add => "add", + Mode::Set => "set", + Mode::Query => "query", + }; + + if targets.len() > 1 { + TextComponent::translate( + format!("commands.experience.{mode_str}.{type_str}.success.multiple"), + [ + TextComponent::text(amount.to_string()), + TextComponent::text(targets.len().to_string()), + ], + ) + } else { + TextComponent::translate( + format!("commands.experience.{mode_str}.{type_str}.success.single"), + [TextComponent::text(amount.to_string()), first_target_name], + ) } } /// Returns `true` if successful. Otherwise, there was a problem setting the points of a player. - async fn handle_modify( - &self, - target: &Arc, - amount: i32, - exp_type: ExpType, - mode: Mode, - ) -> bool { - match exp_type { + async fn handle_modify(&self, target: &Arc, amount: i32) -> bool { + match self.exp_type { ExpType::Levels => { - if mode == Mode::Add { + if self.mode == Mode::Add { target.add_experience_levels(amount).await; } else { target.set_experience_level(amount, true).await; } } ExpType::Points => { - if mode == Mode::Add { + if self.mode == Mode::Add { target.add_experience_points(amount).await; } else { - let current_level = target.experience_level.load(Ordering::Relaxed); - let current_max_points = experience::points_in_level(current_level); - - if amount > current_max_points { + let current_lvl = target.experience_level.load(Ordering::Relaxed); + if amount > experience::points_in_level(current_lvl) { return false; } - target.set_experience_points(amount).await; } } @@ -214,72 +138,46 @@ impl CommandExecutor for Executor { Box::pin(async move { let targets = PlayersArgumentConsumer::find_arg(args, ARG_TARGETS)?; - match self.mode { - Mode::Query => { - if targets.len() != 1 { - // TODO: Add proper error message for multiple players in query mode during parsing itself and not here - return Err(CommandError::CommandFailed(TextComponent::translate( - "argument.player.toomany", - [], - ))); - } - Ok(self - .handle_query(sender, &targets[0], self.exp_type.unwrap()) - .await) + if self.mode == Mode::Query { + let target = targets.first().ok_or_else(|| { + CommandError::CommandFailed(TextComponent::translate( + "argument.player.unknown", + [], + )) + })?; + + if targets.len() > 1 { + return Err(CommandError::CommandFailed(TextComponent::translate( + "argument.player.toomany", + [], + ))); } - Mode::Add | Mode::Set => { - let Ok(amount) = BoundedNumArgumentConsumer::::find_arg(args, ARG_AMOUNT)? - else { - return Err(CommandError::CommandFailed(TextComponent::translate( - "commands.experience.set.points.invalid", - [], - ))); - }; + return Ok(self.handle_query(sender, target).await); + } - if self.mode == Mode::Set && amount < 0 { - return Err(CommandError::CommandFailed(TextComponent::translate( - "commands.experience.set.points.invalid", - [], - ))); - } + // Handle Add/Set + let amount = BoundedNumArgumentConsumer::::find_arg(args, ARG_AMOUNT)??; - let mut successes: i32 = 0; - for target in targets { - let succeeded = self - .handle_modify(target, amount, self.exp_type.unwrap(), self.mode) - .await; - - if succeeded { - successes += 1; - } - } - - if successes == 0 { - Err(CommandError::CommandFailed(TextComponent::translate( - "commands.experience.set.points.invalid", - [], - ))) - } else { - // This should not panic as we already check the number of successes to not be equal to `0`. - let target = targets - .first() - .expect("expected at least one player in targets") - .get_display_name() - .await; - - let msg = Self::get_success_message( - self.mode, - self.exp_type.unwrap(), - amount, - targets.len(), - Some(target), - ); - sender.send_message(msg).await; - - Ok(successes) - } + let mut successes = 0; + for target in targets { + if self.handle_modify(target, amount).await { + successes += 1; } } + + if successes == 0 { + return Err(CommandError::CommandFailed(TextComponent::translate( + "commands.experience.set.points.invalid", + [], + ))); + } + + // Safe to access first() because successes > 0 + let first_name = targets[0].get_display_name().await; + let msg = self.get_success_message(amount, targets, first_name); + sender.send_message(msg).await; + + Ok(successes) }) } } @@ -292,15 +190,15 @@ pub fn init_command_tree() -> CommandTree { argument(ARG_AMOUNT, xp_amount()) .then(literal("levels").execute(Executor { mode: Mode::Add, - exp_type: Some(ExpType::Levels), + exp_type: ExpType::Levels, })) .then(literal("points").execute(Executor { mode: Mode::Add, - exp_type: Some(ExpType::Points), + exp_type: ExpType::Points, })) .execute(Executor { mode: Mode::Add, - exp_type: Some(ExpType::Points), + exp_type: ExpType::Points, }), ), ), @@ -311,15 +209,15 @@ pub fn init_command_tree() -> CommandTree { argument(ARG_AMOUNT, xp_amount()) .then(literal("levels").execute(Executor { mode: Mode::Set, - exp_type: Some(ExpType::Levels), + exp_type: ExpType::Levels, })) .then(literal("points").execute(Executor { mode: Mode::Set, - exp_type: Some(ExpType::Points), + exp_type: ExpType::Points, })) .execute(Executor { mode: Mode::Set, - exp_type: Some(ExpType::Points), + exp_type: ExpType::Points, }), ), ), @@ -329,11 +227,11 @@ pub fn init_command_tree() -> CommandTree { argument(ARG_TARGETS, PlayersArgumentConsumer) .then(literal("levels").execute(Executor { mode: Mode::Query, - exp_type: Some(ExpType::Levels), + exp_type: ExpType::Levels, })) .then(literal("points").execute(Executor { mode: Mode::Query, - exp_type: Some(ExpType::Points), + exp_type: ExpType::Points, })), ), ) diff --git a/pumpkin/src/data/usercache.rs b/pumpkin/src/data/usercache.rs index ef6cbb37d..ac5f3879e 100644 --- a/pumpkin/src/data/usercache.rs +++ b/pumpkin/src/data/usercache.rs @@ -2,20 +2,20 @@ use std::cmp::Reverse; use std::collections::HashMap; use std::{env, fs}; -use chrono::{DateTime, FixedOffset, Local, Months, TimeDelta, Utc}; use serde::{Deserialize, Serialize}; +use time::format_description::well_known::Rfc3339; +use time::{Duration, OffsetDateTime}; use tracing::warn; use uuid::Uuid; const USER_CACHE_PATH: &str = "usercache.json"; const USER_CACHE_MRU_LIMIT: usize = 1000; -const USER_CACHE_DATE_FORMAT: &str = "%Y-%m-%d %H:%M:%S %z"; #[derive(Clone, Debug)] pub struct UserCacheEntry { pub uuid: Uuid, pub name: String, - expiration_date: DateTime, + expiration_date: OffsetDateTime, last_access: u64, } @@ -192,8 +192,8 @@ impl UserCache { let Ok(uuid) = Uuid::parse_str(uuid_raw) else { continue; }; - let Ok(expiration_date) = DateTime::parse_from_str(expires_on, USER_CACHE_DATE_FORMAT) - else { + + let Ok(expiration_date) = OffsetDateTime::parse(expires_on, &Rfc3339) else { continue; }; @@ -209,16 +209,14 @@ impl UserCache { } } -fn format_cache_date(date: DateTime) -> String { - date.format(USER_CACHE_DATE_FORMAT).to_string() +fn format_cache_date(date: OffsetDateTime) -> String { + date.format(&Rfc3339).unwrap_or_default() } -fn is_expired(expiration_date: DateTime) -> bool { - Utc::now() >= expiration_date.with_timezone(&Utc) +fn is_expired(expiration_date: OffsetDateTime) -> bool { + OffsetDateTime::now_utc() >= expiration_date } -fn one_month_from_now() -> DateTime { - let now = Local::now().fixed_offset(); - now.checked_add_months(Months::new(1)) - .unwrap_or(now + TimeDelta::days(30)) +fn one_month_from_now() -> OffsetDateTime { + OffsetDateTime::now_utc() + Duration::days(30) } diff --git a/pumpkin/src/entity/mob/mod.rs b/pumpkin/src/entity/mob/mod.rs index 2d90785c5..e51ba2e83 100644 --- a/pumpkin/src/entity/mob/mod.rs +++ b/pumpkin/src/entity/mob/mod.rs @@ -561,8 +561,7 @@ pub trait SunSensitive: Mob + Send + Sync { .level .light_engine .get_sky_light_level(&world.level, &pos.to_block_pos()) - .await - .unwrap_or(0) as f32 + .await as f32 / 15.0; if brightness < 0.5 { diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index f21bfa22a..6a9bf0ac1 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -106,7 +106,7 @@ use pumpkin_world::chunk_system::ChunkLoading; const MAX_CACHED_SIGNATURES: u8 = 128; // Vanilla: 128 const MAX_PREVIOUS_MESSAGES: u8 = 20; // Vanilla: 20 -pub const DATA_VERSION: i32 = 4786; // 26.1 +pub const DATA_VERSION: i32 = 4790; // 26.1.2 enum BatchState { Count(u8), diff --git a/pumpkin/src/net/bedrock/mod.rs b/pumpkin/src/net/bedrock/mod.rs index 9403baed5..e0e7a0056 100644 --- a/pumpkin/src/net/bedrock/mod.rs +++ b/pumpkin/src/net/bedrock/mod.rs @@ -449,6 +449,13 @@ impl BedrockClient { vec }); + if fragment_index >= entry.len() { + return Err(Error::other(format!( + "Fragment index {fragment_index} out of bounds for size {}", + entry.len() + ))); + } + entry[fragment_index] = Some(frame); // Check if all fragments are received @@ -456,21 +463,21 @@ impl BedrockClient { return Ok(()); } - let mut frames = compounds.remove(&compound_id).unwrap(); + let mut frames_opt = compounds + .remove(&compound_id) + .ok_or_else(|| Error::other("Compound ID vanished"))?; - // Safety: We already checked that all frames are Some at this point - let len = frames - .iter() - .map(|frame| unsafe { frame.as_ref().unwrap_unchecked().payload.len() }) - .sum(); + let total_len: usize = frames_opt.iter().flatten().map(|f| f.payload.len()).sum(); - let mut merged = Vec::with_capacity(len); + let mut merged = Vec::with_capacity(total_len); - for frame in &frames { - merged.extend_from_slice(unsafe { &frame.as_ref().unwrap_unchecked().payload }); + for f in frames_opt.iter().flatten() { + merged.extend_from_slice(&f.payload); } - frame = unsafe { frames[0].take().unwrap_unchecked() }; + frame = frames_opt[0] + .take() + .ok_or_else(|| Error::other("Failed to retrieve primary frame"))?; frame.payload = merged; frame.split_size = 0; @@ -504,7 +511,8 @@ impl BedrockClient { .await; } _ => { - self.handle_play_packet(self.player.lock().await.as_ref().unwrap(), server, packet) + return self + .handle_play_packet(self.player.lock().await.as_ref().unwrap(), server, packet) .await; } } @@ -516,46 +524,43 @@ impl BedrockClient { player: &Arc, server: &Arc, packet: RawPacket, - ) { + ) -> Result<(), Error> { let reader = &mut &packet.payload[..]; match packet.id { SPlayerAuthInput::PACKET_ID => { - if let Ok(input_packet) = SPlayerAuthInput::read(reader) { - self.player_pos_update(player, input_packet, server).await; - } + self.player_pos_update(player, SPlayerAuthInput::read(reader)?, server) + .await; } SLoadingScreen::PACKET_ID => { - if SLoadingScreen::read(reader).unwrap().is_loading_done() { + if SLoadingScreen::read(reader)?.is_loading_done() { player.set_client_loaded(true); } } SRequestChunkRadius::PACKET_ID => { - self.handle_request_chunk_radius( - player, - SRequestChunkRadius::read(reader).unwrap(), - ) - .await; + self.handle_request_chunk_radius(player, SRequestChunkRadius::read(reader)?) + .await; } SInteraction::PACKET_ID => { - self.handle_interaction(player, SInteraction::read(reader).unwrap()) + self.handle_interaction(player, SInteraction::read(reader)?) .await; } SContainerClose::PACKET_ID => { - self.handle_container_close(player, SContainerClose::read(reader).unwrap()) + self.handle_container_close(player, SContainerClose::read(reader)?) .await; } SText::PACKET_ID => { - self.handle_chat_message(server, player, SText::read(reader).unwrap()) + self.handle_chat_message(server, player, SText::read(reader)?) .await; } SCommandRequest::PACKET_ID => { - self.handle_chat_command(player, server, SCommandRequest::read(reader).unwrap()) + self.handle_chat_command(player, server, SCommandRequest::read(reader)?) .await; } _ => { warn!("Bedrock: Received Unknown Game packet: {}", packet.id); } } + Ok(()) } async fn handle_raknet_packet(