fix: edit game rule screen
This commit is contained in:
parent
7f369c4b5e
commit
9c89f60619
98
Cargo.lock
generated
98
Cargo.lock
generated
@ -263,9 +263,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-compression"
|
name = "async-compression"
|
||||||
version = "0.4.44"
|
version = "0.4.46"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "515a1f282e33d55983c499d7e9e87082e81cbc32974825bf9032f928392d5844"
|
checksum = "4f10dafd0c8d2e51ae9a748805777613ed0bbe17bf586b76c8311f45c020a32f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compression-codecs",
|
"compression-codecs",
|
||||||
"compression-core",
|
"compression-core",
|
||||||
@ -398,9 +398,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.13.1"
|
version = "2.13.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
@ -746,9 +746,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compression-codecs"
|
name = "compression-codecs"
|
||||||
version = "0.4.39"
|
version = "0.4.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fe67f2944eef52fc7b106b8c9450d243a88701a0c065f7f57235e76abaed7df"
|
checksum = "58a6d0db8759036a783bc7c3f7a07f8cef3bf9470eb1db3bc86e8bcd1c5d0fe8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compression-core",
|
"compression-core",
|
||||||
"flate2",
|
"flate2",
|
||||||
@ -2242,7 +2242,7 @@ version = "0.11.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4cc00ea907cab49550b7da656f80ebb97be1b997d931fbcd28d39734e17ce592"
|
checksum = "4cc00ea907cab49550b7da656f80ebb97be1b997d931fbcd28d39734e17ce592"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"inotify-sys",
|
"inotify-sys",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@ -2299,9 +2299,9 @@ checksum = "2f0fb0570afe1fed943c5c3d4102d5358592d8625fda6a0007fdbe65a92fba96"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.12.1"
|
version = "2.12.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78"
|
checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
@ -2403,9 +2403,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.104"
|
version = "0.3.105"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a"
|
checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@ -2428,7 +2428,7 @@ version = "1.1.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087"
|
checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2665,7 +2665,7 @@ version = "0.31.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"libc",
|
"libc",
|
||||||
@ -2697,7 +2697,7 @@ version = "8.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"fsevent-sys",
|
"fsevent-sys",
|
||||||
"inotify",
|
"inotify",
|
||||||
"kqueue",
|
"kqueue",
|
||||||
@ -2715,7 +2715,7 @@ version = "2.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a"
|
checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2806,7 +2806,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3110,7 +3110,7 @@ version = "0.18.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
|
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"fdeflate",
|
"fdeflate",
|
||||||
"flate2",
|
"flate2",
|
||||||
@ -3335,7 +3335,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"base64 0.23.1",
|
"base64 0.23.1",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"colored",
|
"colored",
|
||||||
"console-subscriber",
|
"console-subscriber",
|
||||||
@ -3606,7 +3606,7 @@ dependencies = [
|
|||||||
"aes 0.9.3",
|
"aes 0.9.3",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
"base64 0.23.1",
|
"base64 0.23.1",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cesu8",
|
"cesu8",
|
||||||
"cfb8",
|
"cfb8",
|
||||||
@ -3650,7 +3650,7 @@ name = "pumpkin-world"
|
|||||||
version = "0.1.0+26.2-26.45"
|
version = "0.1.0+26.2-26.45"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"criterion",
|
"criterion",
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
@ -3789,7 +3789,7 @@ version = "0.5.18"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3858,11 +3858,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.13.4"
|
version = "0.13.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
|
checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.23.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@ -4299,7 +4299,7 @@ version = "1.1.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
@ -4318,9 +4318,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.43"
|
version = "0.23.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06"
|
checksum = "6725596c3f2c3a0aef021139e145d4eafe314a6623e4680ca83852b2c67ab2ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -4402,7 +4402,7 @@ version = "18.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "53f6a737db68eb1a8ccff86b584b2fc13eca6a7bb6f78ebc7c529547e3ab9684"
|
checksum = "53f6a737db68eb1a8ccff86b584b2fc13eca6a7bb6f78ebc7c529547e3ab9684"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"clipboard-win",
|
"clipboard-win",
|
||||||
"libc",
|
"libc",
|
||||||
@ -4485,7 +4485,7 @@ version = "3.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@ -5173,7 +5173,7 @@ version = "0.6.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
|
checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
@ -5396,9 +5396,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.127"
|
version = "0.2.128"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70"
|
checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -5409,9 +5409,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.77"
|
version = "0.4.78"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950"
|
checksum = "6ef4c5d3d2cdf5c54f4231181768f5510842e350db025faf1f7163b1030ed928"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@ -5419,9 +5419,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.127"
|
version = "0.2.128"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1"
|
checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@ -5429,22 +5429,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.127"
|
version = "0.2.128"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284"
|
checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.119",
|
"syn 3.0.5",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.127"
|
version = "0.2.128"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf"
|
checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@ -5477,7 +5477,7 @@ version = "0.258.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9a61719f93a87b16d325921e251800c4833f8fab50fa21c7de73aed50086313"
|
checksum = "d9a61719f93a87b16d325921e251800c4833f8fab50fa21c7de73aed50086313"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"hashbrown 0.17.1",
|
"hashbrown 0.17.1",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"semver",
|
"semver",
|
||||||
@ -5502,7 +5502,7 @@ source = "git+https://github.com/bytecodealliance/wasmtime?rev=f6b3140dbb1d9b436
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"addr2line",
|
"addr2line",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cc",
|
"cc",
|
||||||
@ -5699,7 +5699,7 @@ version = "49.0.0-dev"
|
|||||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=f6b3140dbb1d9b436ef523d14740292c956b0364#f6b3140dbb1d9b436ef523d14740292c956b0364"
|
source = "git+https://github.com/bytecodealliance/wasmtime?rev=f6b3140dbb1d9b436ef523d14740292c956b0364#f6b3140dbb1d9b436ef523d14740292c956b0364"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"heck",
|
"heck",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"wit-component",
|
"wit-component",
|
||||||
@ -5712,7 +5712,7 @@ version = "49.0.0-dev"
|
|||||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=f6b3140dbb1d9b436ef523d14740292c956b0364#f6b3140dbb1d9b436ef523d14740292c956b0364"
|
source = "git+https://github.com/bytecodealliance/wasmtime?rev=f6b3140dbb1d9b436ef523d14740292c956b0364#f6b3140dbb1d9b436ef523d14740292c956b0364"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cap-primitives",
|
"cap-primitives",
|
||||||
"futures",
|
"futures",
|
||||||
@ -5767,9 +5767,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.104"
|
version = "0.3.105"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30"
|
checksum = "9fbddc4a036f00ec4f18c83445bd3115cb306a91da554919a099d9222fe4a7f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@ -6129,7 +6129,7 @@ version = "0.36.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d"
|
checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -6191,7 +6191,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "481b5c47b2ecce0389b5e08a05557d6a190c9cd761773b8880a8017ee04dc7ef"
|
checksum = "481b5c47b2ecce0389b5e08a05557d6a190c9cd761773b8880a8017ee04dc7ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.2",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@ -149,9 +149,9 @@ serde_json = { version = "1.0", default-features = false, features = ["std"] }
|
|||||||
tempfile = { version = "3.27.0", default-features = false }
|
tempfile = { version = "3.27.0", default-features = false }
|
||||||
proc-macro-error2 = { version = "2", default-features = false }
|
proc-macro-error2 = { version = "2", default-features = false }
|
||||||
aes = { version = "0.9", default-features = false }
|
aes = { version = "0.9", default-features = false }
|
||||||
async-compression = { version = "0.4.44", default-features = false }
|
async-compression = { version = "0.4.46", default-features = false }
|
||||||
base64 = { version = "0.23.1", default-features = false, features = ["std"] }
|
base64 = { version = "0.23.1", default-features = false, features = ["std"] }
|
||||||
bitflags = { version = "2.13.1", default-features = false, features = ["std"] }
|
bitflags = { version = "2.13.2", default-features = false, features = ["std"] }
|
||||||
cesu8 = { version = "1.1", default-features = false }
|
cesu8 = { version = "1.1", default-features = false }
|
||||||
cfb8 = { version = "0.9", default-features = false }
|
cfb8 = { version = "0.9", default-features = false }
|
||||||
colored = { version = "3.1", default-features = false }
|
colored = { version = "3.1", default-features = false }
|
||||||
@ -215,7 +215,7 @@ time = { version = "0.3", default-features = false, features = ["std"] }
|
|||||||
arc-swap = { version = "1.9", default-features = false }
|
arc-swap = { version = "1.9", default-features = false }
|
||||||
tokio-util = { version = "0.7.19", default-features = false }
|
tokio-util = { version = "0.7.19", default-features = false }
|
||||||
toml = { version = "1.1", default-features = false, features = ["parse", "display", "serde"] }
|
toml = { version = "1.1", default-features = false, features = ["parse", "display", "serde"] }
|
||||||
reqwest = { version = "0.13.4", default-features = false, features = ["rustls-no-provider", "json", "http2"] }
|
reqwest = { version = "0.13.5", default-features = false, features = ["rustls-no-provider", "json", "http2"] }
|
||||||
notify = { version = "8.2.0", default-features = false, features = ["macos_fsevent"] }
|
notify = { version = "8.2.0", default-features = false, features = ["macos_fsevent"] }
|
||||||
|
|
||||||
sysinfo = { version = "0.39", default-features = false, features = ["system"] }
|
sysinfo = { version = "0.39", default-features = false, features = ["system"] }
|
||||||
|
|||||||
@ -6,6 +6,18 @@ use serde_json::Value;
|
|||||||
pub enum TestType {
|
pub enum TestType {
|
||||||
#[serde(rename = "minecraft:block_based")]
|
#[serde(rename = "minecraft:block_based")]
|
||||||
BlockBased,
|
BlockBased,
|
||||||
|
#[serde(rename = "minecraft:function")]
|
||||||
|
Function,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestType {
|
||||||
|
#[must_use]
|
||||||
|
pub const fn serialized_name(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::BlockBased => "minecraft:block_based",
|
||||||
|
Self::Function => "minecraft:function",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
|
||||||
@ -71,6 +83,8 @@ pub struct GameTestDefinition {
|
|||||||
pub instance_type: TestType,
|
pub instance_type: TestType,
|
||||||
pub environment: Value,
|
pub environment: Value,
|
||||||
pub structure: String,
|
pub structure: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub function: Option<String>,
|
||||||
pub max_ticks: i32,
|
pub max_ticks: i32,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub setup_ticks: i32,
|
pub setup_ticks: i32,
|
||||||
@ -93,7 +107,13 @@ pub struct GameTestDefinition {
|
|||||||
impl GameTestDefinition {
|
impl GameTestDefinition {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_valid(&self) -> bool {
|
pub fn is_valid(&self) -> bool {
|
||||||
self.max_ticks > 0
|
let function_valid = match self.instance_type {
|
||||||
|
TestType::BlockBased => true,
|
||||||
|
TestType::Function => self.function.as_ref().is_some_and(|f| !f.is_empty()),
|
||||||
|
};
|
||||||
|
|
||||||
|
function_valid
|
||||||
|
&& self.max_ticks > 0
|
||||||
&& self.setup_ticks >= 0
|
&& self.setup_ticks >= 0
|
||||||
&& self.max_attempts > 0
|
&& self.max_attempts > 0
|
||||||
&& self.required_successes > 0
|
&& self.required_successes > 0
|
||||||
|
|||||||
@ -1,17 +1,20 @@
|
|||||||
use pumpkin_data::packet::clientbound::config::UPDATE_ENABLED_FEATURES;
|
use pumpkin_data::packet::clientbound::config::UPDATE_ENABLED_FEATURES;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
|
|
||||||
use crate::{ClientPacket, ser::NetworkWriteExt};
|
use crate::{ClientPacket, ser::NetworkWriteExt};
|
||||||
|
|
||||||
#[java_packet(UPDATE_ENABLED_FEATURES)]
|
#[java_packet(UPDATE_ENABLED_FEATURES)]
|
||||||
pub struct CFeatureFlags<'a> {
|
pub struct CFeatureFlags<'a> {
|
||||||
pub features: &'a [ResourceLocation],
|
pub features: &'a [&'a str],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type CUpdateEnabledFeatures<'a> = CFeatureFlags<'a>;
|
||||||
|
pub type ClientboundUpdateEnabledFeaturesPacket<'a> = CFeatureFlags<'a>;
|
||||||
|
|
||||||
impl<'a> CFeatureFlags<'a> {
|
impl<'a> CFeatureFlags<'a> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn new(features: &'a [ResourceLocation]) -> Self {
|
pub const fn new(features: &'a [&'a str]) -> Self {
|
||||||
Self { features }
|
Self { features }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,13 @@ use self::test_loader::{
|
|||||||
TestInstance, TestInstanceRegistry, load_test_instances_from_dir, to_registry_entry,
|
TestInstance, TestInstanceRegistry, load_test_instances_from_dir, to_registry_entry,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct KnownPackData {
|
||||||
|
pub namespace: String,
|
||||||
|
pub id: String,
|
||||||
|
pub version: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LoadedDatapack {
|
pub struct LoadedDatapack {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
@ -29,6 +36,7 @@ pub struct LoadedDatapack {
|
|||||||
pub root_path: PathBuf,
|
pub root_path: PathBuf,
|
||||||
pub recipe_count: usize,
|
pub recipe_count: usize,
|
||||||
pub function_count: usize,
|
pub function_count: usize,
|
||||||
|
pub known_packs: Vec<KnownPackData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@ -121,7 +129,7 @@ impl DatapackManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (description, pack_format) = read_pack_mcmeta(&pack_path);
|
let (description, pack_format, known_packs) = read_pack_mcmeta(&pack_path);
|
||||||
|
|
||||||
let (pack_recipe_count, pack_function_count, pack_test_instance_count) =
|
let (pack_recipe_count, pack_function_count, pack_test_instance_count) =
|
||||||
load_pack_contents(
|
load_pack_contents(
|
||||||
@ -144,6 +152,7 @@ impl DatapackManager {
|
|||||||
root_path: pack_path,
|
root_path: pack_path,
|
||||||
recipe_count: pack_recipe_count,
|
recipe_count: pack_recipe_count,
|
||||||
function_count: pack_function_count,
|
function_count: pack_function_count,
|
||||||
|
known_packs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,6 +235,119 @@ impl DatapackManager {
|
|||||||
entries
|
entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the list of known packs for client configuration / pack synchronization,
|
||||||
|
/// matching vanilla's `server.getResourceManager().listPacks().flatMap(p -> p.location().knownPackInfo().stream())`.
|
||||||
|
pub fn get_known_packs<'a>(
|
||||||
|
&self,
|
||||||
|
server: &Server,
|
||||||
|
server_version: &'a str,
|
||||||
|
loaded_packs: &'a [LoadedDatapack],
|
||||||
|
) -> Vec<pumpkin_protocol::KnownPack<'a>> {
|
||||||
|
use pumpkin_protocol::KnownPack;
|
||||||
|
|
||||||
|
let mut known_packs = Vec::new();
|
||||||
|
|
||||||
|
// 1. Primary vanilla core pack
|
||||||
|
known_packs.push(KnownPack {
|
||||||
|
namespace: "minecraft",
|
||||||
|
id: "core",
|
||||||
|
version: server_version,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Built-in feature packs that are enabled
|
||||||
|
let enabled_packs = Self::get_enabled_packs(server);
|
||||||
|
for pack_name in &enabled_packs {
|
||||||
|
let id: &'static str = match pack_name.as_str() {
|
||||||
|
"trade_rebalance" => "trade_rebalance",
|
||||||
|
"minecart_improvements" => "minecart_improvements",
|
||||||
|
"redstone_experiments" => "redstone_experiments",
|
||||||
|
"bundle" => "bundle",
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
let pack = KnownPack {
|
||||||
|
namespace: "minecraft",
|
||||||
|
id,
|
||||||
|
version: server_version,
|
||||||
|
};
|
||||||
|
if !known_packs
|
||||||
|
.iter()
|
||||||
|
.any(|p| p.namespace == pack.namespace && p.id == pack.id)
|
||||||
|
{
|
||||||
|
known_packs.push(pack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Loaded packs with known_pack info from pack.mcmeta
|
||||||
|
for pack in loaded_packs {
|
||||||
|
for kp in &pack.known_packs {
|
||||||
|
let p = KnownPack {
|
||||||
|
namespace: &kp.namespace,
|
||||||
|
id: &kp.id,
|
||||||
|
version: &kp.version,
|
||||||
|
};
|
||||||
|
if !known_packs.iter().any(|existing| {
|
||||||
|
existing.namespace == p.namespace
|
||||||
|
&& existing.id == p.id
|
||||||
|
&& existing.version == p.version
|
||||||
|
}) {
|
||||||
|
known_packs.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
known_packs
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the enabled world feature flags (e.g. `minecraft:vanilla`, `minecraft:trade_rebalance`,
|
||||||
|
/// `minecraft:minecart_improvements`, `minecraft:redstone_experiments`, `minecraft:bundle`).
|
||||||
|
#[must_use]
|
||||||
|
pub fn get_enabled_features(&self, server: &Server) -> Vec<&'static str> {
|
||||||
|
let enabled_packs = Self::get_enabled_packs(server);
|
||||||
|
Self::resolve_enabled_features(&enabled_packs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolves enabled feature flag names given a list of enabled pack names.
|
||||||
|
#[must_use]
|
||||||
|
pub fn resolve_enabled_features(enabled_packs: &[String]) -> Vec<&'static str> {
|
||||||
|
let mut features = vec!["minecraft:vanilla"];
|
||||||
|
|
||||||
|
for pack_name in enabled_packs {
|
||||||
|
let feature: &'static str = match pack_name.as_str() {
|
||||||
|
"trade_rebalance" | "file/trade_rebalance" => "minecraft:trade_rebalance",
|
||||||
|
"minecart_improvements" | "file/minecart_improvements" => {
|
||||||
|
"minecraft:minecart_improvements"
|
||||||
|
}
|
||||||
|
"redstone_experiments" | "file/redstone_experiments" => {
|
||||||
|
"minecraft:redstone_experiments"
|
||||||
|
}
|
||||||
|
"bundle" | "file/bundle" => "minecraft:bundle",
|
||||||
|
_ => {
|
||||||
|
if let Some(stripped) = pack_name.strip_prefix("file/") {
|
||||||
|
match stripped {
|
||||||
|
"trade_rebalance" => "minecraft:trade_rebalance",
|
||||||
|
"minecart_improvements" => "minecraft:minecart_improvements",
|
||||||
|
"redstone_experiments" => "minecraft:redstone_experiments",
|
||||||
|
"bundle" => "minecraft:bundle",
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !features.contains(&feature) {
|
||||||
|
features.push(feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
features
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn is_feature_enabled(&self, server: &Server, feature: &str) -> bool {
|
||||||
|
self.get_enabled_features(server).contains(&feature)
|
||||||
|
}
|
||||||
|
|
||||||
/// Loads a Java Edition structure NBT from the currently enabled datapacks.
|
/// Loads a Java Edition structure NBT from the currently enabled datapacks.
|
||||||
///
|
///
|
||||||
/// Structure identifiers are resource locations such as
|
/// Structure identifiers are resource locations such as
|
||||||
@ -520,7 +642,7 @@ impl DatapackManager {
|
|||||||
.get_world_path()
|
.get_world_path()
|
||||||
.join("datapacks")
|
.join("datapacks")
|
||||||
.join(stripped);
|
.join(stripped);
|
||||||
let (desc, format) = read_pack_mcmeta(&pack_path);
|
let (desc, format, _) = read_pack_mcmeta(&pack_path);
|
||||||
(resolved_name.clone(), stripped.to_string(), desc, format)
|
(resolved_name.clone(), stripped.to_string(), desc, format)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
@ -821,7 +943,7 @@ fn load_pack_contents(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_pack_mcmeta(pack_path: &Path) -> (String, u32) {
|
fn read_pack_mcmeta(pack_path: &Path) -> (String, u32, Vec<KnownPackData>) {
|
||||||
let mcmeta_path = pack_path.join("pack.mcmeta");
|
let mcmeta_path = pack_path.join("pack.mcmeta");
|
||||||
if let Ok(content) = fs::read_to_string(mcmeta_path)
|
if let Ok(content) = fs::read_to_string(mcmeta_path)
|
||||||
&& let Ok(val) = serde_json::from_str::<serde_json::Value>(&content)
|
&& let Ok(val) = serde_json::from_str::<serde_json::Value>(&content)
|
||||||
@ -838,9 +960,49 @@ fn read_pack_mcmeta(pack_path: &Path) -> (String, u32) {
|
|||||||
.and_then(|p| p.get("pack_format"))
|
.and_then(|p| p.get("pack_format"))
|
||||||
.and_then(serde_json::Value::as_u64)
|
.and_then(serde_json::Value::as_u64)
|
||||||
.unwrap_or(61) as u32;
|
.unwrap_or(61) as u32;
|
||||||
return (description, pack_format);
|
|
||||||
|
let mut known_packs = Vec::new();
|
||||||
|
let parse_item = |item: &serde_json::Value| -> Option<KnownPackData> {
|
||||||
|
let ns = item.get("namespace").and_then(serde_json::Value::as_str)?;
|
||||||
|
let id = item.get("id").and_then(serde_json::Value::as_str)?;
|
||||||
|
let ver = item.get("version").and_then(serde_json::Value::as_str)?;
|
||||||
|
Some(KnownPackData {
|
||||||
|
namespace: ns.to_string(),
|
||||||
|
id: id.to_string(),
|
||||||
|
version: ver.to_string(),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(packs_array) = val.get("known_packs").and_then(serde_json::Value::as_array) {
|
||||||
|
for item in packs_array {
|
||||||
|
if let Some(kp) = parse_item(item) {
|
||||||
|
known_packs.push(kp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let Some(item) = val.get("known_pack") {
|
||||||
|
if let Some(kp) = parse_item(item) {
|
||||||
|
known_packs.push(kp);
|
||||||
|
}
|
||||||
|
} else if let Some(pack_obj) = pack {
|
||||||
|
if let Some(packs_array) = pack_obj
|
||||||
|
.get("known_packs")
|
||||||
|
.and_then(serde_json::Value::as_array)
|
||||||
|
{
|
||||||
|
for item in packs_array {
|
||||||
|
if let Some(kp) = parse_item(item) {
|
||||||
|
known_packs.push(kp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let Some(item) = pack_obj.get("known_pack")
|
||||||
|
&& let Some(kp) = parse_item(item)
|
||||||
|
{
|
||||||
|
known_packs.push(kp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (description, pack_format, known_packs);
|
||||||
}
|
}
|
||||||
(String::new(), 61)
|
(String::new(), 61, Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_recipes_from_dir(
|
fn load_recipes_from_dir(
|
||||||
@ -946,4 +1108,87 @@ mod tests {
|
|||||||
"Unknown function tag: #test:missing"
|
"Unknown function tag: #test:missing"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn read_pack_mcmeta_parses_known_packs() {
|
||||||
|
let temp_dir = tempfile::tempdir().expect("tempdir");
|
||||||
|
let pack_path = temp_dir.path();
|
||||||
|
|
||||||
|
// 1. Test root known_packs array
|
||||||
|
let mcmeta_content = r#"{
|
||||||
|
"pack": {
|
||||||
|
"description": "Test Pack",
|
||||||
|
"pack_format": 61
|
||||||
|
},
|
||||||
|
"known_packs": [
|
||||||
|
{
|
||||||
|
"namespace": "example",
|
||||||
|
"id": "content",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"#;
|
||||||
|
std::fs::write(pack_path.join("pack.mcmeta"), mcmeta_content).unwrap();
|
||||||
|
|
||||||
|
let (desc, format, known_packs) = super::read_pack_mcmeta(pack_path);
|
||||||
|
assert_eq!(desc, "Test Pack");
|
||||||
|
assert_eq!(format, 61);
|
||||||
|
assert_eq!(known_packs.len(), 1);
|
||||||
|
assert_eq!(known_packs[0].namespace, "example");
|
||||||
|
assert_eq!(known_packs[0].id, "content");
|
||||||
|
assert_eq!(known_packs[0].version, "1.0.0");
|
||||||
|
|
||||||
|
// 2. Test nested pack.known_packs
|
||||||
|
let mcmeta_content_nested = r#"{
|
||||||
|
"pack": {
|
||||||
|
"description": "Nested Pack",
|
||||||
|
"pack_format": 61,
|
||||||
|
"known_packs": [
|
||||||
|
{
|
||||||
|
"namespace": "nested",
|
||||||
|
"id": "pack",
|
||||||
|
"version": "2.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"#;
|
||||||
|
std::fs::write(pack_path.join("pack.mcmeta"), mcmeta_content_nested).unwrap();
|
||||||
|
|
||||||
|
let (_, _, known_packs) = super::read_pack_mcmeta(pack_path);
|
||||||
|
assert_eq!(known_packs.len(), 1);
|
||||||
|
assert_eq!(known_packs[0].namespace, "nested");
|
||||||
|
assert_eq!(known_packs[0].id, "pack");
|
||||||
|
assert_eq!(known_packs[0].version, "2.0.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resolve_enabled_features_works() {
|
||||||
|
// Default only vanilla
|
||||||
|
let default_features = DatapackManager::resolve_enabled_features(&[]);
|
||||||
|
assert_eq!(default_features, ["minecraft:vanilla"]);
|
||||||
|
|
||||||
|
// With minecart improvements
|
||||||
|
let minecart_features =
|
||||||
|
DatapackManager::resolve_enabled_features(&["file/minecart_improvements".to_string()]);
|
||||||
|
assert_eq!(
|
||||||
|
minecart_features,
|
||||||
|
["minecraft:vanilla", "minecraft:minecart_improvements"]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Multiple experimental features
|
||||||
|
let multi_features = DatapackManager::resolve_enabled_features(&[
|
||||||
|
"trade_rebalance".to_string(),
|
||||||
|
"redstone_experiments".to_string(),
|
||||||
|
"file/bundle".to_string(),
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
multi_features,
|
||||||
|
[
|
||||||
|
"minecraft:vanilla",
|
||||||
|
"minecraft:trade_rebalance",
|
||||||
|
"minecraft:redstone_experiments",
|
||||||
|
"minecraft:bundle"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,14 +96,11 @@ fn load_test_instances_recursive(
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn to_registry_entry(entry_id: String, instance: &TestInstance) -> RegistryEntryData {
|
pub fn to_registry_entry(entry_id: String, instance: &TestInstance) -> RegistryEntryData {
|
||||||
let mut nbt = NbtCompound::new();
|
let mut nbt = NbtCompound::new();
|
||||||
nbt.put_string(
|
nbt.put_string("type", instance.instance_type.serialized_name().to_string());
|
||||||
"type",
|
|
||||||
match instance.instance_type {
|
|
||||||
TestType::BlockBased => "minecraft:block_based",
|
|
||||||
}
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
nbt.put("environment", json_value_to_nbt(&instance.environment));
|
nbt.put("environment", json_value_to_nbt(&instance.environment));
|
||||||
|
if let Some(function) = &instance.function {
|
||||||
|
nbt.put_string("function", function.clone());
|
||||||
|
}
|
||||||
nbt.put_string("structure", instance.structure.clone());
|
nbt.put_string("structure", instance.structure.clone());
|
||||||
nbt.put_int("max_ticks", instance.max_ticks);
|
nbt.put_int("max_ticks", instance.max_ticks);
|
||||||
nbt.put_int("setup_ticks", instance.setup_ticks);
|
nbt.put_int("setup_ticks", instance.setup_ticks);
|
||||||
@ -203,4 +200,66 @@ mod tests {
|
|||||||
assert!(!instance.sky_access);
|
assert!(!instance.sky_access);
|
||||||
assert_eq!(instance.padding, 0);
|
assert_eq!(instance.padding, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn loads_function_test_instance_with_vanilla_defaults() {
|
||||||
|
let dir = tempfile::tempdir().expect("temp dir");
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
dir.path().join("always_pass.json"),
|
||||||
|
r#"{
|
||||||
|
"type": "minecraft:function",
|
||||||
|
"environment": "minecraft:default",
|
||||||
|
"function": "minecraft:always_pass",
|
||||||
|
"max_ticks": 1,
|
||||||
|
"required": false,
|
||||||
|
"setup_ticks": 1,
|
||||||
|
"structure": "minecraft:empty"
|
||||||
|
}"#,
|
||||||
|
)
|
||||||
|
.expect("write test instance");
|
||||||
|
|
||||||
|
let mut registry = TestInstanceRegistry::new();
|
||||||
|
let loaded = load_test_instances_from_dir("minecraft", dir.path(), &mut registry);
|
||||||
|
|
||||||
|
assert_eq!(loaded, 1);
|
||||||
|
|
||||||
|
let instance = registry
|
||||||
|
.get("minecraft:always_pass")
|
||||||
|
.expect("test instance should be registered");
|
||||||
|
|
||||||
|
assert_eq!(instance.instance_type, TestType::Function);
|
||||||
|
assert_eq!(
|
||||||
|
instance.environment,
|
||||||
|
Value::String("minecraft:default".into())
|
||||||
|
);
|
||||||
|
assert_eq!(instance.function.as_deref(), Some("minecraft:always_pass"));
|
||||||
|
assert_eq!(instance.structure, "minecraft:empty");
|
||||||
|
assert_eq!(instance.max_ticks, 1);
|
||||||
|
assert_eq!(instance.setup_ticks, 1);
|
||||||
|
assert!(!instance.required);
|
||||||
|
assert_eq!(instance.rotation, GameTestRotation::None);
|
||||||
|
assert!(!instance.manual_only);
|
||||||
|
assert_eq!(instance.max_attempts, 1);
|
||||||
|
assert_eq!(instance.required_successes, 1);
|
||||||
|
assert!(!instance.sky_access);
|
||||||
|
assert_eq!(instance.padding, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn loads_embedded_test_instances_including_always_pass() {
|
||||||
|
let mut registry = TestInstanceRegistry::new();
|
||||||
|
let count = load_embedded_test_instances(&mut registry);
|
||||||
|
assert!(count > 0);
|
||||||
|
|
||||||
|
let always_pass = registry
|
||||||
|
.get("minecraft:always_pass")
|
||||||
|
.expect("minecraft:always_pass should be successfully parsed and registered");
|
||||||
|
assert_eq!(always_pass.instance_type, TestType::Function);
|
||||||
|
assert_eq!(
|
||||||
|
always_pass.function.as_deref(),
|
||||||
|
Some("minecraft:always_pass")
|
||||||
|
);
|
||||||
|
assert_eq!(always_pass.structure, "minecraft:empty");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,10 @@ impl JavaClient {
|
|||||||
let version = self.version.load();
|
let version = self.version.load();
|
||||||
|
|
||||||
if version.supports_configuration_state() {
|
if version.supports_configuration_state() {
|
||||||
self.send_packet(&CFeatureFlags::new(&["minecraft:vanilla".to_string()]))
|
if version < JavaMinecraftVersion::V_1_20_5 {
|
||||||
.await;
|
let features = server.get_enabled_features();
|
||||||
|
self.send_packet(&CFeatureFlags::new(&features)).await;
|
||||||
|
}
|
||||||
|
|
||||||
let test_instance_entries =
|
let test_instance_entries =
|
||||||
server.datapack_manager.get_test_instance_registry_entries();
|
server.datapack_manager.get_test_instance_registry_entries();
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use crate::{
|
|||||||
use core::str;
|
use core::str;
|
||||||
use pumpkin_data::registry::Registry;
|
use pumpkin_data::registry::Registry;
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
ConnectionState, KnownPack,
|
ConnectionState,
|
||||||
java::{
|
java::{
|
||||||
client::config::{CFeatureFlags, CFinishConfig, CKnownPacks, CRegistryData, CUpdateTags},
|
client::config::{CFeatureFlags, CFinishConfig, CKnownPacks, CRegistryData, CUpdateTags},
|
||||||
server::config::{
|
server::config::{
|
||||||
@ -20,7 +20,7 @@ use pumpkin_protocol::{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use pumpkin_util::{Hand, text::TextComponent};
|
use pumpkin_util::{Hand, text::TextComponent, version::JavaMinecraftVersion};
|
||||||
use tracing::{debug, trace, warn};
|
use tracing::{debug, trace, warn};
|
||||||
|
|
||||||
const BRAND_CHANNEL_PREFIX: &str = "minecraft:brand";
|
const BRAND_CHANNEL_PREFIX: &str = "minecraft:brand";
|
||||||
|
|||||||
@ -69,16 +69,15 @@ impl JavaClient {
|
|||||||
self.id
|
self.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.send_known_packs().await;
|
self.send_known_packs(server).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_known_packs(&self) {
|
pub async fn send_known_packs(&self, server: &Server) {
|
||||||
|
let features = server.get_enabled_features();
|
||||||
|
self.send_packet(&CFeatureFlags::new(&features)).await;
|
||||||
let version_str = self.version.load().to_string();
|
let version_str = self.version.load().to_string();
|
||||||
self.send_packet(&CKnownPacks::new(&[KnownPack {
|
let loaded_packs = server.datapack_manager.get_loaded_packs();
|
||||||
namespace: "minecraft",
|
let known_packs = server.get_known_packs(&version_str, &loaded_packs);
|
||||||
id: "core",
|
self.send_packet(&CKnownPacks::new(&known_packs)).await;
|
||||||
version: &version_str,
|
|
||||||
}]))
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,13 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl PendingConnection {
|
impl PendingConnection {
|
||||||
pub async fn handle_known_packs(&mut self) {
|
pub async fn handle_known_packs(&mut self, server: &Server) {
|
||||||
let version = self.version.load();
|
let version = self.version.load();
|
||||||
if version.supports_configuration_state() {
|
if version.supports_configuration_state() {
|
||||||
self.send_packet_now(&CFeatureFlags::new(&["minecraft:vanilla".to_string()]))
|
if version < JavaMinecraftVersion::V_1_20_5 {
|
||||||
.await;
|
let features = server.get_enabled_features();
|
||||||
|
self.send_packet_now(&CFeatureFlags::new(&features)).await;
|
||||||
|
}
|
||||||
let registry = pumpkin_data::registry::Registry::get_synced(version);
|
let registry = pumpkin_data::registry::Registry::get_synced(version);
|
||||||
for reg in ®istry {
|
for reg in ®istry {
|
||||||
self.send_packet_now(&CRegistryData::new(®.registry_id, ®.registry_entries))
|
self.send_packet_now(&CRegistryData::new(®.registry_id, ®.registry_entries))
|
||||||
|
|||||||
@ -97,21 +97,20 @@ impl PendingConnection {
|
|||||||
|
|
||||||
self.send_packet_now(&resource_pack).await;
|
self.send_packet_now(&resource_pack).await;
|
||||||
} else if self.version.load() >= JavaMinecraftVersion::V_1_20_5 {
|
} else if self.version.load() >= JavaMinecraftVersion::V_1_20_5 {
|
||||||
self.send_known_packs().await;
|
self.send_known_packs(server).await;
|
||||||
} else {
|
} else {
|
||||||
self.handle_known_packs().await;
|
self.handle_known_packs(server).await;
|
||||||
}
|
}
|
||||||
debug!("login acknowledged");
|
debug!("login acknowledged");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_known_packs(&mut self) {
|
pub async fn send_known_packs(&mut self, server: &Server) {
|
||||||
|
let features = server.get_enabled_features();
|
||||||
|
self.send_packet_now(&CFeatureFlags::new(&features)).await;
|
||||||
let version_str = self.version.load().to_string();
|
let version_str = self.version.load().to_string();
|
||||||
self.send_packet_now(&CKnownPacks::new(&[KnownPack {
|
let loaded_packs = server.datapack_manager.get_loaded_packs();
|
||||||
namespace: "minecraft",
|
let known_packs = server.get_known_packs(&version_str, &loaded_packs);
|
||||||
id: "core",
|
self.send_packet_now(&CKnownPacks::new(&known_packs)).await;
|
||||||
version: &version_str,
|
|
||||||
}]))
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use pumpkin_data::translation;
|
use pumpkin_data::translation;
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
ConnectionState, KnownPack, Label, Link, LinkType,
|
ConnectionState, Label, Link, LinkType,
|
||||||
java::client::{
|
java::client::{
|
||||||
config::{
|
config::{
|
||||||
CConfigAddResourcePack, CConfigServerLinks, CFeatureFlags, CFinishConfig, CKnownPacks,
|
CConfigAddResourcePack, CConfigServerLinks, CFeatureFlags, CFinishConfig, CKnownPacks,
|
||||||
|
|||||||
@ -420,7 +420,7 @@ impl PendingConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
id if id == SKnownPacks::to_id(version) => {
|
id if id == SKnownPacks::to_id(version) => {
|
||||||
self.handle_known_packs().await;
|
self.handle_known_packs(server).await;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
id if id == SConfigResourcePack::to_id(version) => {
|
id if id == SConfigResourcePack::to_id(version) => {
|
||||||
@ -509,19 +509,33 @@ impl PendingConnection {
|
|||||||
match packet.response_result() {
|
match packet.response_result() {
|
||||||
ResourcePackResponseResult::Downloaded
|
ResourcePackResponseResult::Downloaded
|
||||||
| ResourcePackResponseResult::DownloadSuccess
|
| ResourcePackResponseResult::DownloadSuccess
|
||||||
| ResourcePackResponseResult::Accepted
|
|
||||||
| ResourcePackResponseResult::Discarded
|
| ResourcePackResponseResult::Discarded
|
||||||
| ResourcePackResponseResult::Unknown(_) => {}
|
| ResourcePackResponseResult::Unknown(_) => {
|
||||||
|
if self.version.load() >= JavaMinecraftVersion::V_1_20_5 {
|
||||||
|
self.send_known_packs(server).await;
|
||||||
|
} else {
|
||||||
|
self.handle_known_packs(server).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResourcePackResponseResult::Accepted => {}
|
||||||
ResourcePackResponseResult::Declined => {
|
ResourcePackResponseResult::Declined => {
|
||||||
if resource_config.force {
|
if resource_config.force {
|
||||||
self.kick(TextComponent::text("Required resource pack was declined"))
|
self.kick(TextComponent::text("Required resource pack was declined"))
|
||||||
.await;
|
.await;
|
||||||
|
} else if self.version.load() >= JavaMinecraftVersion::V_1_20_5 {
|
||||||
|
self.send_known_packs(server).await;
|
||||||
|
} else {
|
||||||
|
self.handle_known_packs(server).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResourcePackResponseResult::DownloadFail => {
|
ResourcePackResponseResult::DownloadFail => {
|
||||||
if resource_config.force {
|
if resource_config.force {
|
||||||
self.kick(TextComponent::text("Failed to download resource pack"))
|
self.kick(TextComponent::text("Failed to download resource pack"))
|
||||||
.await;
|
.await;
|
||||||
|
} else if self.version.load() >= JavaMinecraftVersion::V_1_20_5 {
|
||||||
|
self.send_known_packs(server).await;
|
||||||
|
} else {
|
||||||
|
self.handle_known_packs(server).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResourcePackResponseResult::InvalidUrl => {
|
ResourcePackResponseResult::InvalidUrl => {
|
||||||
|
|||||||
@ -67,9 +67,25 @@ impl JavaClient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let level_info = player.world().level_info.load();
|
let world = player.world();
|
||||||
|
let level_info = world.level_info.load();
|
||||||
|
let minecart_improvements_enabled = world.server.upgrade().map_or_else(
|
||||||
|
|| {
|
||||||
|
level_info
|
||||||
|
.data_packs
|
||||||
|
.enabled
|
||||||
|
.iter()
|
||||||
|
.any(|p| p == "minecart_improvements" || p == "file/minecart_improvements")
|
||||||
|
},
|
||||||
|
|s| s.is_feature_enabled("minecraft:minecart_improvements"),
|
||||||
|
);
|
||||||
|
|
||||||
let rules: Vec<(String, String)> = GameRule::all()
|
let rules: Vec<(String, String)> = GameRule::all()
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|rule| match rule {
|
||||||
|
GameRule::MaxMinecartSpeed => minecart_improvements_enabled,
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
.map(|rule| {
|
.map(|rule| {
|
||||||
(
|
(
|
||||||
rule.to_string(),
|
rule.to_string(),
|
||||||
|
|||||||
@ -13,6 +13,20 @@ impl JavaClient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let world = player.world();
|
||||||
|
let minecart_improvements_enabled = world.server.upgrade().map_or_else(
|
||||||
|
|| {
|
||||||
|
world
|
||||||
|
.level_info
|
||||||
|
.load()
|
||||||
|
.data_packs
|
||||||
|
.enabled
|
||||||
|
.iter()
|
||||||
|
.any(|p| p == "minecart_improvements" || p == "file/minecart_improvements")
|
||||||
|
},
|
||||||
|
|s| s.is_feature_enabled("minecraft:minecart_improvements"),
|
||||||
|
);
|
||||||
|
|
||||||
for entry in &packet.entries {
|
for entry in &packet.entries {
|
||||||
let key = entry
|
let key = entry
|
||||||
.game_rule_key
|
.game_rule_key
|
||||||
@ -23,6 +37,14 @@ impl JavaClient {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if *rule == GameRule::MaxMinecartSpeed && !minecart_improvements_enabled {
|
||||||
|
warn!(
|
||||||
|
"Player {} tried to set game rule {} which is not enabled by feature flags",
|
||||||
|
player.gameprofile.name, entry.game_rule_key
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let level_info = player.world().level_info.load();
|
let level_info = player.world().level_info.load();
|
||||||
let current_val = level_info.game_rules.get(rule);
|
let current_val = level_info.game_rules.get(rule);
|
||||||
match current_val {
|
match current_val {
|
||||||
|
|||||||
@ -564,6 +564,26 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn get_known_packs<'a>(
|
||||||
|
&self,
|
||||||
|
server_version: &'a str,
|
||||||
|
loaded_packs: &'a [crate::data::datapack::LoadedDatapack],
|
||||||
|
) -> Vec<pumpkin_protocol::KnownPack<'a>> {
|
||||||
|
self.datapack_manager
|
||||||
|
.get_known_packs(self, server_version, loaded_packs)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn get_enabled_features(&self) -> Vec<&'static str> {
|
||||||
|
self.datapack_manager.get_enabled_features(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn is_feature_enabled(&self, feature: &str) -> bool {
|
||||||
|
self.datapack_manager.is_feature_enabled(self, feature)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn save_all(&self) -> Result<(), String> {
|
pub async fn save_all(&self) -> Result<(), String> {
|
||||||
if let Err(err) = self.save_world_info() {
|
if let Err(err) = self.save_world_info() {
|
||||||
error!("Failed to save world info: {err}");
|
error!("Failed to save world info: {err}");
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use pumpkin_data::{BlockState, BlockStateId};
|
|||||||
use pumpkin_gametest::{
|
use pumpkin_gametest::{
|
||||||
BlockBasedTest, GameTestError, GameTestManager, GameTestReporter, GameTestResult,
|
BlockBasedTest, GameTestError, GameTestManager, GameTestReporter, GameTestResult,
|
||||||
GameTestRotation, GameTestRunner, GameTestSession, GameTestStructureTemplate, GameTestWorld,
|
GameTestRotation, GameTestRunner, GameTestSession, GameTestStructureTemplate, GameTestWorld,
|
||||||
|
TestType,
|
||||||
};
|
};
|
||||||
pub use pumpkin_gametest::{GameTestBatchReport, GameTestRetryOptions};
|
pub use pumpkin_gametest::{GameTestBatchReport, GameTestRetryOptions};
|
||||||
use pumpkin_nbt::NbtCompound;
|
use pumpkin_nbt::NbtCompound;
|
||||||
@ -149,6 +150,13 @@ async fn prepare_test_run(
|
|||||||
GameTestError::World(format!("Unknown test instance '{}'", request.test_id))
|
GameTestError::World(format!("Unknown test instance '{}'", request.test_id))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
if test_instance.instance_type != TestType::BlockBased {
|
||||||
|
return Err(GameTestError::World(format!(
|
||||||
|
"Test instance '{}' has unsupported type '{:?}' (only block-based tests can be executed currently)",
|
||||||
|
request.test_id, test_instance.instance_type
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
let structure = server
|
let structure = server
|
||||||
.datapack_manager
|
.datapack_manager
|
||||||
.load_structure(&test_instance.structure)
|
.load_structure(&test_instance.structure)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user