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]]
|
||||
name = "async-compression"
|
||||
version = "0.4.44"
|
||||
version = "0.4.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "515a1f282e33d55983c499d7e9e87082e81cbc32974825bf9032f928392d5844"
|
||||
checksum = "4f10dafd0c8d2e51ae9a748805777613ed0bbe17bf586b76c8311f45c020a32f"
|
||||
dependencies = [
|
||||
"compression-codecs",
|
||||
"compression-core",
|
||||
@ -398,9 +398,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.13.1"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
||||
checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@ -746,9 +746,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compression-codecs"
|
||||
version = "0.4.39"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fe67f2944eef52fc7b106b8c9450d243a88701a0c065f7f57235e76abaed7df"
|
||||
checksum = "58a6d0db8759036a783bc7c3f7a07f8cef3bf9470eb1db3bc86e8bcd1c5d0fe8"
|
||||
dependencies = [
|
||||
"compression-core",
|
||||
"flate2",
|
||||
@ -2242,7 +2242,7 @@ version = "0.11.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cc00ea907cab49550b7da656f80ebb97be1b997d931fbcd28d39734e17ce592"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
@ -2299,9 +2299,9 @@ checksum = "2f0fb0570afe1fed943c5c3d4102d5358592d8625fda6a0007fdbe65a92fba96"
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.12.1"
|
||||
version = "2.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78"
|
||||
checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
@ -2403,9 +2403,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.104"
|
||||
version = "0.3.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a"
|
||||
checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
@ -2428,7 +2428,7 @@ version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -2665,7 +2665,7 @@ version = "0.31.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
@ -2697,7 +2697,7 @@ version = "8.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
@ -2715,7 +2715,7 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2806,7 +2806,7 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3110,7 +3110,7 @@ version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
@ -3335,7 +3335,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
"base64 0.23.1",
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"bytes",
|
||||
"colored",
|
||||
"console-subscriber",
|
||||
@ -3606,7 +3606,7 @@ dependencies = [
|
||||
"aes 0.9.3",
|
||||
"async-compression",
|
||||
"base64 0.23.1",
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"bytes",
|
||||
"cesu8",
|
||||
"cfb8",
|
||||
@ -3650,7 +3650,7 @@ name = "pumpkin-world"
|
||||
version = "0.1.0+26.2-26.45"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"bytes",
|
||||
"criterion",
|
||||
"crossbeam",
|
||||
@ -3789,7 +3789,7 @@ version = "0.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3858,11 +3858,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.13.4"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
|
||||
checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"base64 0.23.1",
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@ -4299,7 +4299,7 @@ version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
@ -4318,9 +4318,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.43"
|
||||
version = "0.23.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06"
|
||||
checksum = "6725596c3f2c3a0aef021139e145d4eafe314a6623e4680ca83852b2c67ab2ba"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
@ -4402,7 +4402,7 @@ version = "18.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53f6a737db68eb1a8ccff86b584b2fc13eca6a7bb6f78ebc7c529547e3ab9684"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"cfg-if",
|
||||
"clipboard-win",
|
||||
"libc",
|
||||
@ -4485,7 +4485,7 @@ version = "3.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@ -5173,7 +5173,7 @@ version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
@ -5396,9 +5396,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.127"
|
||||
version = "0.2.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70"
|
||||
checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@ -5409,9 +5409,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.77"
|
||||
version = "0.4.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950"
|
||||
checksum = "6ef4c5d3d2cdf5c54f4231181768f5510842e350db025faf1f7163b1030ed928"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@ -5419,9 +5419,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.127"
|
||||
version = "0.2.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1"
|
||||
checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@ -5429,22 +5429,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.127"
|
||||
version = "0.2.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284"
|
||||
checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
"syn 3.0.5",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.127"
|
||||
version = "0.2.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf"
|
||||
checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -5477,7 +5477,7 @@ version = "0.258.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9a61719f93a87b16d325921e251800c4833f8fab50fa21c7de73aed50086313"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"hashbrown 0.17.1",
|
||||
"indexmap",
|
||||
"semver",
|
||||
@ -5502,7 +5502,7 @@ source = "git+https://github.com/bytecodealliance/wasmtime?rev=f6b3140dbb1d9b436
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"async-trait",
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"bumpalo",
|
||||
"bytes",
|
||||
"cc",
|
||||
@ -5699,7 +5699,7 @@ version = "49.0.0-dev"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=f6b3140dbb1d9b436ef523d14740292c956b0364#f6b3140dbb1d9b436ef523d14740292c956b0364"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"heck",
|
||||
"indexmap",
|
||||
"wit-component",
|
||||
@ -5712,7 +5712,7 @@ version = "49.0.0-dev"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime?rev=f6b3140dbb1d9b436ef523d14740292c956b0364#f6b3140dbb1d9b436ef523d14740292c956b0364"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"bytes",
|
||||
"cap-primitives",
|
||||
"futures",
|
||||
@ -5767,9 +5767,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.104"
|
||||
version = "0.3.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30"
|
||||
checksum = "9fbddc4a036f00ec4f18c83445bd3115cb306a91da554919a099d9222fe4a7f8"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@ -6129,7 +6129,7 @@ version = "0.36.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
@ -6191,7 +6191,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "481b5c47b2ecce0389b5e08a05557d6a190c9cd761773b8880a8017ee04dc7ef"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.13.1",
|
||||
"bitflags 2.13.2",
|
||||
"indexmap",
|
||||
"log",
|
||||
"serde",
|
||||
|
||||
@ -149,9 +149,9 @@ serde_json = { version = "1.0", default-features = false, features = ["std"] }
|
||||
tempfile = { version = "3.27.0", default-features = false }
|
||||
proc-macro-error2 = { version = "2", 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"] }
|
||||
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 }
|
||||
cfb8 = { version = "0.9", 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 }
|
||||
tokio-util = { version = "0.7.19", default-features = false }
|
||||
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"] }
|
||||
|
||||
sysinfo = { version = "0.39", default-features = false, features = ["system"] }
|
||||
|
||||
@ -6,6 +6,18 @@ use serde_json::Value;
|
||||
pub enum TestType {
|
||||
#[serde(rename = "minecraft:block_based")]
|
||||
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)]
|
||||
@ -71,6 +83,8 @@ pub struct GameTestDefinition {
|
||||
pub instance_type: TestType,
|
||||
pub environment: Value,
|
||||
pub structure: String,
|
||||
#[serde(default)]
|
||||
pub function: Option<String>,
|
||||
pub max_ticks: i32,
|
||||
#[serde(default)]
|
||||
pub setup_ticks: i32,
|
||||
@ -93,7 +107,13 @@ pub struct GameTestDefinition {
|
||||
impl GameTestDefinition {
|
||||
#[must_use]
|
||||
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.max_attempts > 0
|
||||
&& self.required_successes > 0
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
use pumpkin_data::packet::clientbound::config::UPDATE_ENABLED_FEATURES;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
use crate::{ClientPacket, ser::NetworkWriteExt};
|
||||
|
||||
#[java_packet(UPDATE_ENABLED_FEATURES)]
|
||||
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> {
|
||||
#[must_use]
|
||||
pub const fn new(features: &'a [ResourceLocation]) -> Self {
|
||||
pub const fn new(features: &'a [&'a str]) -> Self {
|
||||
Self { features }
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,13 @@ use self::test_loader::{
|
||||
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)]
|
||||
pub struct LoadedDatapack {
|
||||
pub id: String,
|
||||
@ -29,6 +36,7 @@ pub struct LoadedDatapack {
|
||||
pub root_path: PathBuf,
|
||||
pub recipe_count: usize,
|
||||
pub function_count: usize,
|
||||
pub known_packs: Vec<KnownPackData>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -121,7 +129,7 @@ impl DatapackManager {
|
||||
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) =
|
||||
load_pack_contents(
|
||||
@ -144,6 +152,7 @@ impl DatapackManager {
|
||||
root_path: pack_path,
|
||||
recipe_count: pack_recipe_count,
|
||||
function_count: pack_function_count,
|
||||
known_packs,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -226,6 +235,119 @@ impl DatapackManager {
|
||||
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.
|
||||
///
|
||||
/// Structure identifiers are resource locations such as
|
||||
@ -520,7 +642,7 @@ impl DatapackManager {
|
||||
.get_world_path()
|
||||
.join("datapacks")
|
||||
.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)
|
||||
} 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");
|
||||
if let Ok(content) = fs::read_to_string(mcmeta_path)
|
||||
&& 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(serde_json::Value::as_u64)
|
||||
.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(
|
||||
@ -946,4 +1108,87 @@ mod tests {
|
||||
"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]
|
||||
pub fn to_registry_entry(entry_id: String, instance: &TestInstance) -> RegistryEntryData {
|
||||
let mut nbt = NbtCompound::new();
|
||||
nbt.put_string(
|
||||
"type",
|
||||
match instance.instance_type {
|
||||
TestType::BlockBased => "minecraft:block_based",
|
||||
}
|
||||
.to_string(),
|
||||
);
|
||||
nbt.put_string("type", instance.instance_type.serialized_name().to_string());
|
||||
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_int("max_ticks", instance.max_ticks);
|
||||
nbt.put_int("setup_ticks", instance.setup_ticks);
|
||||
@ -203,4 +200,66 @@ mod tests {
|
||||
assert!(!instance.sky_access);
|
||||
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();
|
||||
|
||||
if version.supports_configuration_state() {
|
||||
self.send_packet(&CFeatureFlags::new(&["minecraft:vanilla".to_string()]))
|
||||
.await;
|
||||
if version < JavaMinecraftVersion::V_1_20_5 {
|
||||
let features = server.get_enabled_features();
|
||||
self.send_packet(&CFeatureFlags::new(&features)).await;
|
||||
}
|
||||
|
||||
let test_instance_entries =
|
||||
server.datapack_manager.get_test_instance_registry_entries();
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::{
|
||||
use core::str;
|
||||
use pumpkin_data::registry::Registry;
|
||||
use pumpkin_protocol::{
|
||||
ConnectionState, KnownPack,
|
||||
ConnectionState,
|
||||
java::{
|
||||
client::config::{CFeatureFlags, CFinishConfig, CKnownPacks, CRegistryData, CUpdateTags},
|
||||
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};
|
||||
|
||||
const BRAND_CHANNEL_PREFIX: &str = "minecraft:brand";
|
||||
|
||||
@ -69,16 +69,15 @@ impl JavaClient {
|
||||
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();
|
||||
self.send_packet(&CKnownPacks::new(&[KnownPack {
|
||||
namespace: "minecraft",
|
||||
id: "core",
|
||||
version: &version_str,
|
||||
}]))
|
||||
.await;
|
||||
let loaded_packs = server.datapack_manager.get_loaded_packs();
|
||||
let known_packs = server.get_known_packs(&version_str, &loaded_packs);
|
||||
self.send_packet(&CKnownPacks::new(&known_packs)).await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,11 +2,13 @@
|
||||
use super::*;
|
||||
|
||||
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();
|
||||
if version.supports_configuration_state() {
|
||||
self.send_packet_now(&CFeatureFlags::new(&["minecraft:vanilla".to_string()]))
|
||||
.await;
|
||||
if version < JavaMinecraftVersion::V_1_20_5 {
|
||||
let features = server.get_enabled_features();
|
||||
self.send_packet_now(&CFeatureFlags::new(&features)).await;
|
||||
}
|
||||
let registry = pumpkin_data::registry::Registry::get_synced(version);
|
||||
for reg in ®istry {
|
||||
self.send_packet_now(&CRegistryData::new(®.registry_id, ®.registry_entries))
|
||||
|
||||
@ -97,21 +97,20 @@ impl PendingConnection {
|
||||
|
||||
self.send_packet_now(&resource_pack).await;
|
||||
} else if self.version.load() >= JavaMinecraftVersion::V_1_20_5 {
|
||||
self.send_known_packs().await;
|
||||
self.send_known_packs(server).await;
|
||||
} else {
|
||||
self.handle_known_packs().await;
|
||||
self.handle_known_packs(server).await;
|
||||
}
|
||||
debug!("login acknowledged");
|
||||
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();
|
||||
self.send_packet_now(&CKnownPacks::new(&[KnownPack {
|
||||
namespace: "minecraft",
|
||||
id: "core",
|
||||
version: &version_str,
|
||||
}]))
|
||||
.await;
|
||||
let loaded_packs = server.datapack_manager.get_loaded_packs();
|
||||
let known_packs = server.get_known_packs(&version_str, &loaded_packs);
|
||||
self.send_packet_now(&CKnownPacks::new(&known_packs)).await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use arc_swap::ArcSwap;
|
||||
use pumpkin_data::translation;
|
||||
use pumpkin_protocol::{
|
||||
ConnectionState, KnownPack, Label, Link, LinkType,
|
||||
ConnectionState, Label, Link, LinkType,
|
||||
java::client::{
|
||||
config::{
|
||||
CConfigAddResourcePack, CConfigServerLinks, CFeatureFlags, CFinishConfig, CKnownPacks,
|
||||
|
||||
@ -420,7 +420,7 @@ impl PendingConnection {
|
||||
}
|
||||
}
|
||||
id if id == SKnownPacks::to_id(version) => {
|
||||
self.handle_known_packs().await;
|
||||
self.handle_known_packs(server).await;
|
||||
Ok(None)
|
||||
}
|
||||
id if id == SConfigResourcePack::to_id(version) => {
|
||||
@ -509,19 +509,33 @@ impl PendingConnection {
|
||||
match packet.response_result() {
|
||||
ResourcePackResponseResult::Downloaded
|
||||
| ResourcePackResponseResult::DownloadSuccess
|
||||
| ResourcePackResponseResult::Accepted
|
||||
| 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 => {
|
||||
if resource_config.force {
|
||||
self.kick(TextComponent::text("Required resource pack was declined"))
|
||||
.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 => {
|
||||
if resource_config.force {
|
||||
self.kick(TextComponent::text("Failed to download resource pack"))
|
||||
.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 => {
|
||||
|
||||
@ -67,9 +67,25 @@ impl JavaClient {
|
||||
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()
|
||||
.iter()
|
||||
.filter(|rule| match rule {
|
||||
GameRule::MaxMinecartSpeed => minecart_improvements_enabled,
|
||||
_ => true,
|
||||
})
|
||||
.map(|rule| {
|
||||
(
|
||||
rule.to_string(),
|
||||
|
||||
@ -13,6 +13,20 @@ impl JavaClient {
|
||||
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 {
|
||||
let key = entry
|
||||
.game_rule_key
|
||||
@ -23,6 +37,14 @@ impl JavaClient {
|
||||
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 current_val = level_info.game_rules.get(rule);
|
||||
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> {
|
||||
if let Err(err) = self.save_world_info() {
|
||||
error!("Failed to save world info: {err}");
|
||||
|
||||
@ -7,6 +7,7 @@ use pumpkin_data::{BlockState, BlockStateId};
|
||||
use pumpkin_gametest::{
|
||||
BlockBasedTest, GameTestError, GameTestManager, GameTestReporter, GameTestResult,
|
||||
GameTestRotation, GameTestRunner, GameTestSession, GameTestStructureTemplate, GameTestWorld,
|
||||
TestType,
|
||||
};
|
||||
pub use pumpkin_gametest::{GameTestBatchReport, GameTestRetryOptions};
|
||||
use pumpkin_nbt::NbtCompound;
|
||||
@ -149,6 +150,13 @@ async fn prepare_test_run(
|
||||
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
|
||||
.datapack_manager
|
||||
.load_structure(&test_instance.structure)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user