ci: remove macos-15-intel
This commit is contained in:
parent
afbe839dea
commit
3103e97e18
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-24.04-arm
|
- os: ubuntu-26.04-arm
|
||||||
platform: linux/arm64
|
platform: linux/arm64
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
platform: linux/amd64
|
platform: linux/amd64
|
||||||
|
|||||||
4
.github/workflows/rust.yml
vendored
4
.github/workflows/rust.yml
vendored
@ -82,11 +82,10 @@ jobs:
|
|||||||
os:
|
os:
|
||||||
[
|
[
|
||||||
ubuntu-latest,
|
ubuntu-latest,
|
||||||
ubuntu-24.04-arm,
|
ubuntu-26.04-arm,
|
||||||
windows-latest,
|
windows-latest,
|
||||||
windows-11-arm,
|
windows-11-arm,
|
||||||
macos-latest,
|
macos-latest,
|
||||||
macos-15-intel,
|
|
||||||
]
|
]
|
||||||
toolchain:
|
toolchain:
|
||||||
- stable
|
- stable
|
||||||
@ -114,7 +113,6 @@ jobs:
|
|||||||
windows-latest,
|
windows-latest,
|
||||||
windows-11-arm,
|
windows-11-arm,
|
||||||
macos-latest,
|
macos-latest,
|
||||||
macos-15-intel,
|
|
||||||
]
|
]
|
||||||
toolchain:
|
toolchain:
|
||||||
- stable
|
- stable
|
||||||
|
|||||||
772
Cargo.lock
generated
772
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
19
Cargo.toml
@ -119,7 +119,7 @@ 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.42", default-features = false }
|
async-compression = { version = "0.4.42", default-features = false }
|
||||||
base64 = { version = "0.22.1", default-features = false, features = ["std"] }
|
base64 = { version = "0.23.0", default-features = false, features = ["std"] }
|
||||||
bitflags = { version = "2.13.1", default-features = false, features = ["std"] }
|
bitflags = { version = "2.13.1", 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 }
|
||||||
@ -133,7 +133,6 @@ crossfire = { version = "3.1.19", default-features = false, features = ["compat"
|
|||||||
crypto-bigint = { version = "0.7.5", default-features = false }
|
crypto-bigint = { version = "0.7.5", default-features = false }
|
||||||
dashmap = { version = "6.2", default-features = false }
|
dashmap = { version = "6.2", default-features = false }
|
||||||
ecdsa = { version = "0.17.0", default-features = false, features = ["std"] }
|
ecdsa = { version = "0.17.0", default-features = false, features = ["std"] }
|
||||||
either = { version = "1.16.0", default-features = false }
|
|
||||||
enum_dispatch = { version = "0.3.13", default-features = false }
|
enum_dispatch = { version = "0.3.13", default-features = false }
|
||||||
flate2 = { version = "1.1.9", default-features = false, features = ["rust_backend"] }
|
flate2 = { version = "1.1.9", default-features = false, features = ["rust_backend"] }
|
||||||
heck = { version = "0.5", default-features = false }
|
heck = { version = "0.5", default-features = false }
|
||||||
@ -145,7 +144,7 @@ lru = { version = "0.18.1", default-features = false }
|
|||||||
lz4-java-wrc = { version = "0.2.0", default-features = false, features = ["lz4_flex"] }
|
lz4-java-wrc = { version = "0.2.0", default-features = false, features = ["lz4_flex"] }
|
||||||
md5 = { version = "0.8", default-features = false }
|
md5 = { version = "0.8", default-features = false }
|
||||||
num-bigint = { version = "0.5", default-features = false, features = ["std"] }
|
num-bigint = { version = "0.5", default-features = false, features = ["std"] }
|
||||||
num-derive = { version = "0.4", default-features = false }
|
num-derive = { version = "0.5", default-features = false }
|
||||||
num-traits = { version = "0.2", default-features = false, features = ["std"] }
|
num-traits = { version = "0.2", default-features = false, features = ["std"] }
|
||||||
p384 = { version = "0.14.0", default-features = false, features = ["std", "arithmetic", "pkcs8", "ecdh"] }
|
p384 = { version = "0.14.0", default-features = false, features = ["std", "arithmetic", "pkcs8", "ecdh"] }
|
||||||
phf = { version = "0.14.0", default-features = false, features = ["std"] }
|
phf = { version = "0.14.0", default-features = false, features = ["std"] }
|
||||||
@ -178,11 +177,9 @@ tracing-subscriber = { version = "0.3.23", default-features = false, features =
|
|||||||
"std",
|
"std",
|
||||||
] }
|
] }
|
||||||
slotmap = { version = "1.1", default-features = false, features = ["std"] }
|
slotmap = { version = "1.1", default-features = false, features = ["std"] }
|
||||||
temp-dir = { version = "0.2.0", default-features = false }
|
|
||||||
thread_local = { version = "1.1.10", default-features = false }
|
|
||||||
time = { version = "0.3", default-features = false, features = ["std"] }
|
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.18", 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"] }
|
||||||
ureq = { version = "3.3.0", default-features = false, features = ["rustls"] }
|
ureq = { version = "3.3.0", default-features = false, features = ["rustls"] }
|
||||||
notify = { version = "8.2.0", default-features = false, features = ["macos_fsevent"] }
|
notify = { version = "8.2.0", default-features = false, features = ["macos_fsevent"] }
|
||||||
@ -192,12 +189,12 @@ rustc_version_runtime = { version = "0.3", default-features = false }
|
|||||||
ordered-float = { version = "5.3", default-features = false, features = ["std"] }
|
ordered-float = { version = "5.3", default-features = false, features = ["std"] }
|
||||||
xxhash-rust = { version = "0.8", default-features = false, features = ["xxh64"] }
|
xxhash-rust = { version = "0.8", default-features = false, features = ["xxh64"] }
|
||||||
|
|
||||||
wasmtime = { version = "46.0", default-features = false, features = ["runtime", "component-model", "async", "cache", "cranelift", "gc", "gc-drc", "threads", "std"] }
|
wasmtime = { version = "47.0", default-features = false, features = ["runtime", "component-model", "async", "cache", "cranelift", "gc", "gc-drc", "threads", "std"] }
|
||||||
wasmtime-wasi = { version = "46.0", default-features = false, features = ["p2"] }
|
wasmtime-wasi = { version = "47.0", default-features = false, features = ["p2"] }
|
||||||
wasmtime-wasi-http = { version = "46.0", default-features = false, features = ["p2", "default-send-request"] }
|
wasmtime-wasi-http = { version = "47.0", default-features = false, features = ["p2", "default-send-request"] }
|
||||||
# needed for interacting with wasmtime-wasi-http - keep in sync
|
# needed for interacting with wasmtime-wasi-http - keep in sync
|
||||||
hyper = { version = "^1.10", default-features = false }
|
hyper = { version = "^1.11", default-features = false }
|
||||||
wit-bindgen = { version = "0.59", default-features = false, features = ["macros"] }
|
wit-bindgen = { version = "0.60", default-features = false, features = ["macros"] }
|
||||||
|
|
||||||
postcard = { version = "1.1", default-features = false, features = ["alloc"] }
|
postcard = { version = "1.1", default-features = false, features = ["alloc"] }
|
||||||
tracing-serde-structured = { version = "0.4", default-features = false }
|
tracing-serde-structured = { version = "0.4", default-features = false }
|
||||||
|
|||||||
@ -8,7 +8,6 @@ license.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
either.workspace = true
|
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|||||||
@ -1,5 +1,34 @@
|
|||||||
use crate::{DataResult, Decode, DynamicOps, Encode};
|
use crate::{DataResult, Decode, DynamicOps, Encode};
|
||||||
use either::Either;
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub enum Either<L, R> {
|
||||||
|
Left(L),
|
||||||
|
Right(R),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, R> Either<L, R> {
|
||||||
|
pub const fn is_left(&self) -> bool {
|
||||||
|
matches!(self, Self::Left(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn is_right(&self) -> bool {
|
||||||
|
matches!(self, Self::Right(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn left(self) -> Option<L> {
|
||||||
|
match self {
|
||||||
|
Self::Left(l) => Some(l),
|
||||||
|
Self::Right(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right(self) -> Option<R> {
|
||||||
|
match self {
|
||||||
|
Self::Left(_) => None,
|
||||||
|
Self::Right(r) => Some(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<L: Encode, R: Encode> Encode for Either<L, R> {
|
impl<L: Encode, R: Encode> Encode for Either<L, R> {
|
||||||
fn encode<O: DynamicOps>(&self, ops: &'static O, prefix: O::Value) -> DataResult<O::Value> {
|
fn encode<O: DynamicOps>(&self, ops: &'static O, prefix: O::Value) -> DataResult<O::Value> {
|
||||||
@ -46,9 +75,9 @@ impl<L: Decode, R: Decode> Decode for Either<L, R> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use super::Either;
|
||||||
use crate::json_ops::JsonOps;
|
use crate::json_ops::JsonOps;
|
||||||
use crate::{assert_decode, assert_encode_success};
|
use crate::{assert_decode, assert_encode_success};
|
||||||
use either::Either;
|
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
mod either;
|
pub mod either;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod map;
|
pub mod map;
|
||||||
pub mod optional_field;
|
pub mod optional_field;
|
||||||
|
|||||||
@ -21,6 +21,7 @@ pub use number::Number;
|
|||||||
pub use crate::codec::Decode;
|
pub use crate::codec::Decode;
|
||||||
pub use crate::codec::Encode;
|
pub use crate::codec::Encode;
|
||||||
|
|
||||||
|
pub use crate::codec::either::Either;
|
||||||
pub use crate::codec::primitive::ByteBuffer;
|
pub use crate::codec::primitive::ByteBuffer;
|
||||||
pub use crate::codec::primitive::IntStream;
|
pub use crate::codec::primitive::IntStream;
|
||||||
pub use crate::codec::primitive::LongStream;
|
pub use crate::codec::primitive::LongStream;
|
||||||
|
|||||||
104
pumpkin-codegen/Cargo.lock
generated
104
pumpkin-codegen/Cargo.lock
generated
@ -32,6 +32,12 @@ version = "0.22.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b25655df2c3cdd83c5e5b293b88acd880332b2ddadd7c30ac43144fdc0033da9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64ct"
|
name = "base64ct"
|
||||||
version = "1.8.3"
|
version = "1.8.3"
|
||||||
@ -40,9 +46,9 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.13.0"
|
version = "2.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
@ -324,7 +330,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -584,13 +590,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.4.2"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
checksum = "e4e98dc3b890f6c23a0f9d3d491a2823d0dea0fa656302a13dd225fa924112a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 3.0.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -667,7 +673,7 @@ dependencies = [
|
|||||||
"pest_meta",
|
"pest_meta",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -723,7 +729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -788,7 +794,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_json5",
|
"serde_json5",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"syn",
|
"syn 3.0.2",
|
||||||
"wit-encoder",
|
"wit-encoder",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -800,6 +806,7 @@ dependencies = [
|
|||||||
"cesu8",
|
"cesu8",
|
||||||
"flate2",
|
"flate2",
|
||||||
"pumpkin-codecs",
|
"pumpkin-codecs",
|
||||||
|
"rustc-hash",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -810,7 +817,7 @@ dependencies = [
|
|||||||
name = "pumpkin-util"
|
name = "pumpkin-util"
|
||||||
version = "0.1.0-dev+26.2"
|
version = "0.1.0-dev+26.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.23.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
"colored",
|
"colored",
|
||||||
"crypto-bigint",
|
"crypto-bigint",
|
||||||
@ -828,7 +835,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2 0.11.0",
|
"sha2 0.11.0",
|
||||||
"syn",
|
"syn 3.0.2",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"ureq",
|
"ureq",
|
||||||
@ -918,6 +925,12 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.39"
|
version = "0.23.39"
|
||||||
@ -985,9 +998,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.229"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
@ -995,29 +1008,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_core"
|
name = "serde_core"
|
||||||
version = "1.0.228"
|
version = "1.0.229"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.228"
|
version = "1.0.229"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 3.0.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.150"
|
version = "1.0.151"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"itoa",
|
"itoa",
|
||||||
@ -1046,7 +1059,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1130,6 +1143,17 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "3.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a207d6d6a2b7fc470b80443726053f18a2481b7e1eee970597051596567987a3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.18"
|
version = "2.0.18"
|
||||||
@ -1147,14 +1171,14 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.52.0"
|
version = "1.53.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776"
|
checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
@ -1178,7 +1202,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1226,7 +1250,7 @@ version = "3.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0"
|
checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"log",
|
"log",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rustls",
|
"rustls",
|
||||||
@ -1242,7 +1266,7 @@ version = "0.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c"
|
checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"http",
|
"http",
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
@ -1256,9 +1280,9 @@ checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.23.0"
|
version = "1.24.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9"
|
checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.4.1",
|
"getrandom 0.4.1",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@ -1329,7 +1353,7 @@ dependencies = [
|
|||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1378,9 +1402,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmparser"
|
name = "wasmparser"
|
||||||
version = "0.253.0"
|
version = "0.254.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19db11f87d2486580e1e8b6f494c54df7e0566b87d0b599db843c24019667339"
|
checksum = "d5769a29f799fbab136aaf65b4fe5384cd7d93fe6fc9ba0dcb6c8382a1f16e27"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@ -1514,7 +1538,7 @@ dependencies = [
|
|||||||
"heck",
|
"heck",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"prettyplease",
|
"prettyplease",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
"wasm-metadata",
|
"wasm-metadata",
|
||||||
"wit-bindgen-core",
|
"wit-bindgen-core",
|
||||||
"wit-component",
|
"wit-component",
|
||||||
@ -1530,7 +1554,7 @@ dependencies = [
|
|||||||
"prettyplease",
|
"prettyplease",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
"wit-bindgen-core",
|
"wit-bindgen-core",
|
||||||
"wit-bindgen-rust",
|
"wit-bindgen-rust",
|
||||||
]
|
]
|
||||||
@ -1556,15 +1580,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-encoder"
|
name = "wit-encoder"
|
||||||
version = "0.253.0"
|
version = "0.254.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "63b783601ee9357f78aaa12bc5cfd0cd0a2fb3d637de1f35604e14eef52ab97d"
|
checksum = "c565f1f3dcf3b659d6c15052739e35937227590d7dded3d3ce274f7bd9c34d93"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"id-arena",
|
"id-arena",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"wit-parser 0.253.0",
|
"wit-parser 0.254.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1587,9 +1611,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-parser"
|
name = "wit-parser"
|
||||||
version = "0.253.0"
|
version = "0.254.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d997b8e5920fcbeec742b58e583325d6419a6aca617ae8075c406a61c65ba8a"
|
checksum = "1655131e4f7d3f0cb141f6eca71315ca40eff0f3d4de7cff0a82bacedd8c89b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"hashbrown 0.17.1",
|
"hashbrown 0.17.1",
|
||||||
@ -1601,7 +1625,7 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
"wasmparser 0.253.0",
|
"wasmparser 0.254.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@ -16,13 +16,13 @@ serde_repr = { version = "0.1" }
|
|||||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||||
serde_json5 = "0.2"
|
serde_json5 = "0.2"
|
||||||
|
|
||||||
wit-encoder = "0.253.0"
|
wit-encoder = "0.254.0"
|
||||||
semver = "1.0"
|
semver = "1.0"
|
||||||
rayon = "1.12.0"
|
rayon = "1.12.0"
|
||||||
|
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
syn = { version = "2.0", features = ["full", "extra-traits"] }
|
syn = { version = "3.0", features = ["full", "extra-traits"] }
|
||||||
|
|
||||||
pumpkin-util = { path = "../pumpkin-util", features = ["codegen"] }
|
pumpkin-util = { path = "../pumpkin-util", features = ["codegen"] }
|
||||||
pumpkin-nbt = { path = "../pumpkin-nbt" }
|
pumpkin-nbt = { path = "../pumpkin-nbt" }
|
||||||
|
|||||||
@ -765,7 +765,9 @@ impl ToTokens for ItemComponents {
|
|||||||
tokens.extend(quote! { (EnchantmentGlintOverride, &EnchantmentGlintOverrideImpl), });
|
tokens.extend(quote! { (EnchantmentGlintOverride, &EnchantmentGlintOverrideImpl), });
|
||||||
}
|
}
|
||||||
if self.enchantments.is_some() {
|
if self.enchantments.is_some() {
|
||||||
tokens.extend(quote! { (Enchantments, &EnchantmentsImpl { enchantment: Cow::Borrowed(&[]) }), });
|
tokens.extend(
|
||||||
|
quote! { (Enchantments, &EnchantmentsImpl { enchantment: Cow::Borrowed(&[]) }), },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if self.entity_data.is_some() {
|
if self.entity_data.is_some() {
|
||||||
tokens.extend(quote! { (EntityData, &EntityDataImpl), });
|
tokens.extend(quote! { (EntityData, &EntityDataImpl), });
|
||||||
@ -793,7 +795,8 @@ impl ToTokens for ItemComponents {
|
|||||||
}
|
}
|
||||||
if let Some(model) = &self.item_model {
|
if let Some(model) = &self.item_model {
|
||||||
let model_lit = LitStr::new(model, Span::call_site());
|
let model_lit = LitStr::new(model, Span::call_site());
|
||||||
tokens.extend(quote! { (ItemModel, &ItemModelImpl { id: Cow::Borrowed(#model_lit) }), });
|
tokens
|
||||||
|
.extend(quote! { (ItemModel, &ItemModelImpl { id: Cow::Borrowed(#model_lit) }), });
|
||||||
}
|
}
|
||||||
if self.kinetic_weapon.is_some() {
|
if self.kinetic_weapon.is_some() {
|
||||||
tokens.extend(quote! { (KineticWeapon, &KineticWeaponImpl), });
|
tokens.extend(quote! { (KineticWeapon, &KineticWeaponImpl), });
|
||||||
@ -870,7 +873,9 @@ impl ToTokens for ItemComponents {
|
|||||||
tokens.extend(quote! { (UseRemainder, &UseRemainderImpl), });
|
tokens.extend(quote! { (UseRemainder, &UseRemainderImpl), });
|
||||||
}
|
}
|
||||||
if self.writable_book_content.is_some() {
|
if self.writable_book_content.is_some() {
|
||||||
tokens.extend(quote! { (WritableBookContent, &WritableBookContentImpl { pages: Vec::new() }), });
|
tokens.extend(
|
||||||
|
quote! { (WritableBookContent, &WritableBookContentImpl { pages: Vec::new() }), },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -538,7 +538,9 @@ impl ToTokens for LootConditionStruct {
|
|||||||
.and_then(|p| p.entity_type.as_ref())
|
.and_then(|p| p.entity_type.as_ref())
|
||||||
.map(|t| match t {
|
.map(|t| match t {
|
||||||
StringOrVec::String(s) => quote! { Some(#s) },
|
StringOrVec::String(s) => quote! { Some(#s) },
|
||||||
StringOrVec::Vec(v) => v.first().map_or(quote! { None }, |s| quote! { Some(#s) }),
|
StringOrVec::Vec(v) => {
|
||||||
|
v.first().map_or(quote! { None }, |s| quote! { Some(#s) })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(quote! { None });
|
.unwrap_or(quote! { None });
|
||||||
|
|
||||||
@ -559,7 +561,9 @@ impl ToTokens for LootConditionStruct {
|
|||||||
.and_then(|ench| ench.enchantments.as_ref())
|
.and_then(|ench| ench.enchantments.as_ref())
|
||||||
.map(|t| match t {
|
.map(|t| match t {
|
||||||
StringOrVec::String(s) => quote! { Some(#s) },
|
StringOrVec::String(s) => quote! { Some(#s) },
|
||||||
StringOrVec::Vec(v) => v.first().map_or(quote! { None }, |s| quote! { Some(#s) }),
|
StringOrVec::Vec(v) => {
|
||||||
|
v.first().map_or(quote! { None }, |s| quote! { Some(#s) })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(quote! { None });
|
.unwrap_or(quote! { None });
|
||||||
|
|
||||||
@ -613,7 +617,9 @@ impl ToTokens for LootConditionStruct {
|
|||||||
.and_then(|e| e.entity_type.as_ref())
|
.and_then(|e| e.entity_type.as_ref())
|
||||||
.map(|t| match t {
|
.map(|t| match t {
|
||||||
StringOrVec::String(s) => quote! { Some(#s) },
|
StringOrVec::String(s) => quote! { Some(#s) },
|
||||||
StringOrVec::Vec(v) => v.first().map_or(quote! { None }, |s| quote! { Some(#s) }),
|
StringOrVec::Vec(v) => {
|
||||||
|
v.first().map_or(quote! { None }, |s| quote! { Some(#s) })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(quote! { None });
|
.unwrap_or(quote! { None });
|
||||||
|
|
||||||
@ -623,7 +629,9 @@ impl ToTokens for LootConditionStruct {
|
|||||||
.and_then(|e| e.entity_type.as_ref())
|
.and_then(|e| e.entity_type.as_ref())
|
||||||
.map(|t| match t {
|
.map(|t| match t {
|
||||||
StringOrVec::String(s) => quote! { Some(#s) },
|
StringOrVec::String(s) => quote! { Some(#s) },
|
||||||
StringOrVec::Vec(v) => v.first().map_or(quote! { None }, |s| quote! { Some(#s) }),
|
StringOrVec::Vec(v) => {
|
||||||
|
v.first().map_or(quote! { None }, |s| quote! { Some(#s) })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(quote! { None });
|
.unwrap_or(quote! { None });
|
||||||
|
|
||||||
@ -643,7 +651,9 @@ impl ToTokens for LootConditionStruct {
|
|||||||
.and_then(|p| p.biome.as_ref())
|
.and_then(|p| p.biome.as_ref())
|
||||||
.map(|b| match b {
|
.map(|b| match b {
|
||||||
StringOrVec::String(s) => quote! { Some(#s) },
|
StringOrVec::String(s) => quote! { Some(#s) },
|
||||||
StringOrVec::Vec(v) => v.first().map_or(quote! { None }, |s| quote! { Some(#s) }),
|
StringOrVec::Vec(v) => {
|
||||||
|
v.first().map_or(quote! { None }, |s| quote! { Some(#s) })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(quote! { None });
|
.unwrap_or(quote! { None });
|
||||||
quote! { LootCondition::LocationCheck { offset_x: #ox, offset_y: #oy, offset_z: #oz, expected_biome: #expected_biome } }
|
quote! { LootCondition::LocationCheck { offset_x: #ox, offset_y: #oy, offset_z: #oz, expected_biome: #expected_biome } }
|
||||||
|
|||||||
@ -165,7 +165,7 @@ fn collect_fields(
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wit_name(name: String,state: &str) -> String{
|
fn wit_name(name: String, state: &str) -> String {
|
||||||
if state == "play" {
|
if state == "play" {
|
||||||
name.to_kebab_case()
|
name.to_kebab_case()
|
||||||
} else {
|
} else {
|
||||||
@ -180,7 +180,7 @@ fn process_struct(
|
|||||||
variant: &mut Variant,
|
variant: &mut Variant,
|
||||||
defined_cases: &mut HashSet<String>,
|
defined_cases: &mut HashSet<String>,
|
||||||
) {
|
) {
|
||||||
let wit_name = wit_name(s.ident.to_string(),state);
|
let wit_name = wit_name(s.ident.to_string(), state);
|
||||||
if !defined_cases.insert(wit_name.clone()) {
|
if !defined_cases.insert(wit_name.clone()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -199,7 +199,7 @@ fn process_enum(
|
|||||||
variant: &mut Variant,
|
variant: &mut Variant,
|
||||||
defined_cases: &mut HashSet<String>,
|
defined_cases: &mut HashSet<String>,
|
||||||
) {
|
) {
|
||||||
let enum_wit_name = wit_name(e.ident.to_string(),state);
|
let enum_wit_name = wit_name(e.ident.to_string(), state);
|
||||||
if !defined_cases.insert(enum_wit_name.clone()) {
|
if !defined_cases.insert(enum_wit_name.clone()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ pub fn build_java_mapping() -> String {
|
|||||||
output.push_str("}\n\n");
|
output.push_str("}\n\n");
|
||||||
|
|
||||||
output.push_str("#[must_use]\n");
|
output.push_str("#[must_use]\n");
|
||||||
output.push_str("pub fn deserialize_java_serverbound_packet(id: i32, payload: &[u8], version: JavaMinecraftVersion) -> Option<ServerboundPacket> {\n");
|
output.push_str("pub fn deserialize_java_serverbound_packet(id: i32, mut payload: &[u8], version: JavaMinecraftVersion) -> Option<ServerboundPacket> {\n");
|
||||||
output.push_str(" match id {\n");
|
output.push_str(" match id {\n");
|
||||||
|
|
||||||
for state in server_states {
|
for state in server_states {
|
||||||
@ -715,7 +715,7 @@ fn emit_struct_output(
|
|||||||
));
|
));
|
||||||
output.push_str(" use pumpkin_protocol::ServerPacket;\n");
|
output.push_str(" use pumpkin_protocol::ServerPacket;\n");
|
||||||
output.push_str(&format!(
|
output.push_str(&format!(
|
||||||
" let p = <{}::{} as pumpkin_protocol::ServerPacket>::read(&mut Cursor::new(payload), &version).ok()?;\n",
|
" let p = <{}::{} as pumpkin_protocol::ServerPacket>::read(&mut payload, &version).ok()?;\n",
|
||||||
rust_path_prefix, struct_name
|
rust_path_prefix, struct_name
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
@ -846,7 +846,7 @@ fn process_enum(
|
|||||||
));
|
));
|
||||||
output.push_str(" use pumpkin_protocol::ServerPacket;\n");
|
output.push_str(" use pumpkin_protocol::ServerPacket;\n");
|
||||||
output.push_str(&format!(
|
output.push_str(&format!(
|
||||||
" let p = <{}::{} as pumpkin_protocol::ServerPacket>::read(&mut Cursor::new(payload), &version).ok()?;\n",
|
" let p = <{}::{} as pumpkin_protocol::ServerPacket>::read(&mut payload, &version).ok()?;\n",
|
||||||
rust_path_prefix, enum_name
|
rust_path_prefix, enum_name
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -106,7 +106,7 @@ pub fn bench_nbt(c: &mut Criterion) {
|
|||||||
|
|
||||||
c.bench_function("nbt/java/deserialize/raw", |b| {
|
c.bench_function("nbt/java/deserialize/raw", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut cursor = Cursor::new(&wrapper_bytes_java);
|
let mut cursor = Cursor::new(&wrapper_bytes_java[..]);
|
||||||
let mut reader = deserializer::NbtReadHelperJava::new(&mut cursor);
|
let mut reader = deserializer::NbtReadHelperJava::new(&mut cursor);
|
||||||
Nbt::read(&mut reader).unwrap();
|
Nbt::read(&mut reader).unwrap();
|
||||||
});
|
});
|
||||||
@ -135,7 +135,7 @@ pub fn bench_nbt(c: &mut Criterion) {
|
|||||||
|
|
||||||
c.bench_function("nbt/bedrock/deserialize/raw", |b| {
|
c.bench_function("nbt/bedrock/deserialize/raw", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut cursor = Cursor::new(&wrapper_bytes_bedrock);
|
let mut cursor = Cursor::new(&wrapper_bytes_bedrock[..]);
|
||||||
let mut reader = deserializer::NbtReadHelperBedrock::new(&mut cursor);
|
let mut reader = deserializer::NbtReadHelperBedrock::new(&mut cursor);
|
||||||
Nbt::read(&mut reader).unwrap();
|
Nbt::read(&mut reader).unwrap();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -43,7 +43,7 @@ impl NbtCompound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip_content<R: NbtReadHelper>(reader: &mut R) -> Result<(), Error> {
|
pub fn skip_content<'a, R: NbtReadHelper<'a>>(reader: &mut R) -> Result<(), Error> {
|
||||||
loop {
|
loop {
|
||||||
let tag_id = match reader.get_u8() {
|
let tag_id = match reader.get_u8() {
|
||||||
Ok(id) => id,
|
Ok(id) => id,
|
||||||
@ -64,7 +64,7 @@ impl NbtCompound {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize_content<R: NbtReadHelper>(reader: &mut R) -> Result<Self, Error> {
|
pub fn deserialize_content<'a, R: NbtReadHelper<'a>>(reader: &mut R) -> Result<Self, Error> {
|
||||||
let mut compound = Self::new();
|
let mut compound = Self::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::io::{Seek, SeekFrom};
|
use std::io::{Cursor, Seek, SeekFrom};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BYTE_ARRAY_ID, BYTE_ID, COMPOUND_ID, END_ID, Error, INT_ARRAY_ID, INT_ID, LIST_ID,
|
BYTE_ARRAY_ID, BYTE_ID, COMPOUND_ID, END_ID, Error, INT_ARRAY_ID, INT_ID, LIST_ID,
|
||||||
@ -25,16 +26,178 @@ pub(super) fn set_curr_visitor_seq_list_id(tag: Option<u8>) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NbtReadHelper {
|
pub trait NbtDataSource<'a> {
|
||||||
type Reader: Read + Seek;
|
fn read_u8(&mut self) -> Result<u8>;
|
||||||
|
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<()>;
|
||||||
|
fn seek_relative(&mut self, offset: i64) -> Result<()>;
|
||||||
|
fn read_string(&mut self, len: usize) -> Result<Cow<'a, str>>;
|
||||||
|
fn read_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NbtStreamReader<R>(pub R);
|
||||||
|
|
||||||
|
impl<'a, R: Read + Seek> NbtDataSource<'a> for NbtStreamReader<R> {
|
||||||
|
fn read_u8(&mut self) -> Result<u8> {
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
|
self.0.read_exact(&mut buf).map_err(Error::Incomplete)?;
|
||||||
|
Ok(buf[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<()> {
|
||||||
|
self.0.read_exact(buf).map_err(Error::Incomplete)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seek_relative(&mut self, offset: i64) -> Result<()> {
|
||||||
|
self.0
|
||||||
|
.seek(SeekFrom::Current(offset))
|
||||||
|
.map_err(Error::Incomplete)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_string(&mut self, len: usize) -> Result<Cow<'a, str>> {
|
||||||
|
let mut buf = vec![0u8; len];
|
||||||
|
self.0.read_exact(&mut buf).map_err(Error::Incomplete)?;
|
||||||
|
let string = cesu8::from_java_cesu8(&buf).map_err(|_| Error::Cesu8DecodingError)?;
|
||||||
|
Ok(Cow::Owned(string.into_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>> {
|
||||||
|
let mut buf = vec![0u8; len];
|
||||||
|
self.0.read_exact(&mut buf).map_err(Error::Incomplete)?;
|
||||||
|
let i8_buf: Vec<i8> = buf.into_iter().map(|b| b as i8).collect();
|
||||||
|
Ok(Cow::Owned(i8_buf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> NbtDataSource<'a> for Cursor<&'a [u8]> {
|
||||||
|
fn read_u8(&mut self) -> Result<u8> {
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
|
self.read_exact(&mut buf).map_err(Error::Incomplete)?;
|
||||||
|
Ok(buf[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<()> {
|
||||||
|
self.read_exact(buf).map_err(Error::Incomplete)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seek_relative(&mut self, offset: i64) -> Result<()> {
|
||||||
|
self.seek(SeekFrom::Current(offset))
|
||||||
|
.map_err(Error::Incomplete)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_string(&mut self, len: usize) -> Result<Cow<'a, str>> {
|
||||||
|
let pos = self.position() as usize;
|
||||||
|
let data_len = self.get_ref().len();
|
||||||
|
if pos + len > data_len {
|
||||||
|
return Err(Error::Incomplete(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::UnexpectedEof,
|
||||||
|
"unexpected EOF",
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
self.set_position((pos + len) as u64);
|
||||||
|
let data = self.get_ref();
|
||||||
|
let slice = &data[pos..pos + len];
|
||||||
|
if let Ok(s) = std::str::from_utf8(slice) {
|
||||||
|
Ok(Cow::Borrowed(s))
|
||||||
|
} else {
|
||||||
|
let string = cesu8::from_java_cesu8(slice).map_err(|_| Error::Cesu8DecodingError)?;
|
||||||
|
Ok(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>> {
|
||||||
|
let pos = self.position() as usize;
|
||||||
|
let data_len = self.get_ref().len();
|
||||||
|
if pos + len > data_len {
|
||||||
|
return Err(Error::Incomplete(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::UnexpectedEof,
|
||||||
|
"unexpected EOF",
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
self.set_position((pos + len) as u64);
|
||||||
|
let data = self.get_ref();
|
||||||
|
let slice = &data[pos..pos + len];
|
||||||
|
let i8_slice = unsafe { std::slice::from_raw_parts(slice.as_ptr().cast::<i8>(), len) };
|
||||||
|
Ok(Cow::Borrowed(i8_slice))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, S: NbtDataSource<'a> + ?Sized> NbtDataSource<'a> for &mut S {
|
||||||
|
fn read_u8(&mut self) -> Result<u8> {
|
||||||
|
(**self).read_u8()
|
||||||
|
}
|
||||||
|
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<()> {
|
||||||
|
(**self).read_bytes(buf)
|
||||||
|
}
|
||||||
|
fn seek_relative(&mut self, offset: i64) -> Result<()> {
|
||||||
|
(**self).seek_relative(offset)
|
||||||
|
}
|
||||||
|
fn read_string(&mut self, len: usize) -> Result<Cow<'a, str>> {
|
||||||
|
(**self).read_string(len)
|
||||||
|
}
|
||||||
|
fn read_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>> {
|
||||||
|
(**self).read_byte_array(len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> NbtDataSource<'a> for Cursor<Vec<u8>> {
|
||||||
|
fn read_u8(&mut self) -> Result<u8> {
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
|
self.read_exact(&mut buf).map_err(Error::Incomplete)?;
|
||||||
|
Ok(buf[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<()> {
|
||||||
|
self.read_exact(buf).map_err(Error::Incomplete)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seek_relative(&mut self, offset: i64) -> Result<()> {
|
||||||
|
self.seek(SeekFrom::Current(offset))
|
||||||
|
.map_err(Error::Incomplete)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_string(&mut self, len: usize) -> Result<Cow<'a, str>> {
|
||||||
|
let pos = self.position() as usize;
|
||||||
|
let data_len = self.get_ref().len();
|
||||||
|
if pos + len > data_len {
|
||||||
|
return Err(Error::Incomplete(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::UnexpectedEof,
|
||||||
|
"unexpected EOF",
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
self.set_position((pos + len) as u64);
|
||||||
|
let data = self.get_ref();
|
||||||
|
let slice = &data[pos..pos + len];
|
||||||
|
let string = cesu8::from_java_cesu8(slice).map_err(|_| Error::Cesu8DecodingError)?;
|
||||||
|
Ok(Cow::Owned(string.into_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>> {
|
||||||
|
let pos = self.position() as usize;
|
||||||
|
let data_len = self.get_ref().len();
|
||||||
|
if pos + len > data_len {
|
||||||
|
return Err(Error::Incomplete(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::UnexpectedEof,
|
||||||
|
"unexpected EOF",
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
self.set_position((pos + len) as u64);
|
||||||
|
let data = self.get_ref();
|
||||||
|
let slice = &data[pos..pos + len];
|
||||||
|
let i8_slice = unsafe { std::slice::from_raw_parts(slice.as_ptr().cast::<i8>(), len) };
|
||||||
|
Ok(Cow::Owned(i8_slice.to_vec()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait NbtReadHelper<'a> {
|
||||||
|
type Reader: NbtDataSource<'a>;
|
||||||
|
|
||||||
fn reader(&mut self) -> &mut Self::Reader;
|
fn reader(&mut self) -> &mut Self::Reader;
|
||||||
|
|
||||||
fn skip_bytes(&mut self, count: i64) -> Result<()> {
|
fn skip_bytes(&mut self, count: i64) -> Result<()> {
|
||||||
self.reader()
|
self.reader().seek_relative(count)
|
||||||
.seek(SeekFrom::Current(count))
|
|
||||||
.map_err(Error::Incomplete)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
fn skip_u8(&mut self) -> Result<()> {
|
fn skip_u8(&mut self) -> Result<()> {
|
||||||
self.skip_bytes(1)
|
self.skip_bytes(1)
|
||||||
@ -66,63 +229,42 @@ pub trait NbtReadHelper {
|
|||||||
fn get_i64(&mut self) -> Result<i64>;
|
fn get_i64(&mut self) -> Result<i64>;
|
||||||
fn get_f32(&mut self) -> Result<f32>;
|
fn get_f32(&mut self) -> Result<f32>;
|
||||||
fn get_f64(&mut self) -> Result<f64>;
|
fn get_f64(&mut self) -> Result<f64>;
|
||||||
fn get_string(&mut self) -> Result<String>;
|
fn get_string(&mut self) -> Result<Cow<'a, str>>;
|
||||||
|
fn get_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! define_get_number_be {
|
pub struct NbtReadHelperJava<D> {
|
||||||
($name:ident, $type:ty) => {
|
reader: D,
|
||||||
fn $name(&mut self) -> Result<$type> {
|
|
||||||
let mut buf = [0u8; std::mem::size_of::<$type>()];
|
|
||||||
self.reader
|
|
||||||
.read_exact(&mut buf)
|
|
||||||
.map_err(Error::Incomplete)?;
|
|
||||||
|
|
||||||
Ok(<$type>::from_be_bytes(buf))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! define_get_number_le {
|
impl<D> NbtReadHelperJava<D> {
|
||||||
($name:ident, $type:ty) => {
|
pub const fn new(r: D) -> Self {
|
||||||
fn $name(&mut self) -> Result<$type> {
|
|
||||||
let mut buf = [0u8; std::mem::size_of::<$type>()];
|
|
||||||
self.reader
|
|
||||||
.read_exact(&mut buf)
|
|
||||||
.map_err(Error::Incomplete)?;
|
|
||||||
|
|
||||||
Ok(<$type>::from_le_bytes(buf))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NbtReadHelperJava<R: Read + Seek> {
|
|
||||||
reader: R,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Read + Seek> NbtReadHelperJava<R> {
|
|
||||||
pub const fn new(r: R) -> Self {
|
|
||||||
Self { reader: r }
|
Self { reader: r }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NbtReadHelperBedrock<R: Read + Seek> {
|
pub struct NbtReadHelperBedrock<D> {
|
||||||
reader: R,
|
reader: D,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read + Seek> NbtReadHelperBedrock<R> {
|
impl<D> NbtReadHelperBedrock<D> {
|
||||||
pub const fn new(r: R) -> Self {
|
pub const fn new(r: D) -> Self {
|
||||||
Self { reader: r }
|
Self { reader: r }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read + Seek> NbtReadHelperJava<R> {
|
impl<'a, D: NbtDataSource<'a>> NbtReadHelperJava<D> {
|
||||||
define_get_number_be!(get_string_len, u16);
|
fn get_string_len(&mut self) -> Result<u16> {
|
||||||
|
let mut buf = [0u8; 2];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(u16::from_be_bytes(buf))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read + Seek> NbtReadHelper for NbtReadHelperJava<R> {
|
impl<'a, D: NbtDataSource<'a>> NbtReadHelper<'a> for NbtReadHelperJava<D> {
|
||||||
type Reader = R;
|
type Reader = D;
|
||||||
|
|
||||||
fn reader(&mut self) -> &mut R {
|
fn reader(&mut self) -> &mut D {
|
||||||
&mut self.reader
|
&mut self.reader
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,31 +273,54 @@ impl<R: Read + Seek> NbtReadHelper for NbtReadHelperJava<R> {
|
|||||||
self.skip_bytes(len)
|
self.skip_bytes(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
define_get_number_be!(get_u8, u8);
|
fn get_u8(&mut self) -> Result<u8> {
|
||||||
define_get_number_be!(get_i8, i8);
|
self.reader.read_u8()
|
||||||
define_get_number_be!(get_i16, i16);
|
}
|
||||||
define_get_number_be!(get_i32, i32);
|
fn get_i8(&mut self) -> Result<i8> {
|
||||||
define_get_number_be!(get_i64, i64);
|
Ok(self.reader.read_u8()? as i8)
|
||||||
define_get_number_be!(get_f32, f32);
|
}
|
||||||
define_get_number_be!(get_f64, f64);
|
fn get_i16(&mut self) -> Result<i16> {
|
||||||
|
let mut buf = [0u8; 2];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(i16::from_be_bytes(buf))
|
||||||
|
}
|
||||||
|
fn get_i32(&mut self) -> Result<i32> {
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(i32::from_be_bytes(buf))
|
||||||
|
}
|
||||||
|
fn get_i64(&mut self) -> Result<i64> {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(i64::from_be_bytes(buf))
|
||||||
|
}
|
||||||
|
fn get_f32(&mut self) -> Result<f32> {
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(f32::from_be_bytes(buf))
|
||||||
|
}
|
||||||
|
fn get_f64(&mut self) -> Result<f64> {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(f64::from_be_bytes(buf))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_string(&mut self) -> Result<String> {
|
fn get_string(&mut self) -> Result<Cow<'a, str>> {
|
||||||
let len = self.get_string_len()? as usize;
|
let len = self.get_string_len()? as usize;
|
||||||
|
self.reader.read_string(len)
|
||||||
|
}
|
||||||
|
|
||||||
let mut buf = vec![0u8; len];
|
fn get_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>> {
|
||||||
self.reader
|
self.reader.read_byte_array(len)
|
||||||
.read_exact(&mut buf)
|
|
||||||
.map_err(Error::Incomplete)?;
|
|
||||||
|
|
||||||
let string = cesu8::from_java_cesu8(&buf).map_err(|_| Error::Cesu8DecodingError)?;
|
|
||||||
|
|
||||||
Ok(string.into_owned())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read + Seek> NbtReadHelperBedrock<R> {
|
impl<'a, D: NbtDataSource<'a>> NbtReadHelperBedrock<D> {
|
||||||
|
fn get_u8(&mut self) -> Result<u8> {
|
||||||
|
self.reader.read_u8()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_var_u32(&mut self) -> Result<u32> {
|
fn get_var_u32(&mut self) -> Result<u32> {
|
||||||
// LEB128
|
|
||||||
let mut val = 0;
|
let mut val = 0;
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
let byte = self.get_u8()?;
|
let byte = self.get_u8()?;
|
||||||
@ -169,12 +334,10 @@ impl<R: Read + Seek> NbtReadHelperBedrock<R> {
|
|||||||
|
|
||||||
fn get_var_i32(&mut self) -> Result<i32> {
|
fn get_var_i32(&mut self) -> Result<i32> {
|
||||||
let val = self.get_var_u32()?;
|
let val = self.get_var_u32()?;
|
||||||
// ZigZag
|
|
||||||
Ok(((val >> 1) as i32) ^ -((val as i32) & 1))
|
Ok(((val >> 1) as i32) ^ -((val as i32) & 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_var_u64(&mut self) -> Result<u64> {
|
fn get_var_u64(&mut self) -> Result<u64> {
|
||||||
// LEB128
|
|
||||||
let mut val = 0;
|
let mut val = 0;
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
let byte = self.get_u8()?;
|
let byte = self.get_u8()?;
|
||||||
@ -188,7 +351,6 @@ impl<R: Read + Seek> NbtReadHelperBedrock<R> {
|
|||||||
|
|
||||||
fn get_var_i64(&mut self) -> Result<i64> {
|
fn get_var_i64(&mut self) -> Result<i64> {
|
||||||
let val = self.get_var_u64()?;
|
let val = self.get_var_u64()?;
|
||||||
// ZigZag
|
|
||||||
Ok(((val >> 1) as i64) ^ -((val as i64) & 1))
|
Ok(((val >> 1) as i64) ^ -((val as i64) & 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,67 +359,64 @@ impl<R: Read + Seek> NbtReadHelperBedrock<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read + Seek> NbtReadHelper for NbtReadHelperBedrock<R> {
|
impl<'a, D: NbtDataSource<'a>> NbtReadHelper<'a> for NbtReadHelperBedrock<D> {
|
||||||
type Reader = R;
|
type Reader = D;
|
||||||
|
|
||||||
fn reader(&mut self) -> &mut Self::Reader {
|
fn reader(&mut self) -> &mut D {
|
||||||
&mut self.reader
|
&mut self.reader
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip_i32(&mut self) -> Result<()> {
|
|
||||||
for _ in 0..5 {
|
|
||||||
if self.get_u8()? & 0x80 == 0 {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(Error::VarIntTooLarge)
|
|
||||||
}
|
|
||||||
fn skip_i64(&mut self) -> Result<()> {
|
|
||||||
for _ in 0..10 {
|
|
||||||
if self.get_u8()? & 0x80 == 0 {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(Error::VarLongTooLarge)
|
|
||||||
}
|
|
||||||
fn skip_string(&mut self) -> Result<()> {
|
fn skip_string(&mut self) -> Result<()> {
|
||||||
let len = self.get_string_len()? as i64;
|
let len = self.get_string_len()? as i64;
|
||||||
self.skip_bytes(len)
|
self.skip_bytes(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
define_get_number_le!(get_u8, u8);
|
fn get_u8(&mut self) -> Result<u8> {
|
||||||
define_get_number_le!(get_i8, i8);
|
self.reader.read_u8()
|
||||||
define_get_number_le!(get_i16, i16);
|
}
|
||||||
|
fn get_i8(&mut self) -> Result<i8> {
|
||||||
|
Ok(self.reader.read_u8()? as i8)
|
||||||
|
}
|
||||||
|
fn get_i16(&mut self) -> Result<i16> {
|
||||||
|
let mut buf = [0u8; 2];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(i16::from_le_bytes(buf))
|
||||||
|
}
|
||||||
fn get_i32(&mut self) -> Result<i32> {
|
fn get_i32(&mut self) -> Result<i32> {
|
||||||
self.get_var_i32()
|
self.get_var_i32()
|
||||||
}
|
}
|
||||||
fn get_i64(&mut self) -> Result<i64> {
|
fn get_i64(&mut self) -> Result<i64> {
|
||||||
self.get_var_i64()
|
self.get_var_i64()
|
||||||
}
|
}
|
||||||
define_get_number_le!(get_f32, f32);
|
fn get_f32(&mut self) -> Result<f32> {
|
||||||
define_get_number_le!(get_f64, f64);
|
let mut buf = [0u8; 4];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(f32::from_le_bytes(buf))
|
||||||
|
}
|
||||||
|
fn get_f64(&mut self) -> Result<f64> {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
self.reader.read_bytes(&mut buf)?;
|
||||||
|
Ok(f64::from_le_bytes(buf))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_string(&mut self) -> Result<String> {
|
fn get_string(&mut self) -> Result<Cow<'a, str>> {
|
||||||
let len = self.get_string_len()? as usize;
|
let len = self.get_string_len()? as usize;
|
||||||
|
self.reader.read_string(len)
|
||||||
|
}
|
||||||
|
|
||||||
let mut buf = vec![0u8; len];
|
fn get_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>> {
|
||||||
self.reader
|
self.reader.read_byte_array(len)
|
||||||
.read_exact(&mut buf)
|
|
||||||
.map_err(Error::Incomplete)?;
|
|
||||||
|
|
||||||
String::from_utf8(buf).map_err(|_| Error::Utf8DecodingError)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Deserializer<R: NbtReadHelper> {
|
pub struct Deserializer<R> {
|
||||||
input: R,
|
input: R,
|
||||||
tag_to_deserialize_stack: Option<u8>,
|
tag_to_deserialize_stack: Option<u8>,
|
||||||
// Yes, this breaks with recursion. Just an attempt at a sanity check
|
|
||||||
in_list: bool,
|
in_list: bool,
|
||||||
is_named: bool,
|
is_named: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: NbtReadHelper> Deserializer<R> {
|
impl<R> Deserializer<R> {
|
||||||
pub const fn new(input: R, is_named: bool) -> Self {
|
pub const fn new(input: R, is_named: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
input,
|
input,
|
||||||
@ -270,28 +429,46 @@ impl<R: NbtReadHelper> Deserializer<R> {
|
|||||||
|
|
||||||
/// Deserializes struct using Serde Deserializer from normal NBT
|
/// Deserializes struct using Serde Deserializer from normal NBT
|
||||||
pub fn from_bytes<'a, T: Deserialize<'a>>(r: impl Read + Seek) -> Result<T> {
|
pub fn from_bytes<'a, T: Deserialize<'a>>(r: impl Read + Seek) -> Result<T> {
|
||||||
let mut deserializer = Deserializer::new(NbtReadHelperJava::new(r), true);
|
let mut deserializer = Deserializer::new(NbtReadHelperJava::new(NbtStreamReader(r)), true);
|
||||||
T::deserialize(&mut deserializer)
|
T::deserialize(&mut deserializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes struct using Serde Deserializer from network NBT
|
/// Deserializes struct using Serde Deserializer from network NBT
|
||||||
pub fn from_bytes_unnamed<'a, T: Deserialize<'a>>(r: impl Read + Seek) -> Result<T> {
|
pub fn from_bytes_unnamed<'a, T: Deserialize<'a>>(r: impl Read + Seek) -> Result<T> {
|
||||||
let mut deserializer = Deserializer::new(NbtReadHelperJava::new(r), false);
|
let mut deserializer = Deserializer::new(NbtReadHelperJava::new(NbtStreamReader(r)), false);
|
||||||
T::deserialize(&mut deserializer)
|
T::deserialize(&mut deserializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes struct using Serde Deserializer from Bedrock network NBT
|
/// Deserializes struct using Serde Deserializer from Bedrock network NBT
|
||||||
pub fn from_bytes_bedrock<'a, T: Deserialize<'a>>(r: impl Read + Seek) -> Result<T> {
|
pub fn from_bytes_bedrock<'a, T: Deserialize<'a>>(r: impl Read + Seek) -> Result<T> {
|
||||||
let mut deserializer = Deserializer::new(NbtReadHelperBedrock::new(r), true);
|
let mut deserializer = Deserializer::new(NbtReadHelperBedrock::new(NbtStreamReader(r)), true);
|
||||||
T::deserialize(&mut deserializer)
|
T::deserialize(&mut deserializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, R: NbtReadHelper> de::Deserializer<'de> for &mut Deserializer<R> {
|
/// Deserializes struct using Serde Deserializer from a normal NBT slice (zero-allocation)
|
||||||
|
pub fn from_slice<'a, T: Deserialize<'a>>(slice: &'a [u8]) -> Result<T> {
|
||||||
|
let mut deserializer = Deserializer::new(NbtReadHelperJava::new(Cursor::new(slice)), true);
|
||||||
|
T::deserialize(&mut deserializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes struct using Serde Deserializer from a network NBT slice (zero-allocation)
|
||||||
|
pub fn from_slice_unnamed<'a, T: Deserialize<'a>>(slice: &'a [u8]) -> Result<T> {
|
||||||
|
let mut deserializer = Deserializer::new(NbtReadHelperJava::new(Cursor::new(slice)), false);
|
||||||
|
T::deserialize(&mut deserializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes struct using Serde Deserializer from a Bedrock network NBT slice (zero-allocation)
|
||||||
|
pub fn from_slice_bedrock<'a, T: Deserialize<'a>>(slice: &'a [u8]) -> Result<T> {
|
||||||
|
let mut deserializer = Deserializer::new(NbtReadHelperBedrock::new(Cursor::new(slice)), true);
|
||||||
|
T::deserialize(&mut deserializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, R: NbtReadHelper<'de>> de::Deserializer<'de> for &mut Deserializer<R> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
forward_to_deserialize_any! {
|
||||||
i8 i16 i32 i64 f32 f64 char str string unit unit_struct seq tuple tuple_struct
|
i8 i16 i32 i64 f32 f64 char unit unit_struct seq tuple tuple_struct
|
||||||
bytes newtype_struct byte_buf
|
newtype_struct byte_buf
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
@ -334,8 +511,6 @@ impl<'de, R: NbtReadHelper> de::Deserializer<'de> for &mut Deserializer<R> {
|
|||||||
return Err(Error::LargeLength(remaining_values));
|
return Err(Error::LargeLength(remaining_values));
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO this is a bit hacky but I couldn't think of a better way
|
|
||||||
// This flag gets auto cleared in visit_seq
|
|
||||||
set_curr_visitor_seq_list_id(Some(list_type));
|
set_curr_visitor_seq_list_id(Some(list_type));
|
||||||
let result = visitor.visit_seq(ListAccess {
|
let result = visitor.visit_seq(ListAccess {
|
||||||
de: self,
|
de: self,
|
||||||
@ -353,7 +528,7 @@ impl<'de, R: NbtReadHelper> de::Deserializer<'de> for &mut Deserializer<R> {
|
|||||||
NbtTag::Long(value) => visitor.visit_i64::<Error>(value)?,
|
NbtTag::Long(value) => visitor.visit_i64::<Error>(value)?,
|
||||||
NbtTag::Float(value) => visitor.visit_f32::<Error>(value)?,
|
NbtTag::Float(value) => visitor.visit_f32::<Error>(value)?,
|
||||||
NbtTag::Double(value) => visitor.visit_f64::<Error>(value)?,
|
NbtTag::Double(value) => visitor.visit_f64::<Error>(value)?,
|
||||||
NbtTag::String(value) => visitor.visit_string::<Error>(value.into())?,
|
NbtTag::String(value) => visitor.visit_string::<Error>(value.into_string())?,
|
||||||
_ => return Err(Error::SerdeError("Unreachable state reached".to_string())),
|
_ => return Err(Error::SerdeError("Unreachable state reached".to_string())),
|
||||||
};
|
};
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@ -378,13 +553,11 @@ impl<'de, R: NbtReadHelper> de::Deserializer<'de> for &mut Deserializer<R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
// ZigZag might make this a problem for Bedrock...
|
|
||||||
let value = self.input.get_i32()?;
|
let value = self.input.get_i32()?;
|
||||||
visitor.visit_i32::<Error>(value)
|
visitor.visit_i32::<Error>(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
// ZigZag might make this a problem for Bedrock...
|
|
||||||
let value = self.input.get_i64()?;
|
let value = self.input.get_i64()?;
|
||||||
visitor.visit_i64::<Error>(value)
|
visitor.visit_i64::<Error>(value)
|
||||||
}
|
}
|
||||||
@ -399,18 +572,49 @@ impl<'de, R: NbtReadHelper> de::Deserializer<'de> for &mut Deserializer<R> {
|
|||||||
visitor.visit_bool(false)
|
visitor.visit_bool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
|
match self.input.get_string()? {
|
||||||
|
Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
|
||||||
|
Cow::Owned(s) => visitor.visit_string(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
|
self.deserialize_str(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
|
let tag_id = self.tag_to_deserialize_stack.unwrap_or(BYTE_ARRAY_ID);
|
||||||
|
if tag_id == BYTE_ARRAY_ID {
|
||||||
|
let len = self.input.get_i32()?;
|
||||||
|
if len < 0 {
|
||||||
|
return Err(Error::NegativeLength(len));
|
||||||
|
}
|
||||||
|
let slice = self.input.get_byte_array(len as usize)?;
|
||||||
|
let u8_slice: &'de [u8] =
|
||||||
|
unsafe { std::slice::from_raw_parts(slice.as_ptr().cast::<u8>(), slice.len()) };
|
||||||
|
match slice {
|
||||||
|
Cow::Borrowed(_) => visitor.visit_borrowed_bytes(u8_slice),
|
||||||
|
Cow::Owned(_) => visitor.visit_bytes(u8_slice),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.deserialize_any(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_enum<V: Visitor<'de>>(
|
fn deserialize_enum<V: Visitor<'de>>(
|
||||||
self,
|
self,
|
||||||
_name: &'static str,
|
_name: &'static str,
|
||||||
_variants: &'static [&'static str],
|
_variants: &'static [&'static str],
|
||||||
visitor: V,
|
visitor: V,
|
||||||
) -> Result<V::Value> {
|
) -> Result<V::Value> {
|
||||||
let variant = self.input.get_string()?;
|
match self.input.get_string()? {
|
||||||
visitor.visit_enum(variant.into_deserializer())
|
Cow::Borrowed(s) => visitor.visit_enum(s.into_deserializer()),
|
||||||
|
Cow::Owned(s) => visitor.visit_enum(s.into_deserializer()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
// None is not encoded, so no need for it
|
|
||||||
visitor.visit_some(self)
|
visitor.visit_some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,8 +650,7 @@ impl<'de, R: NbtReadHelper> de::Deserializer<'de> for &mut Deserializer<R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
let str = self.input.get_string()?;
|
self.deserialize_str(visitor)
|
||||||
visitor.visit_string(str)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
fn is_human_readable(&self) -> bool {
|
||||||
@ -455,11 +658,11 @@ impl<'de, R: NbtReadHelper> de::Deserializer<'de> for &mut Deserializer<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CompoundAccess<'a, R: NbtReadHelper> {
|
struct CompoundAccess<'a, R> {
|
||||||
de: &'a mut Deserializer<R>,
|
de: &'a mut Deserializer<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, R: NbtReadHelper> MapAccess<'de> for CompoundAccess<'_, R> {
|
impl<'de, R: NbtReadHelper<'de>> MapAccess<'de> for CompoundAccess<'_, R> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
|
fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
|
||||||
@ -478,16 +681,18 @@ impl<'de, R: NbtReadHelper> MapAccess<'de> for CompoundAccess<'_, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MapKey<'a, R: NbtReadHelper> {
|
struct MapKey<'a, R> {
|
||||||
de: &'a mut Deserializer<R>,
|
de: &'a mut Deserializer<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, R: NbtReadHelper> de::Deserializer<'de> for MapKey<'_, R> {
|
impl<'de, R: NbtReadHelper<'de>> de::Deserializer<'de> for MapKey<'_, R> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
let key = self.de.input.get_string()?;
|
match self.de.input.get_string()? {
|
||||||
visitor.visit_string(key)
|
Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
|
||||||
|
Cow::Owned(s) => visitor.visit_string(s),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
forward_to_deserialize_any! {
|
||||||
@ -496,13 +701,13 @@ impl<'de, R: NbtReadHelper> de::Deserializer<'de> for MapKey<'_, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ListAccess<'a, R: NbtReadHelper> {
|
struct ListAccess<'a, R> {
|
||||||
de: &'a mut Deserializer<R>,
|
de: &'a mut Deserializer<R>,
|
||||||
remaining_values: usize,
|
remaining_values: usize,
|
||||||
list_type: u8,
|
list_type: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, R: NbtReadHelper> SeqAccess<'de> for ListAccess<'_, R> {
|
impl<'de, R: NbtReadHelper<'de>> SeqAccess<'de> for ListAccess<'_, R> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
fn size_hint(&self) -> Option<usize> {
|
||||||
|
|||||||
@ -19,7 +19,10 @@ pub mod serializer;
|
|||||||
pub mod tag;
|
pub mod tag;
|
||||||
|
|
||||||
pub use compound::NbtCompound;
|
pub use compound::NbtCompound;
|
||||||
pub use deserializer::{from_bytes, from_bytes_unnamed};
|
pub use deserializer::{
|
||||||
|
from_bytes, from_bytes_bedrock, from_bytes_unnamed, from_slice, from_slice_bedrock,
|
||||||
|
from_slice_unnamed,
|
||||||
|
};
|
||||||
pub use serializer::{to_bytes, to_bytes_named, to_bytes_unnamed};
|
pub use serializer::{to_bytes, to_bytes_named, to_bytes_unnamed};
|
||||||
|
|
||||||
// This NBT crate is inspired from CrabNBT
|
// This NBT crate is inspired from CrabNBT
|
||||||
@ -93,7 +96,7 @@ impl Nbt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<R: NbtReadHelper>(reader: &mut R) -> Result<Self, Error> {
|
pub fn read<'a, R: NbtReadHelper<'a>>(reader: &mut R) -> Result<Self, Error> {
|
||||||
let tag_type_id = reader.get_u8()?;
|
let tag_type_id = reader.get_u8()?;
|
||||||
|
|
||||||
if tag_type_id != COMPOUND_ID {
|
if tag_type_id != COMPOUND_ID {
|
||||||
@ -101,13 +104,13 @@ impl Nbt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
name: reader.get_string()?,
|
name: reader.get_string()?.into_owned(),
|
||||||
root_tag: NbtCompound::deserialize_content(reader)?,
|
root_tag: NbtCompound::deserialize_content(reader)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an NBT tag that doesn't contain the name of the root `Compound`.
|
/// Reads an NBT tag that doesn't contain the name of the root `Compound`.
|
||||||
pub fn read_unnamed<R: NbtReadHelper>(reader: &mut R) -> Result<Self, Error> {
|
pub fn read_unnamed<'a, R: NbtReadHelper<'a>>(reader: &mut R) -> Result<Self, Error> {
|
||||||
let tag_type_id = reader.get_u8()?;
|
let tag_type_id = reader.get_u8()?;
|
||||||
|
|
||||||
if tag_type_id != COMPOUND_ID {
|
if tag_type_id != COMPOUND_ID {
|
||||||
@ -256,6 +259,31 @@ mod test {
|
|||||||
string: String,
|
string: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct BorrowedTest<'a> {
|
||||||
|
byte: i8,
|
||||||
|
string: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn zero_alloc_from_slice() {
|
||||||
|
let test = Test {
|
||||||
|
byte: 123,
|
||||||
|
short: 1342,
|
||||||
|
int: 4313,
|
||||||
|
long: 34,
|
||||||
|
float: 1.00,
|
||||||
|
string: "Zero alloc NBT".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut bytes = Vec::new();
|
||||||
|
to_bytes_unnamed(&test, &mut bytes).unwrap();
|
||||||
|
let borrowed: BorrowedTest = crate::from_slice_unnamed(&bytes).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(borrowed.byte, 123);
|
||||||
|
assert_eq!(borrowed.string, "Zero alloc NBT");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn simple_ser_de_unnamed() {
|
fn simple_ser_de_unnamed() {
|
||||||
let test = Test {
|
let test = Test {
|
||||||
|
|||||||
@ -175,12 +175,12 @@ impl NbtTag {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize<R: NbtReadHelper>(reader: &mut R) -> Result<Self, Error> {
|
pub fn deserialize<'a, R: NbtReadHelper<'a>>(reader: &mut R) -> Result<Self, Error> {
|
||||||
let tag_id = reader.get_u8()?;
|
let tag_id = reader.get_u8()?;
|
||||||
Self::deserialize_data(reader, tag_id)
|
Self::deserialize_data(reader, tag_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip_data<R: NbtReadHelper>(reader: &mut R, tag_id: u8) -> Result<(), Error> {
|
pub fn skip_data<'a, R: NbtReadHelper<'a>>(reader: &mut R, tag_id: u8) -> Result<(), Error> {
|
||||||
match tag_id {
|
match tag_id {
|
||||||
END_ID => Ok(()),
|
END_ID => Ok(()),
|
||||||
BYTE_ID => reader.skip_i8(),
|
BYTE_ID => reader.skip_i8(),
|
||||||
@ -239,7 +239,10 @@ impl NbtTag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize_data<R: NbtReadHelper>(reader: &mut R, tag_id: u8) -> Result<Self, Error> {
|
pub fn deserialize_data<'a, R: NbtReadHelper<'a>>(
|
||||||
|
reader: &mut R,
|
||||||
|
tag_id: u8,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
match tag_id {
|
match tag_id {
|
||||||
END_ID => Ok(Self::End),
|
END_ID => Ok(Self::End),
|
||||||
BYTE_ID => {
|
BYTE_ID => {
|
||||||
@ -283,7 +286,7 @@ impl NbtTag {
|
|||||||
}
|
}
|
||||||
Ok(Self::ByteArray(byte_array.into()))
|
Ok(Self::ByteArray(byte_array.into()))
|
||||||
}
|
}
|
||||||
STRING_ID => Ok(Self::String(reader.get_string()?.into())),
|
STRING_ID => Ok(Self::String(reader.get_string()?.into_owned().into())),
|
||||||
LIST_ID => {
|
LIST_ID => {
|
||||||
let tag_type_id = reader.get_u8()?;
|
let tag_type_id = reader.get_u8()?;
|
||||||
let len = reader.get_i32()?;
|
let len = reader.get_i32()?;
|
||||||
|
|||||||
@ -1,19 +1,60 @@
|
|||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use std::borrow::Cow;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::serial::PacketRead;
|
use crate::serial::{PacketRead, PacketReadSlice, read_str_slice};
|
||||||
|
|
||||||
#[derive(Debug, PacketRead)]
|
#[derive(Debug)]
|
||||||
#[packet(77)]
|
#[packet(77)]
|
||||||
pub struct SCommandRequest {
|
pub struct SCommandRequest<'a> {
|
||||||
pub command: String,
|
pub command: Cow<'a, str>,
|
||||||
|
pub command_type: Cow<'a, str>,
|
||||||
// Command Origin
|
|
||||||
pub command_type: String,
|
|
||||||
pub command_uuid: Uuid,
|
pub command_uuid: Uuid,
|
||||||
pub request_id: String,
|
pub request_id: Cow<'a, str>,
|
||||||
pub player_actor_unique_id: i64,
|
pub player_actor_unique_id: i64,
|
||||||
|
|
||||||
pub is_internal_source: bool,
|
pub is_internal_source: bool,
|
||||||
pub version: String,
|
pub version: Cow<'a, str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PacketReadSlice<'a> for SCommandRequest<'a> {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, std::io::Error> {
|
||||||
|
let command = Cow::Borrowed(read_str_slice(buf)?);
|
||||||
|
let command_type = Cow::Borrowed(read_str_slice(buf)?);
|
||||||
|
let command_uuid = Uuid::read_slice(buf)?;
|
||||||
|
let request_id = Cow::Borrowed(read_str_slice(buf)?);
|
||||||
|
let player_actor_unique_id = i64::read_slice(buf)?;
|
||||||
|
let is_internal_source = bool::read_slice(buf)?;
|
||||||
|
let version = Cow::Borrowed(read_str_slice(buf)?);
|
||||||
|
Ok(Self {
|
||||||
|
command,
|
||||||
|
command_type,
|
||||||
|
command_uuid,
|
||||||
|
request_id,
|
||||||
|
player_actor_unique_id,
|
||||||
|
is_internal_source,
|
||||||
|
version,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketRead for SCommandRequest<'static> {
|
||||||
|
fn read<R: std::io::Read>(reader: &mut R) -> Result<Self, std::io::Error> {
|
||||||
|
let command = Cow::Owned(String::read(reader)?);
|
||||||
|
let command_type = Cow::Owned(String::read(reader)?);
|
||||||
|
let command_uuid = Uuid::read(reader)?;
|
||||||
|
let request_id = Cow::Owned(String::read(reader)?);
|
||||||
|
let player_actor_unique_id = i64::read(reader)?;
|
||||||
|
let is_internal_source = bool::read(reader)?;
|
||||||
|
let version = Cow::Owned(String::read(reader)?);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
command,
|
||||||
|
command_type,
|
||||||
|
command_uuid,
|
||||||
|
request_id,
|
||||||
|
player_actor_unique_id,
|
||||||
|
is_internal_source,
|
||||||
|
version,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,62 @@
|
|||||||
use crate::codec::var_ulong::VarULong;
|
use crate::codec::var_ulong::VarULong;
|
||||||
use crate::serial::{PacketRead, PacketWrite};
|
use crate::serial::{PacketRead, PacketReadSlice, PacketWrite, read_str_slice};
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::io::{Error, Write};
|
||||||
|
|
||||||
pub const EMOTE_FLAG_SERVER_SIDE: u8 = 1 << 0;
|
pub const EMOTE_FLAG_SERVER_SIDE: u8 = 1 << 0;
|
||||||
pub const EMOTE_FLAG_MUTE_CHAT: u8 = 1 << 1;
|
pub const EMOTE_FLAG_MUTE_CHAT: u8 = 1 << 1;
|
||||||
|
|
||||||
#[derive(PacketRead, PacketWrite, Debug)]
|
#[derive(Debug)]
|
||||||
#[packet(138)]
|
#[packet(138)]
|
||||||
pub struct SEmote {
|
pub struct SEmote<'a> {
|
||||||
pub runtime_entity_id: VarULong,
|
pub runtime_entity_id: VarULong,
|
||||||
pub emote_id: String,
|
pub emote_id: Cow<'a, str>,
|
||||||
pub emote_length: u32,
|
pub emote_length: u32,
|
||||||
pub xuid: String,
|
pub xuid: Cow<'a, str>,
|
||||||
pub platform_id: String,
|
pub platform_id: Cow<'a, str>,
|
||||||
pub flags: u8,
|
pub flags: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> PacketReadSlice<'a> for SEmote<'a> {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
let runtime_entity_id = VarULong::read_slice(buf)?;
|
||||||
|
let emote_id = Cow::Borrowed(read_str_slice(buf)?);
|
||||||
|
let emote_length = u32::read_slice(buf)?;
|
||||||
|
let xuid = Cow::Borrowed(read_str_slice(buf)?);
|
||||||
|
let platform_id = Cow::Borrowed(read_str_slice(buf)?);
|
||||||
|
let flags = u8::read_slice(buf)?;
|
||||||
|
Ok(Self {
|
||||||
|
runtime_entity_id,
|
||||||
|
emote_id,
|
||||||
|
emote_length,
|
||||||
|
xuid,
|
||||||
|
platform_id,
|
||||||
|
flags,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketRead for SEmote<'static> {
|
||||||
|
fn read<R: std::io::Read>(reader: &mut R) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
runtime_entity_id: VarULong::read(reader)?,
|
||||||
|
emote_id: Cow::Owned(String::read(reader)?),
|
||||||
|
emote_length: u32::read(reader)?,
|
||||||
|
xuid: Cow::Owned(String::read(reader)?),
|
||||||
|
platform_id: Cow::Owned(String::read(reader)?),
|
||||||
|
flags: u8::read(reader)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketWrite for SEmote<'_> {
|
||||||
|
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||||
|
self.runtime_entity_id.write(writer)?;
|
||||||
|
self.emote_id.as_ref().write(writer)?;
|
||||||
|
self.emote_length.write(writer)?;
|
||||||
|
self.xuid.as_ref().write(writer)?;
|
||||||
|
self.platform_id.as_ref().write(writer)?;
|
||||||
|
self.flags.write(writer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,18 +1,30 @@
|
|||||||
use crate::codec::var_int::VarInt;
|
use crate::codec::var_int::VarInt;
|
||||||
use crate::serial::PacketRead;
|
use crate::serial::{PacketRead, PacketReadSlice, read_str_slice};
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::io::{Error, Read};
|
use std::io::{Error, Read};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
#[packet(101)]
|
#[packet(101)]
|
||||||
pub struct SModalFormResponse {
|
pub struct SModalFormResponse<'a> {
|
||||||
pub form_id: VarInt,
|
pub form_id: VarInt,
|
||||||
pub form_data: Option<String>,
|
pub form_data: Option<Cow<'a, str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketRead for SModalFormResponse {
|
impl<'a> PacketReadSlice<'a> for SModalFormResponse<'a> {
|
||||||
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
let form_id = VarInt::read(reader)?;
|
let form_id = VarInt::read_slice(buf)?;
|
||||||
let form_data = Option::<String>::read(reader)?;
|
let form_data = bool::read_slice(buf)?
|
||||||
|
.then(|| read_str_slice(buf).map(Cow::Borrowed))
|
||||||
|
.transpose()?;
|
||||||
|
Ok(Self { form_id, form_data })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketRead for SModalFormResponse<'static> {
|
||||||
|
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||||
|
let form_id = VarInt::read(reader)?;
|
||||||
|
let form_data = Option::<String>::read(reader)?.map(Cow::Owned);
|
||||||
Ok(Self { form_id, form_data })
|
Ok(Self { form_id, form_data })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,52 +1,70 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
codec::var_uint::VarUInt,
|
codec::var_uint::VarUInt,
|
||||||
serial::{PacketRead, PacketWrite},
|
serial::{PacketRead, PacketReadSlice, PacketWrite, read_str_slice},
|
||||||
};
|
};
|
||||||
use pumpkin_macros::packet;
|
use pumpkin_macros::packet;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::io::{Error, ErrorKind, Read, Write};
|
use std::io::{Error, ErrorKind, Read, Write};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[packet(9)]
|
#[packet(9)]
|
||||||
pub struct SText {
|
pub struct SText<'a> {
|
||||||
pub needs_translation: bool,
|
pub needs_translation: bool,
|
||||||
pub r#type: TextPacketType,
|
pub r#type: TextPacketType,
|
||||||
pub source_name: String,
|
pub source_name: Cow<'a, str>,
|
||||||
pub message: String,
|
pub message: Cow<'a, str>,
|
||||||
pub parameters: Vec<String>,
|
pub parameters: Vec<Cow<'a, str>>,
|
||||||
pub xuid: String,
|
pub xuid: Cow<'a, str>,
|
||||||
pub platform_chat_id: String,
|
pub platform_chat_id: Cow<'a, str>,
|
||||||
pub filtered_message: Option<String>,
|
pub filtered_message: Option<Cow<'a, str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SText {
|
impl SText<'_> {
|
||||||
|
const fn get_category(&self) -> u8 {
|
||||||
|
match self.r#type {
|
||||||
|
TextPacketType::Raw
|
||||||
|
| TextPacketType::Tip
|
||||||
|
| TextPacketType::System
|
||||||
|
| TextPacketType::JsonWhisper
|
||||||
|
| TextPacketType::JsonAnnouncement
|
||||||
|
| TextPacketType::Json => 0,
|
||||||
|
|
||||||
|
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => 1,
|
||||||
|
|
||||||
|
TextPacketType::Translation | TextPacketType::Popup | TextPacketType::JukeboxPopup => 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SText<'static> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(message: String, source_name: String) -> Self {
|
pub fn new(message: String, source_name: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
needs_translation: false,
|
needs_translation: false,
|
||||||
r#type: TextPacketType::Chat,
|
r#type: TextPacketType::Chat,
|
||||||
source_name,
|
source_name: Cow::Owned(source_name),
|
||||||
message: if message.is_empty() {
|
message: Cow::Owned(if message.is_empty() {
|
||||||
" ".to_string()
|
" ".to_string()
|
||||||
} else {
|
} else {
|
||||||
message
|
message
|
||||||
},
|
}),
|
||||||
parameters: Vec::new(),
|
parameters: Vec::new(),
|
||||||
xuid: String::new(),
|
xuid: Cow::Borrowed(""),
|
||||||
platform_chat_id: String::new(),
|
platform_chat_id: Cow::Borrowed(""),
|
||||||
filtered_message: None,
|
filtered_message: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn translation(message: String, parameters: Vec<String>) -> Self {
|
pub fn translation(message: String, parameters: Vec<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
needs_translation: true,
|
needs_translation: true,
|
||||||
r#type: TextPacketType::Translation,
|
r#type: TextPacketType::Translation,
|
||||||
source_name: String::new(),
|
source_name: Cow::Borrowed(""),
|
||||||
message,
|
message: Cow::Owned(message),
|
||||||
parameters,
|
parameters: parameters.into_iter().map(Cow::Owned).collect(),
|
||||||
xuid: String::new(),
|
xuid: Cow::Borrowed(""),
|
||||||
platform_chat_id: String::new(),
|
platform_chat_id: Cow::Borrowed(""),
|
||||||
filtered_message: None,
|
filtered_message: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,15 +74,15 @@ impl SText {
|
|||||||
Self {
|
Self {
|
||||||
needs_translation: false,
|
needs_translation: false,
|
||||||
r#type: TextPacketType::System,
|
r#type: TextPacketType::System,
|
||||||
source_name: String::new(),
|
source_name: Cow::Borrowed(""),
|
||||||
message: if message.is_empty() {
|
message: Cow::Owned(if message.is_empty() {
|
||||||
" ".to_string()
|
" ".to_string()
|
||||||
} else {
|
} else {
|
||||||
message
|
message
|
||||||
},
|
}),
|
||||||
parameters: Vec::new(),
|
parameters: Vec::new(),
|
||||||
xuid: String::new(),
|
xuid: Cow::Borrowed(""),
|
||||||
platform_chat_id: String::new(),
|
platform_chat_id: Cow::Borrowed(""),
|
||||||
filtered_message: None,
|
filtered_message: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,37 +92,72 @@ impl SText {
|
|||||||
Self {
|
Self {
|
||||||
needs_translation: false,
|
needs_translation: false,
|
||||||
r#type: TextPacketType::Json,
|
r#type: TextPacketType::Json,
|
||||||
source_name: String::new(),
|
source_name: Cow::Borrowed(""),
|
||||||
message,
|
message: Cow::Owned(message),
|
||||||
parameters: Vec::new(),
|
parameters: Vec::new(),
|
||||||
xuid: String::new(),
|
xuid: Cow::Borrowed(""),
|
||||||
platform_chat_id: String::new(),
|
platform_chat_id: Cow::Borrowed(""),
|
||||||
filtered_message: None,
|
filtered_message: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn get_category(&self) -> u8 {
|
|
||||||
match self.r#type {
|
|
||||||
TextPacketType::Raw
|
|
||||||
| TextPacketType::Tip
|
|
||||||
| TextPacketType::System
|
|
||||||
| TextPacketType::JsonWhisper
|
|
||||||
| TextPacketType::JsonAnnouncement
|
|
||||||
| TextPacketType::Json => 0, // CATEGORY_MESSAGE_ONLY
|
|
||||||
|
|
||||||
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => 1, // CATEGORY_AUTHORED_MESSAGE
|
|
||||||
|
|
||||||
TextPacketType::Translation | TextPacketType::Popup | TextPacketType::JukeboxPopup => 2, // CATEGORY_MESSAGE_WITH_PARAMETERS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketRead for SText {
|
impl<'a> PacketReadSlice<'a> for SText<'a> {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
let needs_translation = bool::read_slice(buf)?;
|
||||||
|
let _category = u8::read_slice(buf)?;
|
||||||
|
let r#type = TextPacketType::read_slice(buf)?;
|
||||||
|
|
||||||
|
let mut source_name = "";
|
||||||
|
let message;
|
||||||
|
let mut parameters: Vec<Cow<'a, str>> = Vec::new();
|
||||||
|
|
||||||
|
match r#type {
|
||||||
|
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => {
|
||||||
|
source_name = read_str_slice(buf)?;
|
||||||
|
message = read_str_slice(buf)?;
|
||||||
|
}
|
||||||
|
TextPacketType::Raw
|
||||||
|
| TextPacketType::Tip
|
||||||
|
| TextPacketType::System
|
||||||
|
| TextPacketType::JsonWhisper
|
||||||
|
| TextPacketType::Json
|
||||||
|
| TextPacketType::JsonAnnouncement => {
|
||||||
|
message = read_str_slice(buf)?;
|
||||||
|
}
|
||||||
|
TextPacketType::Translation | TextPacketType::Popup | TextPacketType::JukeboxPopup => {
|
||||||
|
message = read_str_slice(buf)?;
|
||||||
|
let count = VarUInt::read_slice(buf)?.0 as usize;
|
||||||
|
for _ in 0..count {
|
||||||
|
parameters.push(Cow::Borrowed(read_str_slice(buf)?));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let xuid = read_str_slice(buf)?;
|
||||||
|
let platform_chat_id = read_str_slice(buf)?;
|
||||||
|
|
||||||
|
let filtered_message = bool::read_slice(buf)?
|
||||||
|
.then(|| read_str_slice(buf).map(Cow::Borrowed))
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
needs_translation,
|
||||||
|
r#type,
|
||||||
|
source_name: Cow::Borrowed(source_name),
|
||||||
|
message: Cow::Borrowed(message),
|
||||||
|
parameters,
|
||||||
|
xuid: Cow::Borrowed(xuid),
|
||||||
|
platform_chat_id: Cow::Borrowed(platform_chat_id),
|
||||||
|
filtered_message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketRead for SText<'static> {
|
||||||
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||||
let needs_translation = bool::read(reader)?;
|
let needs_translation = bool::read(reader)?;
|
||||||
|
|
||||||
let _category = u8::read(reader)?;
|
let _category = u8::read(reader)?;
|
||||||
|
|
||||||
let r#type = TextPacketType::read(reader)?;
|
let r#type = TextPacketType::read(reader)?;
|
||||||
|
|
||||||
let mut source_name = String::new();
|
let mut source_name = String::new();
|
||||||
@ -129,7 +182,7 @@ impl PacketRead for SText {
|
|||||||
message = String::read(reader)?;
|
message = String::read(reader)?;
|
||||||
let count = VarUInt::read(reader)?.0 as usize;
|
let count = VarUInt::read(reader)?.0 as usize;
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
parameters.push(String::read(reader)?);
|
parameters.push(Cow::Owned(String::read(reader)?));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,23 +191,23 @@ impl PacketRead for SText {
|
|||||||
let platform_chat_id = String::read(reader)?;
|
let platform_chat_id = String::read(reader)?;
|
||||||
|
|
||||||
let filtered_message = bool::read(reader)?
|
let filtered_message = bool::read(reader)?
|
||||||
.then(|| String::read(reader))
|
.then(|| String::read(reader).map(Cow::Owned))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
needs_translation,
|
needs_translation,
|
||||||
r#type,
|
r#type,
|
||||||
source_name,
|
source_name: Cow::Owned(source_name),
|
||||||
message,
|
message: Cow::Owned(message),
|
||||||
parameters,
|
parameters,
|
||||||
xuid,
|
xuid: Cow::Owned(xuid),
|
||||||
platform_chat_id,
|
platform_chat_id: Cow::Owned(platform_chat_id),
|
||||||
filtered_message,
|
filtered_message,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketWrite for SText {
|
impl PacketWrite for SText<'_> {
|
||||||
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||||
self.needs_translation.write(writer)?;
|
self.needs_translation.write(writer)?;
|
||||||
|
|
||||||
@ -165,8 +218,8 @@ impl PacketWrite for SText {
|
|||||||
|
|
||||||
match self.r#type {
|
match self.r#type {
|
||||||
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => {
|
TextPacketType::Chat | TextPacketType::Whisper | TextPacketType::Announcement => {
|
||||||
self.source_name.write(writer)?;
|
self.source_name.as_ref().write(writer)?;
|
||||||
self.message.write(writer)?;
|
self.message.as_ref().write(writer)?;
|
||||||
}
|
}
|
||||||
TextPacketType::Raw
|
TextPacketType::Raw
|
||||||
| TextPacketType::Tip
|
| TextPacketType::Tip
|
||||||
@ -174,23 +227,23 @@ impl PacketWrite for SText {
|
|||||||
| TextPacketType::JsonWhisper
|
| TextPacketType::JsonWhisper
|
||||||
| TextPacketType::Json
|
| TextPacketType::Json
|
||||||
| TextPacketType::JsonAnnouncement => {
|
| TextPacketType::JsonAnnouncement => {
|
||||||
self.message.write(writer)?;
|
self.message.as_ref().write(writer)?;
|
||||||
}
|
}
|
||||||
TextPacketType::Translation | TextPacketType::Popup | TextPacketType::JukeboxPopup => {
|
TextPacketType::Translation | TextPacketType::Popup | TextPacketType::JukeboxPopup => {
|
||||||
self.message.write(writer)?;
|
self.message.as_ref().write(writer)?;
|
||||||
VarUInt(self.parameters.len() as u32).write(writer)?;
|
VarUInt(self.parameters.len() as u32).write(writer)?;
|
||||||
for param in &self.parameters {
|
for param in &self.parameters {
|
||||||
param.write(writer)?;
|
param.as_ref().write(writer)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.xuid.write(writer)?;
|
self.xuid.as_ref().write(writer)?;
|
||||||
self.platform_chat_id.write(writer)?;
|
self.platform_chat_id.as_ref().write(writer)?;
|
||||||
|
|
||||||
if let Some(msg) = &self.filtered_message {
|
if let Some(msg) = &self.filtered_message {
|
||||||
true.write(writer)?;
|
true.write(writer)?;
|
||||||
msg.write(writer)?;
|
msg.as_ref().write(writer)?;
|
||||||
} else {
|
} else {
|
||||||
false.write(writer)?;
|
false.write(writer)?;
|
||||||
}
|
}
|
||||||
@ -241,3 +294,23 @@ impl PacketRead for TextPacketType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> PacketReadSlice<'a> for TextPacketType {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
match u8::read_slice(buf)? {
|
||||||
|
0 => Ok(Self::Raw),
|
||||||
|
1 => Ok(Self::Chat),
|
||||||
|
2 => Ok(Self::Translation),
|
||||||
|
3 => Ok(Self::Popup),
|
||||||
|
4 => Ok(Self::JukeboxPopup),
|
||||||
|
5 => Ok(Self::Tip),
|
||||||
|
6 => Ok(Self::System),
|
||||||
|
7 => Ok(Self::Whisper),
|
||||||
|
8 => Ok(Self::Announcement),
|
||||||
|
9 => Ok(Self::JsonWhisper),
|
||||||
|
10 => Ok(Self::Json),
|
||||||
|
11 => Ok(Self::JsonAnnouncement),
|
||||||
|
_ => Err(Error::new(ErrorKind::InvalidData, "Unknown Text Type")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -106,16 +106,30 @@ fn read_length_prefixed_component(
|
|||||||
) -> Result<(DataComponent, Box<dyn DataComponentImpl>), ReadingError> {
|
) -> Result<(DataComponent, Box<dyn DataComponentImpl>), ReadingError> {
|
||||||
let id = read_component_id(read)?;
|
let id = read_component_id(read)?;
|
||||||
let byte_len = read.get_var_int()?.0;
|
let byte_len = read.get_var_int()?.0;
|
||||||
let byte_len = byte_len
|
let byte_len: usize = byte_len
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| ReadingError::Message("Negative component data length".into()))?;
|
.map_err(|_| ReadingError::Message("Negative component data length".into()))?;
|
||||||
let component_data = read.read_boxed_slice(byte_len)?;
|
|
||||||
|
|
||||||
let component_impl = if id == DataComponent::CustomName {
|
let component_impl = if byte_len <= 256 {
|
||||||
|
let mut stack_buf = [0u8; 256];
|
||||||
|
let slice = &mut stack_buf[..byte_len];
|
||||||
|
read.read_bytes_to_buf(slice)?;
|
||||||
|
|
||||||
|
if id == DataComponent::CustomName {
|
||||||
|
decode_custom_name(slice)?
|
||||||
|
} else {
|
||||||
|
let mut cursor = Cursor::new(slice);
|
||||||
|
deserialize(id, &mut cursor)?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut component_data = vec![0u8; byte_len];
|
||||||
|
read.read_bytes_to_buf(&mut component_data)?;
|
||||||
|
if id == DataComponent::CustomName {
|
||||||
decode_custom_name(component_data.as_ref())?
|
decode_custom_name(component_data.as_ref())?
|
||||||
} else {
|
} else {
|
||||||
let mut cursor = Cursor::new(component_data);
|
let mut cursor = Cursor::new(component_data);
|
||||||
deserialize(id, &mut cursor)?
|
deserialize(id, &mut cursor)?
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((id, component_impl))
|
Ok((id, component_impl))
|
||||||
@ -297,13 +311,11 @@ impl ItemComponentHash {
|
|||||||
pub fn read(read: &mut impl NetworkReadExt) -> Result<Self, ReadingError> {
|
pub fn read(read: &mut impl NetworkReadExt) -> Result<Self, ReadingError> {
|
||||||
const MAX_COMPONENTS: i32 = 256;
|
const MAX_COMPONENTS: i32 = 256;
|
||||||
|
|
||||||
let mut added = Vec::new();
|
|
||||||
let mut removed = Vec::new();
|
|
||||||
|
|
||||||
let added_length = read.get_var_int()?;
|
let added_length = read.get_var_int()?;
|
||||||
if added_length.0 < 0 || added_length.0 > MAX_COMPONENTS {
|
if added_length.0 < 0 || added_length.0 > MAX_COMPONENTS {
|
||||||
return Err(ReadingError::Message("added_length out of bounds".into()));
|
return Err(ReadingError::Message("added_length out of bounds".into()));
|
||||||
}
|
}
|
||||||
|
let mut added = Vec::with_capacity(added_length.0 as usize);
|
||||||
for _ in 0..added_length.0 {
|
for _ in 0..added_length.0 {
|
||||||
let component_id = read.get_var_int()?;
|
let component_id = read.get_var_int()?;
|
||||||
let component_value = read.get_i32()?;
|
let component_value = read.get_i32()?;
|
||||||
@ -314,6 +326,7 @@ impl ItemComponentHash {
|
|||||||
if removed_length.0 < 0 || removed_length.0 > MAX_COMPONENTS {
|
if removed_length.0 < 0 || removed_length.0 > MAX_COMPONENTS {
|
||||||
return Err(ReadingError::Message("removed_length out of bounds".into()));
|
return Err(ReadingError::Message("removed_length out of bounds".into()));
|
||||||
}
|
}
|
||||||
|
let mut removed = Vec::with_capacity(removed_length.0 as usize);
|
||||||
for _ in 0..removed_length.0 {
|
for _ in 0..removed_length.0 {
|
||||||
let component_id = read.get_var_int()?;
|
let component_id = read.get_var_int()?;
|
||||||
removed.push(component_id);
|
removed.push(component_id);
|
||||||
|
|||||||
@ -16,12 +16,12 @@ use crate::{
|
|||||||
/// initializes the player's world view, dimension settings, and local game
|
/// initializes the player's world view, dimension settings, and local game
|
||||||
/// rules. Once received, the client begins rendering the world.
|
/// rules. Once received, the client begins rendering the world.
|
||||||
#[java_packet(PLAY_LOGIN)]
|
#[java_packet(PLAY_LOGIN)]
|
||||||
pub struct CLogin {
|
pub struct CLogin<'a> {
|
||||||
/// The unique ID assigned to the player for the current session.
|
/// The unique ID assigned to the player for the current session.
|
||||||
pub entity_id: i32,
|
pub entity_id: i32,
|
||||||
pub is_hardcore: bool,
|
pub is_hardcore: bool,
|
||||||
/// A list of all dimensions present on the server (e.g., overworld, nether, end).
|
/// A list of all dimensions present on the server (e.g., overworld, nether, end).
|
||||||
pub dimension_names: Vec<ResourceLocation>,
|
pub dimension_names: &'a [ResourceLocation],
|
||||||
pub max_players: VarInt,
|
pub max_players: VarInt,
|
||||||
/// The number of chunks the client will render in each direction.
|
/// The number of chunks the client will render in each direction.
|
||||||
pub view_distance: VarInt,
|
pub view_distance: VarInt,
|
||||||
@ -38,14 +38,14 @@ pub struct CLogin {
|
|||||||
pub enforce_secure_chat: bool,
|
pub enforce_secure_chat: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CLogin {
|
impl<'a> CLogin<'a> {
|
||||||
#[expect(clippy::too_many_arguments)]
|
#[expect(clippy::too_many_arguments)]
|
||||||
#[expect(clippy::fn_params_excessive_bools)]
|
#[expect(clippy::fn_params_excessive_bools)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
entity_id: i32,
|
entity_id: i32,
|
||||||
is_hardcore: bool,
|
is_hardcore: bool,
|
||||||
dimension_names: Vec<ResourceLocation>,
|
dimension_names: &'a [ResourceLocation],
|
||||||
max_players: VarInt,
|
max_players: VarInt,
|
||||||
view_distance: VarInt,
|
view_distance: VarInt,
|
||||||
simulated_distance: VarInt,
|
simulated_distance: VarInt,
|
||||||
@ -73,7 +73,7 @@ impl CLogin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientPacket for CLogin {
|
impl ClientPacket for CLogin<'_> {
|
||||||
fn write_packet_data(
|
fn write_packet_data(
|
||||||
&self,
|
&self,
|
||||||
mut write: impl std::io::Write,
|
mut write: impl std::io::Write,
|
||||||
@ -81,7 +81,7 @@ impl ClientPacket for CLogin {
|
|||||||
) -> Result<(), WritingError> {
|
) -> Result<(), WritingError> {
|
||||||
write.write_i32_be(self.entity_id)?;
|
write.write_i32_be(self.entity_id)?;
|
||||||
write.write_bool(self.is_hardcore)?;
|
write.write_bool(self.is_hardcore)?;
|
||||||
write.write_list(&self.dimension_names, |write, dim| write.write_string(dim))?;
|
write.write_list(self.dimension_names, |write, dim| write.write_string(dim))?;
|
||||||
write.write_var_int(&self.max_players)?;
|
write.write_var_int(&self.max_players)?;
|
||||||
write.write_var_int(&self.view_distance)?;
|
write.write_var_int(&self.view_distance)?;
|
||||||
write.write_var_int(&self.simulated_distance)?;
|
write.write_var_int(&self.simulated_distance)?;
|
||||||
|
|||||||
@ -84,9 +84,9 @@ impl ClientPacket for CPlayerPosition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for CPlayerPosition {
|
impl<'a> ServerPacket<'a> for CPlayerPosition {
|
||||||
fn read(
|
fn read(
|
||||||
mut read: impl std::io::Read,
|
read: &mut &'a [u8],
|
||||||
_version: &JavaMinecraftVersion,
|
_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, crate::ser::ReadingError> {
|
) -> Result<Self, crate::ser::ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@ -191,7 +191,10 @@ impl<R: AsyncRead + Unpin> TCPNetworkDecoder<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = self.payload_scratch.split().freeze();
|
let payload = self
|
||||||
|
.payload_scratch
|
||||||
|
.split_to(self.payload_scratch.len())
|
||||||
|
.freeze();
|
||||||
|
|
||||||
Ok(RawPacket {
|
Ok(RawPacket {
|
||||||
id: packet_id,
|
id: packet_id,
|
||||||
@ -456,4 +459,40 @@ mod tests {
|
|||||||
assert_eq!(raw_packet.payload.as_ref(), payload);
|
assert_eq!(raw_packet.payload.as_ref(), payload);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test decoding multiple packets sequentially to verify capacity is retained for zero allocation
|
||||||
|
#[tokio::test]
|
||||||
|
async fn decode_multiple_packets_zero_allocation() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let packet1 = build_packet(1, b"Hello", false, None, None)?;
|
||||||
|
let packet2 = build_packet(2, b"World", false, None, None)?;
|
||||||
|
|
||||||
|
let mut stream = Vec::new();
|
||||||
|
stream.extend_from_slice(&packet1);
|
||||||
|
stream.extend_from_slice(&packet2);
|
||||||
|
|
||||||
|
let mut decoder = TCPNetworkDecoder::new(stream.as_slice());
|
||||||
|
|
||||||
|
let p1 = decoder.get_raw_packet().await?;
|
||||||
|
assert_eq!(p1.id, 1);
|
||||||
|
assert_eq!(p1.payload.as_ref(), b"Hello");
|
||||||
|
drop(p1);
|
||||||
|
|
||||||
|
let cap_after_p1 = decoder.payload_scratch.capacity();
|
||||||
|
assert!(
|
||||||
|
cap_after_p1 > 0,
|
||||||
|
"Capacity should be allocated after first read"
|
||||||
|
);
|
||||||
|
|
||||||
|
let p2 = decoder.get_raw_packet().await?;
|
||||||
|
assert_eq!(p2.id, 2);
|
||||||
|
assert_eq!(p2.payload.as_ref(), b"World");
|
||||||
|
drop(p2);
|
||||||
|
|
||||||
|
let cap_after_p2 = decoder.payload_scratch.capacity();
|
||||||
|
assert_eq!(
|
||||||
|
cap_after_p2, cap_after_p1,
|
||||||
|
"Buffer capacity should be retained and reused without new heap allocations"
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -204,9 +204,6 @@ impl<W: AsyncWrite + Unpin> TCPNetworkEncoder<W> {
|
|||||||
/// NOTE: This method does not flush. Call [`Self::flush`] to flush buffered data.
|
/// NOTE: This method does not flush. Call [`Self::flush`] to flush buffered data.
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub async fn write_packet(&mut self, packet_data: Bytes) -> Result<(), PacketEncodeError> {
|
pub async fn write_packet(&mut self, packet_data: Bytes) -> Result<(), PacketEncodeError> {
|
||||||
// We need to know the length of the compressed buffer and serde is not async :(
|
|
||||||
// We need to write to a buffer here 😔
|
|
||||||
|
|
||||||
let data_len = packet_data.len();
|
let data_len = packet_data.len();
|
||||||
if data_len > MAX_PACKET_DATA_SIZE {
|
if data_len > MAX_PACKET_DATA_SIZE {
|
||||||
return Err(PacketEncodeError::TooLong(data_len));
|
return Err(PacketEncodeError::TooLong(data_len));
|
||||||
@ -218,14 +215,13 @@ impl<W: AsyncWrite + Unpin> TCPNetworkEncoder<W> {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some((compression_threshold, compression_level)) = self.compression {
|
let mut header_buf = [0u8; 10];
|
||||||
if data_len >= compression_threshold {
|
let mut header_cursor = std::io::Cursor::new(&mut header_buf[..]);
|
||||||
// Pushed before data:
|
|
||||||
// Length of (Data Length) + length of compressed (Packet ID + Data)
|
|
||||||
// Length of uncompressed (Packet ID + Data)
|
|
||||||
|
|
||||||
// TODO: We need the compressed length at the beginning of the packet so we need to write to
|
let payload_to_write: &[u8] = if let Some((compression_threshold, compression_level)) =
|
||||||
// buf here :( Is there a magic way to find a compressed length?
|
self.compression
|
||||||
|
{
|
||||||
|
if data_len >= compression_threshold {
|
||||||
self.compress_packet_data(packet_data.as_ref(), compression_level)?;
|
self.compress_packet_data(packet_data.as_ref(), compression_level)?;
|
||||||
debug_assert!(!self.compression_scratch.is_empty());
|
debug_assert!(!self.compression_scratch.is_empty());
|
||||||
|
|
||||||
@ -245,24 +241,14 @@ impl<W: AsyncWrite + Unpin> TCPNetworkEncoder<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
full_packet_len_var_int
|
full_packet_len_var_int
|
||||||
.encode_async(self.writer.as_mut().unwrap())
|
.encode(&mut header_cursor)
|
||||||
.await
|
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
||||||
data_len_var_int
|
data_len_var_int
|
||||||
.encode_async(self.writer.as_mut().unwrap())
|
.encode(&mut header_cursor)
|
||||||
.await
|
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
||||||
self.writer
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.write_all(&self.compression_scratch)
|
|
||||||
.await
|
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
|
||||||
} else {
|
|
||||||
// Pushed before data:
|
|
||||||
// Length of (Data Length) + length of compressed (Packet ID + Data)
|
|
||||||
// 0 to indicate uncompressed
|
|
||||||
|
|
||||||
|
self.compression_scratch.as_slice()
|
||||||
|
} else {
|
||||||
let data_len_var_int: VarInt = 0.into();
|
let data_len_var_int: VarInt = 0.into();
|
||||||
let full_packet_len_var_int: VarInt = (data_len_var_int.written_size() + data_len)
|
let full_packet_len_var_int: VarInt = (data_len_var_int.written_size() + data_len)
|
||||||
.try_into()
|
.try_into()
|
||||||
@ -279,24 +265,15 @@ impl<W: AsyncWrite + Unpin> TCPNetworkEncoder<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
full_packet_len_var_int
|
full_packet_len_var_int
|
||||||
.encode_async(self.writer.as_mut().unwrap())
|
.encode(&mut header_cursor)
|
||||||
.await
|
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
||||||
data_len_var_int
|
data_len_var_int
|
||||||
.encode_async(self.writer.as_mut().unwrap())
|
.encode(&mut header_cursor)
|
||||||
.await
|
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
|
||||||
self.writer
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.write_all(&packet_data)
|
|
||||||
.await
|
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
||||||
|
|
||||||
|
packet_data.as_ref()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Pushed before data:
|
|
||||||
// Length of Packet ID + Data
|
|
||||||
|
|
||||||
let full_packet_len_var_int: VarInt = data_len_var_int;
|
let full_packet_len_var_int: VarInt = data_len_var_int;
|
||||||
|
|
||||||
let complete_serialization_length =
|
let complete_serialization_length =
|
||||||
@ -306,16 +283,27 @@ impl<W: AsyncWrite + Unpin> TCPNetworkEncoder<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
full_packet_len_var_int
|
full_packet_len_var_int
|
||||||
.encode_async(self.writer.as_mut().unwrap())
|
.encode(&mut header_cursor)
|
||||||
.await
|
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
||||||
self.writer
|
|
||||||
|
packet_data.as_ref()
|
||||||
|
};
|
||||||
|
|
||||||
|
let header_len = header_cursor.position() as usize;
|
||||||
|
let header_bytes = &header_buf[..header_len];
|
||||||
|
let writer = self
|
||||||
|
.writer
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.ok_or_else(|| PacketEncodeError::Message("Writer missing".into()))?;
|
||||||
.write_all(&packet_data)
|
|
||||||
|
writer
|
||||||
|
.write_all(header_bytes)
|
||||||
|
.await
|
||||||
|
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
||||||
|
writer
|
||||||
|
.write_all(payload_to_write)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
.map_err(|err| PacketEncodeError::Message(err.to_string()))?;
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -323,7 +311,7 @@ impl<W: AsyncWrite + Unpin> TCPNetworkEncoder<W> {
|
|||||||
pub async fn flush(&mut self) -> Result<(), PacketEncodeError> {
|
pub async fn flush(&mut self) -> Result<(), PacketEncodeError> {
|
||||||
self.writer
|
self.writer
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.ok_or_else(|| PacketEncodeError::Message("Writer missing".into()))?
|
||||||
.flush()
|
.flush()
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PacketEncodeError::Message(err.to_string()))
|
.map_err(|err| PacketEncodeError::Message(err.to_string()))
|
||||||
|
|||||||
@ -3,15 +3,17 @@ use pumpkin_macros::java_packet;
|
|||||||
|
|
||||||
use crate::{ServerPacket, ser::ReadingError};
|
use crate::{ServerPacket, ser::ReadingError};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
/// This packet signals to the server that the client is ready to transition
|
/// This packet signals to the server that the client is ready to transition
|
||||||
/// from the `Configuration` state to the `Play` state.
|
/// from the `Configuration` state to the `Play` state.
|
||||||
#[java_packet(CONFIG_FINISH_CONFIGURATION)]
|
#[java_packet(CONFIG_FINISH_CONFIGURATION)]
|
||||||
pub struct SAcknowledgeFinishConfig;
|
pub struct SAcknowledgeFinishConfig;
|
||||||
|
|
||||||
impl ServerPacket for SAcknowledgeFinishConfig {
|
impl<'a> ServerPacket<'a> for SAcknowledgeFinishConfig {
|
||||||
fn read(_bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(
|
||||||
|
_bytebuf: &mut &'a [u8],
|
||||||
|
_version: &JavaMinecraftVersion,
|
||||||
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self)
|
Ok(Self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,16 +5,15 @@ use crate::VarInt;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
/// Sent by the client to inform the server about its local settings
|
/// Sent by the client to inform the server about its local settings
|
||||||
#[java_packet(CONFIG_CLIENT_INFORMATION)]
|
#[java_packet(CONFIG_CLIENT_INFORMATION)]
|
||||||
pub struct SClientInformationConfig {
|
pub struct SClientInformationConfig<'a> {
|
||||||
/// The language code used by the client (e.g., "`en_us`")
|
/// The language code used by the client (e.g., "`en_us`")
|
||||||
pub locale: String,
|
pub locale: &'a str,
|
||||||
/// The maximum number of chunks the client renders
|
/// The maximum number of chunks the client renders
|
||||||
pub view_distance: i8,
|
pub view_distance: i8,
|
||||||
/// Visibility of chat messages (0: Enabled, 1: Commands Only, 2: Hidden)
|
/// Visibility of chat messages (0: Enabled, 1: Commands Only, 2: Hidden)
|
||||||
@ -31,10 +30,10 @@ pub struct SClientInformationConfig {
|
|||||||
pub server_listing: bool,
|
pub server_listing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SClientInformationConfig {
|
impl<'a> ServerPacket<'a> for SClientInformationConfig<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
locale: bytebuf.get_str()?.into_string(),
|
locale: bytebuf.get_str_borrowed()?,
|
||||||
view_distance: bytebuf.get_i8()?,
|
view_distance: bytebuf.get_i8()?,
|
||||||
chat_mode: bytebuf.get_var_int()?,
|
chat_mode: bytebuf.get_var_int()?,
|
||||||
chat_colors: bytebuf.get_bool()?,
|
chat_colors: bytebuf.get_bool()?,
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::CONFIG_COOKIE_RESPONSE;
|
use pumpkin_data::packet::serverbound::CONFIG_COOKIE_RESPONSE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
|
|
||||||
use crate::{ReadingError, ServerPacket, ser::NetworkReadExt};
|
use crate::{
|
||||||
|
ReadingError, ServerPacket,
|
||||||
|
ser::{NetworkReadExt, NetworkReadSliceExt},
|
||||||
|
};
|
||||||
|
|
||||||
/// The maximum allowed size for a cookie payload (5 KiB).
|
/// The maximum allowed size for a cookie payload (5 KiB).
|
||||||
const MAX_COOKIE_LENGTH: usize = 5120;
|
const MAX_COOKIE_LENGTH: usize = 5120;
|
||||||
@ -14,19 +15,18 @@ const MAX_COOKIE_LENGTH: usize = 5120;
|
|||||||
/// Cookies allow servers to store small amounts of data on the client side,
|
/// Cookies allow servers to store small amounts of data on the client side,
|
||||||
/// which can be retrieved later (e.g., for session tracking or preferences)
|
/// which can be retrieved later (e.g., for session tracking or preferences)
|
||||||
#[java_packet(CONFIG_COOKIE_RESPONSE)]
|
#[java_packet(CONFIG_COOKIE_RESPONSE)]
|
||||||
pub struct SConfigCookieResponse {
|
pub struct SConfigCookieResponse<'a> {
|
||||||
/// The unique identifier for the cookie being returned
|
/// The unique identifier for the cookie being returned
|
||||||
pub key: Box<str>,
|
pub key: &'a str,
|
||||||
/// Indicates whether a payload is attached to this response
|
/// Indicates whether a payload is attached to this response
|
||||||
pub has_payload: bool,
|
pub has_payload: bool,
|
||||||
/// The actual data stored in the cookie. Limited to 5120 bytes
|
/// The actual data stored in the cookie. Limited to 5120 bytes
|
||||||
pub payload: Option<Box<[u8]>>,
|
pub payload: Option<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SConfigCookieResponse {
|
impl<'a> ServerPacket<'a> for SConfigCookieResponse<'a> {
|
||||||
fn read(read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
let mut read = read;
|
let key = read.get_str_borrowed()?;
|
||||||
let key = read.get_str()?;
|
|
||||||
let has_payload = read.get_bool()?;
|
let has_payload = read.get_bool()?;
|
||||||
|
|
||||||
if !has_payload {
|
if !has_payload {
|
||||||
@ -42,7 +42,7 @@ impl ServerPacket for SConfigCookieResponse {
|
|||||||
return Err(ReadingError::TooLarge("SConfigCookieResponse".to_string()));
|
return Err(ReadingError::TooLarge("SConfigCookieResponse".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = read.read_boxed_slice(payload_length)?;
|
let payload = read.read_slice_borrowed(payload_length)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
key,
|
key,
|
||||||
has_payload,
|
has_payload,
|
||||||
|
|||||||
@ -1,25 +1,22 @@
|
|||||||
use pumpkin_data::packet::serverbound::CONFIG_CUSTOM_CLICK_ACTION;
|
|
||||||
use pumpkin_macros::java_packet;
|
|
||||||
use pumpkin_util::resource_location::ResourceLocation;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
|
use pumpkin_data::packet::serverbound::CONFIG_CUSTOM_CLICK_ACTION;
|
||||||
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(CONFIG_CUSTOM_CLICK_ACTION)]
|
#[java_packet(CONFIG_CUSTOM_CLICK_ACTION)]
|
||||||
pub struct SCustomClickAction {
|
pub struct SCustomClickAction<'a> {
|
||||||
pub action_id: ResourceLocation,
|
pub action_id: &'a str,
|
||||||
pub payload: Option<Box<[u8]>>,
|
pub payload: Option<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SCustomClickAction {
|
impl<'a> ServerPacket<'a> for SCustomClickAction<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
action_id: bytebuf.get_str()?.into_string(),
|
action_id: bytebuf.get_str_borrowed()?,
|
||||||
payload: bytebuf.get_option(|v| v.read_remaining_to_boxed_slice(32767))?,
|
payload: bytebuf.get_option(|v| v.read_remaining_slice_borrowed(32767))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,15 +6,14 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(CONFIG_KEEP_ALIVE)]
|
#[java_packet(CONFIG_KEEP_ALIVE)]
|
||||||
pub struct SKeepAlive {
|
pub struct SKeepAlive {
|
||||||
pub keep_alive_id: i64,
|
pub keep_alive_id: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SKeepAlive {
|
impl<'a> ServerPacket<'a> for SKeepAlive {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
keep_alive_id: bytebuf.get_i64_be()?,
|
keep_alive_id: bytebuf.get_i64_be()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -8,7 +8,6 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(CONFIG_SELECT_KNOWN_PACKS)]
|
#[java_packet(CONFIG_SELECT_KNOWN_PACKS)]
|
||||||
pub struct SKnownPacks {
|
pub struct SKnownPacks {
|
||||||
@ -16,8 +15,8 @@ pub struct SKnownPacks {
|
|||||||
// known_packs: &'a [KnownPack]
|
// known_packs: &'a [KnownPack]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SKnownPacks {
|
impl<'a> ServerPacket<'a> for SKnownPacks {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
known_pack_count: bytebuf.get_var_int()?,
|
known_pack_count: bytebuf.get_var_int()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::CONFIG_CUSTOM_PAYLOAD;
|
use pumpkin_data::packet::serverbound::CONFIG_CUSTOM_PAYLOAD;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
|
|
||||||
use crate::{ReadingError, ServerPacket, ser::NetworkReadExt};
|
use crate::{ReadingError, ServerPacket, ser::NetworkReadSliceExt};
|
||||||
|
|
||||||
/// The maximum allowed size for a plugin message payload (1 MiB).
|
/// The maximum allowed size for a plugin message payload (1 MiB).
|
||||||
const MAX_PAYLOAD_SIZE: usize = 1_048_576;
|
const MAX_PAYLOAD_SIZE: usize = 1_048_576;
|
||||||
@ -14,19 +12,19 @@ const MAX_PAYLOAD_SIZE: usize = 1_048_576;
|
|||||||
/// This allows mods, plugins, or proxy
|
/// This allows mods, plugins, or proxy
|
||||||
/// software to send proprietary data over the standard Minecraft protocol.
|
/// software to send proprietary data over the standard Minecraft protocol.
|
||||||
#[java_packet(CONFIG_CUSTOM_PAYLOAD)]
|
#[java_packet(CONFIG_CUSTOM_PAYLOAD)]
|
||||||
pub struct SPluginMessage {
|
pub struct SPluginMessage<'a> {
|
||||||
/// The name of the channel used to distinguish different types of messages.
|
/// The name of the channel used to distinguish different types of messages.
|
||||||
/// Example: `minecraft:brand` or `velocity:main`.
|
/// Example: `minecraft:brand` or `velocity:main`.
|
||||||
pub channel: Box<str>,
|
pub channel: &'a str,
|
||||||
/// The payload sent by the client.
|
/// The payload sent by the client.
|
||||||
pub data: Box<[u8]>,
|
pub data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPluginMessage {
|
impl<'a> ServerPacket<'a> for SPluginMessage<'a> {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
channel: read.get_str()?,
|
channel: read.get_str_borrowed()?,
|
||||||
data: read.read_remaining_to_boxed_slice(MAX_PAYLOAD_SIZE)?,
|
data: read.read_remaining_slice_borrowed(MAX_PAYLOAD_SIZE)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -34,8 +33,8 @@ pub struct SConfigResourcePack {
|
|||||||
pub result: VarInt,
|
pub result: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SConfigResourcePack {
|
impl<'a> ServerPacket<'a> for SConfigResourcePack {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
uuid: bytebuf.get_uuid()?,
|
uuid: bytebuf.get_uuid()?,
|
||||||
result: bytebuf.get_var_int()?,
|
result: bytebuf.get_var_int()?,
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ClientPacket, ConnectionState, ReadingError, ServerPacket, VarInt, ser::NetworkReadExt,
|
ClientPacket, ConnectionState, ReadingError, ServerPacket, VarInt, ser::NetworkReadExt,
|
||||||
ser::NetworkWriteExt,
|
ser::NetworkWriteExt,
|
||||||
@ -24,8 +22,8 @@ pub struct SHandShake {
|
|||||||
pub next_state: ConnectionState,
|
pub next_state: ConnectionState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SHandShake {
|
impl<'a> ServerPacket<'a> for SHandShake {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
protocol_version: read.get_var_int()?,
|
protocol_version: read.get_var_int()?,
|
||||||
server_address: read.get_str_bounded(255)?,
|
server_address: read.get_str_bounded(255)?,
|
||||||
|
|||||||
@ -1,26 +1,25 @@
|
|||||||
use pumpkin_data::packet::serverbound::LOGIN_COOKIE_RESPONSE;
|
use pumpkin_data::packet::serverbound::LOGIN_COOKIE_RESPONSE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[java_packet(LOGIN_COOKIE_RESPONSE)]
|
#[java_packet(LOGIN_COOKIE_RESPONSE)]
|
||||||
/// Response to a `CCookieRequest` (login) from the server.
|
/// Response to a `CCookieRequest` (login) from the server.
|
||||||
/// The Notchian server only accepts responses of up to 5 kiB in size.
|
/// The Notchian server only accepts responses of up to 5 kiB in size.
|
||||||
pub struct SLoginCookieResponse {
|
pub struct SLoginCookieResponse<'a> {
|
||||||
pub key: Box<str>,
|
pub key: &'a str,
|
||||||
pub payload: Option<Box<[u8]>>, // 5120,
|
pub payload: Option<&'a [u8]>, // 5120,
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_COOKIE_LENGTH: usize = 5120;
|
const MAX_COOKIE_LENGTH: usize = 5120;
|
||||||
|
|
||||||
impl ServerPacket for SLoginCookieResponse {
|
impl<'a> ServerPacket<'a> for SLoginCookieResponse<'a> {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
let key = read.get_str()?;
|
let key = read.get_str_borrowed()?;
|
||||||
let has_payload = read.get_bool()?;
|
let has_payload = read.get_bool()?;
|
||||||
|
|
||||||
if !has_payload {
|
if !has_payload {
|
||||||
@ -33,7 +32,7 @@ impl ServerPacket for SLoginCookieResponse {
|
|||||||
return Err(ReadingError::TooLarge("SLoginCookieResponse".to_string()));
|
return Err(ReadingError::TooLarge("SLoginCookieResponse".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = read.read_boxed_slice(length)?;
|
let payload = read.read_slice_borrowed(length)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
key,
|
key,
|
||||||
|
|||||||
@ -1,26 +1,36 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::LOGIN_KEY;
|
use pumpkin_data::packet::serverbound::LOGIN_KEY;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
|
|
||||||
use crate::{ReadingError, ServerPacket, ser::NetworkReadExt};
|
use crate::{ReadingError, ServerPacket, ser::NetworkReadExt};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
#[java_packet(LOGIN_KEY)]
|
#[java_packet(LOGIN_KEY)]
|
||||||
pub struct SEncryptionResponse {
|
pub struct SEncryptionResponse {
|
||||||
pub shared_secret: Box<[u8]>,
|
pub shared_secret: Box<[u8]>,
|
||||||
pub verify_token: Box<[u8]>,
|
pub verify_token: Box<[u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SEncryptionResponse {
|
impl<'a> ServerPacket<'a> for SEncryptionResponse {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(
|
||||||
let shared_secret_length = read.get_var_int()?.0 as usize;
|
mut read: &mut &'a [u8],
|
||||||
let shared_secret = read.read_boxed_slice(shared_secret_length)?;
|
_version: &JavaMinecraftVersion,
|
||||||
let verify_token_length = read.get_var_int()?.0 as usize;
|
) -> Result<Self, ReadingError> {
|
||||||
let verify_token = read.read_boxed_slice(verify_token_length)?;
|
let shared_secret = read_encryption_buffer(&mut read)?;
|
||||||
|
let verify_token = read_encryption_buffer(&mut read)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
shared_secret,
|
shared_secret,
|
||||||
verify_token,
|
verify_token,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_encryption_buffer(read: &mut impl NetworkReadExt) -> Result<Box<[u8]>, ReadingError> {
|
||||||
|
let length = read.get_var_int()?.0 as usize;
|
||||||
|
if length > 256 {
|
||||||
|
return Err(ReadingError::Message("Encryption payload too large".into()));
|
||||||
|
}
|
||||||
|
let mut data = vec![0u8; length];
|
||||||
|
read.read_bytes_to_buf(&mut data)?;
|
||||||
|
Ok(data.into_boxed_slice())
|
||||||
|
}
|
||||||
|
|||||||
@ -3,14 +3,16 @@ use pumpkin_macros::java_packet;
|
|||||||
|
|
||||||
use crate::{ServerPacket, ser::ReadingError};
|
use crate::{ServerPacket, ser::ReadingError};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
/// Acknowledgement to the `CLoginSuccess` packet sent by the server.
|
/// Acknowledgement to the `CLoginSuccess` packet sent by the server.
|
||||||
#[java_packet(LOGIN_LOGIN_ACKNOWLEDGED)]
|
#[java_packet(LOGIN_LOGIN_ACKNOWLEDGED)]
|
||||||
pub struct SLoginAcknowledged;
|
pub struct SLoginAcknowledged;
|
||||||
|
|
||||||
impl ServerPacket for SLoginAcknowledged {
|
impl<'a> ServerPacket<'a> for SLoginAcknowledged {
|
||||||
fn read(_bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(
|
||||||
|
_bytebuf: &mut &'a [u8],
|
||||||
|
_version: &JavaMinecraftVersion,
|
||||||
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self)
|
Ok(Self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::LOGIN_HELLO;
|
use pumpkin_data::packet::serverbound::LOGIN_HELLO;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
@ -15,8 +13,8 @@ pub struct SLoginStart {
|
|||||||
pub uuid: uuid::Uuid,
|
pub uuid: uuid::Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SLoginStart {
|
impl<'a> ServerPacket<'a> for SLoginStart {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
name: read.get_str_bounded(16)?,
|
name: read.get_str_bounded(16)?,
|
||||||
uuid: read.get_uuid()?,
|
uuid: read.get_uuid()?,
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::{ReadingError, ServerPacket, VarInt, ser::NetworkReadExt};
|
use crate::{ReadingError, ServerPacket, VarInt, ser::NetworkReadExt};
|
||||||
use pumpkin_data::packet::serverbound::LOGIN_CUSTOM_QUERY_ANSWER;
|
use pumpkin_data::packet::serverbound::LOGIN_CUSTOM_QUERY_ANSWER;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
@ -13,11 +11,11 @@ pub struct SLoginPluginResponse {
|
|||||||
pub data: Option<Box<[u8]>>,
|
pub data: Option<Box<[u8]>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SLoginPluginResponse {
|
impl<'a> ServerPacket<'a> for SLoginPluginResponse {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
message_id: read.get_var_int()?,
|
message_id: read.get_var_int()?,
|
||||||
data: read.get_option(|v| v.read_remaining_to_boxed_slice(MAX_PAYLOAD_SIZE))?,
|
data: read.get_option(|v| crate::ser::read_remaining_bytes(v, MAX_PAYLOAD_SIZE))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_ATTACK;
|
use pumpkin_data::packet::serverbound::PLAY_ATTACK;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::codec::var_int::VarInt;
|
use crate::codec::var_int::VarInt;
|
||||||
|
|
||||||
@ -14,9 +13,9 @@ pub struct SAttack {
|
|||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SAttack {
|
impl<'a> ServerPacket<'a> for SAttack {
|
||||||
fn read(
|
fn read(
|
||||||
mut bytebuf: impl Read,
|
bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@ -8,7 +8,6 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_BUNDLE_ITEM_SELECTED)]
|
#[java_packet(PLAY_BUNDLE_ITEM_SELECTED)]
|
||||||
pub struct SBundleItemSelected {
|
pub struct SBundleItemSelected {
|
||||||
@ -16,8 +15,8 @@ pub struct SBundleItemSelected {
|
|||||||
pub selected_item_index: VarInt,
|
pub selected_item_index: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SBundleItemSelected {
|
impl<'a> ServerPacket<'a> for SBundleItemSelected {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
slot_id: bytebuf.get_var_int()?,
|
slot_id: bytebuf.get_var_int()?,
|
||||||
selected_item_index: bytebuf.get_var_int()?,
|
selected_item_index: bytebuf.get_var_int()?,
|
||||||
|
|||||||
@ -6,15 +6,14 @@ use pumpkin_data::packet::serverbound::PLAY_CHANGE_GAME_MODE;
|
|||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::GameMode;
|
use pumpkin_util::GameMode;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_CHANGE_GAME_MODE)]
|
#[java_packet(PLAY_CHANGE_GAME_MODE)]
|
||||||
pub struct SChangeGameMode {
|
pub struct SChangeGameMode {
|
||||||
pub game_mode: GameMode,
|
pub game_mode: GameMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SChangeGameMode {
|
impl<'a> ServerPacket<'a> for SChangeGameMode {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
game_mode: GameMode::try_from(bytebuf.get_u8()? as i8)
|
game_mode: GameMode::try_from(bytebuf.get_u8()? as i8)
|
||||||
.map_err(|()| crate::ser::ReadingError::Message("Invalid game mode".into()))?,
|
.map_err(|()| crate::ser::ReadingError::Message("Invalid game mode".into()))?,
|
||||||
|
|||||||
@ -3,20 +3,19 @@ use pumpkin_macros::java_packet;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_CHAT_COMMAND)]
|
#[java_packet(PLAY_CHAT_COMMAND)]
|
||||||
pub struct SChatCommand {
|
pub struct SChatCommand<'a> {
|
||||||
pub command: String,
|
pub command: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SChatCommand {
|
impl<'a> ServerPacket<'a> for SChatCommand<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
command: bytebuf.get_str()?.into_string(),
|
command: bytebuf.get_str_borrowed()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::PLAY_CHAT;
|
use pumpkin_data::packet::serverbound::PLAY_CHAT;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
@ -8,46 +6,46 @@ use crate::{
|
|||||||
ClientPacket, ServerPacket,
|
ClientPacket, ServerPacket,
|
||||||
codec::var_int::VarInt,
|
codec::var_int::VarInt,
|
||||||
ser::NetworkWriteExt,
|
ser::NetworkWriteExt,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[java_packet(PLAY_CHAT)]
|
#[java_packet(PLAY_CHAT)]
|
||||||
pub struct SChatMessage {
|
pub struct SChatMessage<'a> {
|
||||||
pub message: Box<str>,
|
pub message: &'a str,
|
||||||
pub timestamp: i64,
|
pub timestamp: i64,
|
||||||
pub salt: i64,
|
pub salt: i64,
|
||||||
pub signature: Option<Box<[u8]>>,
|
pub signature: Option<&'a [u8]>,
|
||||||
pub message_count: VarInt,
|
pub message_count: VarInt,
|
||||||
pub acknowledged: Box<[u8]>, // Bitset fixed 20 bits
|
pub acknowledged: &'a [u8], // Bitset fixed 20 bits
|
||||||
pub checksum: u8, // 1.21.5 "fingerprint" checksum
|
pub checksum: u8, // 1.21.5 "fingerprint" checksum
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SChatMessage {
|
impl<'a> ServerPacket<'a> for SChatMessage<'a> {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
message: read.get_str_bounded(256)?,
|
message: read.get_str_bounded_borrowed(256)?,
|
||||||
timestamp: read.get_i64_be()?,
|
timestamp: read.get_i64_be()?,
|
||||||
salt: read.get_i64_be()?,
|
salt: read.get_i64_be()?,
|
||||||
signature: read.get_option(|v| v.read_boxed_slice(256))?,
|
signature: read.get_option(|v| v.read_slice_borrowed(256))?,
|
||||||
message_count: read.get_var_int()?,
|
message_count: read.get_var_int()?,
|
||||||
acknowledged: read.get_fixed_bitset(20)?,
|
acknowledged: read.read_slice_borrowed(3)?,
|
||||||
checksum: read.get_u8()?,
|
checksum: read.get_u8()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientPacket for SChatMessage {
|
impl ClientPacket for SChatMessage<'_> {
|
||||||
fn write_packet_data(
|
fn write_packet_data(
|
||||||
&self,
|
&self,
|
||||||
mut write: impl std::io::Write,
|
mut write: impl std::io::Write,
|
||||||
_version: &JavaMinecraftVersion,
|
_version: &JavaMinecraftVersion,
|
||||||
) -> Result<(), crate::ser::WritingError> {
|
) -> Result<(), crate::ser::WritingError> {
|
||||||
write.write_string(&self.message)?;
|
write.write_string(self.message)?;
|
||||||
write.write_i64_be(self.timestamp)?;
|
write.write_i64_be(self.timestamp)?;
|
||||||
write.write_i64_be(self.salt)?;
|
write.write_i64_be(self.salt)?;
|
||||||
write.write_option(&self.signature, |p, v| p.write_slice(v))?;
|
write.write_option(&self.signature, |p, v| p.write_slice(v))?;
|
||||||
write.write_var_int(&self.message_count)?;
|
write.write_var_int(&self.message_count)?;
|
||||||
write.write_fixed_bitset(20, self.acknowledged.clone())?;
|
write.write_slice(self.acknowledged)?;
|
||||||
write.write_u8(self.checksum)?;
|
write.write_u8(self.checksum)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -5,15 +5,14 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_CHUNK_BATCH_RECEIVED;
|
use pumpkin_data::packet::serverbound::PLAY_CHUNK_BATCH_RECEIVED;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_CHUNK_BATCH_RECEIVED)]
|
#[java_packet(PLAY_CHUNK_BATCH_RECEIVED)]
|
||||||
pub struct SChunkBatch {
|
pub struct SChunkBatch {
|
||||||
pub chunks_per_tick: f32,
|
pub chunks_per_tick: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SChunkBatch {
|
impl<'a> ServerPacket<'a> for SChunkBatch {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
chunks_per_tick: bytebuf.get_f32_be()?,
|
chunks_per_tick: bytebuf.get_f32_be()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -22,8 +22,11 @@ pub struct SClickSlot {
|
|||||||
pub carried_item: OptionalItemStackHash,
|
pub carried_item: OptionalItemStackHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SClickSlot {
|
impl<'a> ServerPacket<'a> for SClickSlot {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(
|
||||||
|
mut bytebuf: &mut &'a [u8],
|
||||||
|
_version: &JavaMinecraftVersion,
|
||||||
|
) -> Result<Self, ReadingError> {
|
||||||
let sync_id = bytebuf.get_var_int()?;
|
let sync_id = bytebuf.get_var_int()?;
|
||||||
let revision = bytebuf.get_var_int()?;
|
let revision = bytebuf.get_var_int()?;
|
||||||
let slot = bytebuf.get_i16_be()?;
|
let slot = bytebuf.get_i16_be()?;
|
||||||
@ -31,6 +34,11 @@ impl ServerPacket for SClickSlot {
|
|||||||
let mode = SlotActionType::read(&mut bytebuf)?;
|
let mode = SlotActionType::read(&mut bytebuf)?;
|
||||||
|
|
||||||
let length_of_array = bytebuf.get_var_int()?;
|
let length_of_array = bytebuf.get_var_int()?;
|
||||||
|
if length_of_array.0 < 0 || length_of_array.0 > 256 {
|
||||||
|
return Err(ReadingError::Message(
|
||||||
|
"Changed slots length out of bounds".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
let mut array_of_changed_slots = Vec::with_capacity(length_of_array.0 as usize);
|
let mut array_of_changed_slots = Vec::with_capacity(length_of_array.0 as usize);
|
||||||
for _ in 0..length_of_array.0 {
|
for _ in 0..length_of_array.0 {
|
||||||
array_of_changed_slots.push((
|
array_of_changed_slots.push((
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_CLIENT_COMMAND;
|
use pumpkin_data::packet::serverbound::PLAY_CLIENT_COMMAND;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -14,8 +13,8 @@ pub struct SClientCommand {
|
|||||||
pub action_id: VarInt,
|
pub action_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SClientCommand {
|
impl<'a> ServerPacket<'a> for SClientCommand {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
action_id: bytebuf.get_var_int()?,
|
action_id: bytebuf.get_var_int()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,17 +1,16 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_data::packet::serverbound::PLAY_CLIENT_INFORMATION;
|
use pumpkin_data::packet::serverbound::PLAY_CLIENT_INFORMATION;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
#[java_packet(PLAY_CLIENT_INFORMATION)]
|
#[java_packet(PLAY_CLIENT_INFORMATION)]
|
||||||
pub struct SClientInformationPlay {
|
pub struct SClientInformationPlay<'a> {
|
||||||
pub locale: String, // 16
|
pub locale: &'a str, // 16
|
||||||
pub view_distance: i8,
|
pub view_distance: i8,
|
||||||
pub chat_mode: VarInt, // VarInt
|
pub chat_mode: VarInt, // VarInt
|
||||||
pub chat_colors: bool,
|
pub chat_colors: bool,
|
||||||
@ -21,10 +20,10 @@ pub struct SClientInformationPlay {
|
|||||||
pub server_listing: bool,
|
pub server_listing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SClientInformationPlay {
|
impl<'a> ServerPacket<'a> for SClientInformationPlay<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
locale: bytebuf.get_str()?.to_string(),
|
locale: bytebuf.get_str_borrowed()?,
|
||||||
view_distance: bytebuf.get_i8()?,
|
view_distance: bytebuf.get_i8()?,
|
||||||
chat_mode: bytebuf.get_var_int()?,
|
chat_mode: bytebuf.get_var_int()?,
|
||||||
chat_colors: bytebuf.get_bool()?,
|
chat_colors: bytebuf.get_bool()?,
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_CONTAINER_CLOSE;
|
use pumpkin_data::packet::serverbound::PLAY_CONTAINER_CLOSE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -14,8 +13,8 @@ pub struct SCloseContainer {
|
|||||||
pub window_id: VarInt,
|
pub window_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SCloseContainer {
|
impl<'a> ServerPacket<'a> for SCloseContainer {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
window_id: bytebuf.get_var_int()?,
|
window_id: bytebuf.get_var_int()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,22 +5,21 @@ use crate::VarInt;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_COMMAND_SUGGESTION)]
|
#[java_packet(PLAY_COMMAND_SUGGESTION)]
|
||||||
pub struct SCommandSuggestion {
|
pub struct SCommandSuggestion<'a> {
|
||||||
pub id: VarInt,
|
pub id: VarInt,
|
||||||
pub command: String,
|
pub command: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SCommandSuggestion {
|
impl<'a> ServerPacket<'a> for SCommandSuggestion<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: bytebuf.get_var_int()?,
|
id: bytebuf.get_var_int()?,
|
||||||
command: bytebuf.get_str()?.into_string(),
|
command: bytebuf.get_str_borrowed()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_ACCEPT_TELEPORTATION;
|
use pumpkin_data::packet::serverbound::PLAY_ACCEPT_TELEPORTATION;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -14,8 +13,8 @@ pub struct SConfirmTeleport {
|
|||||||
pub teleport_id: VarInt,
|
pub teleport_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SConfirmTeleport {
|
impl<'a> ServerPacket<'a> for SConfirmTeleport {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
teleport_id: bytebuf.get_var_int()?,
|
teleport_id: bytebuf.get_var_int()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -7,7 +7,6 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[java_packet(PLAY_CONTAINER_BUTTON_CLICK)]
|
#[java_packet(PLAY_CONTAINER_BUTTON_CLICK)]
|
||||||
@ -16,8 +15,8 @@ pub struct SContainerButtonClick {
|
|||||||
pub button_id: VarInt,
|
pub button_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SContainerButtonClick {
|
impl<'a> ServerPacket<'a> for SContainerButtonClick {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
window_id: bytebuf.get_var_int()?,
|
window_id: bytebuf.get_var_int()?,
|
||||||
button_id: bytebuf.get_var_int()?,
|
button_id: bytebuf.get_var_int()?,
|
||||||
|
|||||||
@ -1,27 +1,25 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::PLAY_COOKIE_RESPONSE;
|
use pumpkin_data::packet::serverbound::PLAY_COOKIE_RESPONSE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[java_packet(PLAY_COOKIE_RESPONSE)]
|
#[java_packet(PLAY_COOKIE_RESPONSE)]
|
||||||
/// Response to a `CCookieRequest` (play) from the server.
|
/// Response to a `CCookieRequest` (play) from the server.
|
||||||
/// The Notchian (vanilla) server only accepts responses of up to 5 KiB in size.
|
/// The Notchian (vanilla) server only accepts responses of up to 5 KiB in size.
|
||||||
pub struct SCookieResponse {
|
pub struct SCookieResponse<'a> {
|
||||||
pub key: Box<str>,
|
pub key: &'a str,
|
||||||
pub payload: Option<Box<[u8]>>, // 5120,
|
pub payload: Option<&'a [u8]>, // 5120,
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_COOKIE_LENGTH: usize = 5120;
|
const MAX_COOKIE_LENGTH: usize = 5120;
|
||||||
|
|
||||||
impl ServerPacket for SCookieResponse {
|
impl<'a> ServerPacket<'a> for SCookieResponse<'a> {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
let key = read.get_str()?;
|
let key = read.get_str_borrowed()?;
|
||||||
let has_payload = read.get_bool()?;
|
let has_payload = read.get_bool()?;
|
||||||
|
|
||||||
if !has_payload {
|
if !has_payload {
|
||||||
@ -33,7 +31,7 @@ impl ServerPacket for SCookieResponse {
|
|||||||
return Err(ReadingError::TooLarge("SCookieResponse".to_string()));
|
return Err(ReadingError::TooLarge("SCookieResponse".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = read.read_boxed_slice(payload_length)?;
|
let payload = read.read_slice_borrowed(payload_length)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
key,
|
key,
|
||||||
|
|||||||
@ -1,24 +1,22 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_data::packet::serverbound::PLAY_CUSTOM_CLICK_ACTION;
|
use pumpkin_data::packet::serverbound::PLAY_CUSTOM_CLICK_ACTION;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::resource_location::ResourceLocation;
|
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_CUSTOM_CLICK_ACTION)]
|
#[java_packet(PLAY_CUSTOM_CLICK_ACTION)]
|
||||||
pub struct SCustomClickAction {
|
pub struct SCustomClickAction<'a> {
|
||||||
pub action_id: ResourceLocation,
|
pub action_id: &'a str,
|
||||||
pub payload: Option<Box<[u8]>>,
|
pub payload: Option<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SCustomClickAction {
|
impl<'a> ServerPacket<'a> for SCustomClickAction<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
action_id: bytebuf.get_str()?.to_string(),
|
action_id: bytebuf.get_str_borrowed()?,
|
||||||
payload: bytebuf.get_option(|b| b.read_remaining_to_boxed_slice(32767))?,
|
payload: bytebuf.get_option(|b| b.read_remaining_slice_borrowed(32767))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::PLAY_CUSTOM_PAYLOAD;
|
use pumpkin_data::packet::serverbound::PLAY_CUSTOM_PAYLOAD;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
|
|
||||||
use crate::{ReadingError, ServerPacket, ser::NetworkReadExt};
|
use crate::{ReadingError, ServerPacket, ser::NetworkReadSliceExt};
|
||||||
|
|
||||||
/// The maximum allowed size for a play custom payload (32 KiB).
|
/// The maximum allowed size for a play custom payload (32 KiB).
|
||||||
const MAX_PAYLOAD_SIZE: usize = 32_767;
|
const MAX_PAYLOAD_SIZE: usize = 32_767;
|
||||||
@ -14,19 +12,19 @@ const MAX_PAYLOAD_SIZE: usize = 32_767;
|
|||||||
/// This allows mods, plugins, or proxy software to send proprietary data over the standard
|
/// This allows mods, plugins, or proxy software to send proprietary data over the standard
|
||||||
/// Minecraft protocol.
|
/// Minecraft protocol.
|
||||||
#[java_packet(PLAY_CUSTOM_PAYLOAD)]
|
#[java_packet(PLAY_CUSTOM_PAYLOAD)]
|
||||||
pub struct SCustomPayload {
|
pub struct SCustomPayload<'a> {
|
||||||
/// The name of the channel used to distinguish different types of messages.
|
/// The name of the channel used to distinguish different types of messages.
|
||||||
/// Example: `minecraft:brand` or `voicechat:request_secret`.
|
/// Example: `minecraft:brand` or `voicechat:request_secret`.
|
||||||
pub channel: Box<str>,
|
pub channel: &'a str,
|
||||||
/// The payload sent by the client.
|
/// The payload sent by the client.
|
||||||
pub data: Box<[u8]>,
|
pub data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SCustomPayload {
|
impl<'a> ServerPacket<'a> for SCustomPayload<'a> {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
channel: read.get_str()?,
|
channel: read.get_str_borrowed()?,
|
||||||
data: read.read_remaining_to_boxed_slice(MAX_PAYLOAD_SIZE)?,
|
data: read.read_remaining_slice_borrowed(MAX_PAYLOAD_SIZE)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::PLAY_INTERACT;
|
use pumpkin_data::packet::serverbound::PLAY_INTERACT;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::{math::vector3::Vector3, version::JavaMinecraftVersion};
|
use pumpkin_util::{math::vector3::Vector3, version::JavaMinecraftVersion};
|
||||||
@ -20,8 +18,8 @@ pub struct SInteract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Great job Mojang ;D
|
// Great job Mojang ;D
|
||||||
impl ServerPacket for SInteract {
|
impl<'a> ServerPacket<'a> for SInteract {
|
||||||
fn read(mut read: impl Read, version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(mut read: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
// 26.1+ removes the 'type' field and uses doubles for location
|
// 26.1+ removes the 'type' field and uses doubles for location
|
||||||
if version >= &JavaMinecraftVersion::V_26_1 {
|
if version >= &JavaMinecraftVersion::V_26_1 {
|
||||||
let entity_id = read.get_var_int()?;
|
let entity_id = read.get_var_int()?;
|
||||||
|
|||||||
@ -6,7 +6,6 @@ use pumpkin_data::packet::serverbound::PLAY_JIGSAW_GENERATE;
|
|||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::codec::var_int::VarInt;
|
use crate::codec::var_int::VarInt;
|
||||||
|
|
||||||
@ -17,9 +16,9 @@ pub struct SJigsawGenerate {
|
|||||||
pub keep_jigsaws: bool,
|
pub keep_jigsaws: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SJigsawGenerate {
|
impl<'a> ServerPacket<'a> for SJigsawGenerate {
|
||||||
fn read(
|
fn read(
|
||||||
mut bytebuf: impl Read,
|
bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@ -6,15 +6,14 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_KEEP_ALIVE)]
|
#[java_packet(PLAY_KEEP_ALIVE)]
|
||||||
pub struct SKeepAlive {
|
pub struct SKeepAlive {
|
||||||
pub keep_alive_id: i64,
|
pub keep_alive_id: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SKeepAlive {
|
impl<'a> ServerPacket<'a> for SKeepAlive {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
keep_alive_id: bytebuf.get_i64_be()?,
|
keep_alive_id: bytebuf.get_i64_be()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_MOVE_VEHICLE;
|
use pumpkin_data::packet::serverbound::PLAY_MOVE_VEHICLE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_MOVE_VEHICLE)]
|
#[java_packet(PLAY_MOVE_VEHICLE)]
|
||||||
pub struct SMoveVehicle {
|
pub struct SMoveVehicle {
|
||||||
@ -16,9 +15,9 @@ pub struct SMoveVehicle {
|
|||||||
pub pitch: f32,
|
pub pitch: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SMoveVehicle {
|
impl<'a> ServerPacket<'a> for SMoveVehicle {
|
||||||
fn read(
|
fn read(
|
||||||
mut bytebuf: impl Read,
|
bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@ -6,7 +6,6 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_PADDLE_BOAT)]
|
#[java_packet(PLAY_PADDLE_BOAT)]
|
||||||
pub struct SPaddleBoat {
|
pub struct SPaddleBoat {
|
||||||
@ -14,8 +13,8 @@ pub struct SPaddleBoat {
|
|||||||
pub right_paddle: bool,
|
pub right_paddle: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPaddleBoat {
|
impl<'a> ServerPacket<'a> for SPaddleBoat {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
left_paddle: bytebuf.get_bool()?,
|
left_paddle: bytebuf.get_bool()?,
|
||||||
right_paddle: bytebuf.get_bool()?,
|
right_paddle: bytebuf.get_bool()?,
|
||||||
|
|||||||
@ -8,7 +8,6 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_PICK_ITEM_FROM_BLOCK)]
|
#[java_packet(PLAY_PICK_ITEM_FROM_BLOCK)]
|
||||||
pub struct SPickItemFromBlock {
|
pub struct SPickItemFromBlock {
|
||||||
@ -16,8 +15,8 @@ pub struct SPickItemFromBlock {
|
|||||||
pub include_data: bool,
|
pub include_data: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPickItemFromBlock {
|
impl<'a> ServerPacket<'a> for SPickItemFromBlock {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
pos: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
pos: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
||||||
include_data: bytebuf.get_bool()?,
|
include_data: bytebuf.get_bool()?,
|
||||||
@ -31,8 +30,8 @@ pub struct SPickItemFromEntity {
|
|||||||
pub include_data: bool,
|
pub include_data: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPickItemFromEntity {
|
impl<'a> ServerPacket<'a> for SPickItemFromEntity {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: bytebuf.get_var_int()?,
|
id: bytebuf.get_var_int()?,
|
||||||
include_data: bytebuf.get_bool()?,
|
include_data: bytebuf.get_bool()?,
|
||||||
|
|||||||
@ -6,15 +6,14 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_PING_REQUEST)]
|
#[java_packet(PLAY_PING_REQUEST)]
|
||||||
pub struct SPlayPingRequest {
|
pub struct SPlayPingRequest {
|
||||||
pub payload: i64,
|
pub payload: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlayPingRequest {
|
impl<'a> ServerPacket<'a> for SPlayPingRequest {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
payload: bytebuf.get_i64_be()?,
|
payload: bytebuf.get_i64_be()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_PLACE_RECIPE;
|
use pumpkin_data::packet::serverbound::PLAY_PLACE_RECIPE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -16,8 +15,8 @@ pub struct SPlaceRecipe {
|
|||||||
pub use_max_items: bool,
|
pub use_max_items: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlaceRecipe {
|
impl<'a> ServerPacket<'a> for SPlaceRecipe {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
container_id: bytebuf.get_i8()?,
|
container_id: bytebuf.get_i8()?,
|
||||||
recipe_display_id: bytebuf.get_var_int()?,
|
recipe_display_id: bytebuf.get_var_int()?,
|
||||||
|
|||||||
@ -8,15 +8,14 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_PLAYER_ABILITIES)]
|
#[java_packet(PLAY_PLAYER_ABILITIES)]
|
||||||
pub struct SPlayerAbilities {
|
pub struct SPlayerAbilities {
|
||||||
pub flags: i8,
|
pub flags: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlayerAbilities {
|
impl<'a> ServerPacket<'a> for SPlayerAbilities {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
flags: bytebuf.get_i8()?,
|
flags: bytebuf.get_i8()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -6,7 +6,6 @@ use pumpkin_data::packet::serverbound::PLAY_PLAYER_ACTION;
|
|||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -18,9 +17,9 @@ pub struct SPlayerAction {
|
|||||||
pub sequence: VarInt,
|
pub sequence: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlayerAction {
|
impl<'a> ServerPacket<'a> for SPlayerAction {
|
||||||
fn read(
|
fn read(
|
||||||
mut bytebuf: impl Read,
|
bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::PLAY_PLAYER_COMMAND;
|
use pumpkin_data::packet::serverbound::PLAY_PLAYER_COMMAND;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
@ -33,8 +31,8 @@ pub enum Action {
|
|||||||
|
|
||||||
pub struct InvalidAction;
|
pub struct InvalidAction;
|
||||||
|
|
||||||
impl ServerPacket for SPlayerCommand {
|
impl<'a> ServerPacket<'a> for SPlayerCommand {
|
||||||
fn read(mut read: impl Read, version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
let entity_id = read.get_var_int()?;
|
let entity_id = read.get_var_int()?;
|
||||||
let action_id = read.get_var_int()?;
|
let action_id = read.get_var_int()?;
|
||||||
let jump_boost = read.get_var_int()?;
|
let jump_boost = read.get_var_int()?;
|
||||||
|
|||||||
@ -5,15 +5,14 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_MOVE_PLAYER_STATUS_ONLY;
|
use pumpkin_data::packet::serverbound::PLAY_MOVE_PLAYER_STATUS_ONLY;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_MOVE_PLAYER_STATUS_ONLY)]
|
#[java_packet(PLAY_MOVE_PLAYER_STATUS_ONLY)]
|
||||||
pub struct SSetPlayerGround {
|
pub struct SSetPlayerGround {
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSetPlayerGround {
|
impl<'a> ServerPacket<'a> for SSetPlayerGround {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
on_ground: bytebuf.get_bool()?,
|
on_ground: bytebuf.get_bool()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_PLAYER_INPUT;
|
use pumpkin_data::packet::serverbound::PLAY_PLAYER_INPUT;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_PLAYER_INPUT)]
|
#[java_packet(PLAY_PLAYER_INPUT)]
|
||||||
pub struct SPlayerInput {
|
pub struct SPlayerInput {
|
||||||
@ -23,8 +22,8 @@ impl SPlayerInput {
|
|||||||
pub const SPRINT: i8 = 64;
|
pub const SPRINT: i8 = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlayerInput {
|
impl<'a> ServerPacket<'a> for SPlayerInput {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
input: bytebuf.get_i8()?,
|
input: bytebuf.get_i8()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,14 +2,13 @@ use crate::{ServerPacket, ser::ReadingError};
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_PLAYER_LOADED;
|
use pumpkin_data::packet::serverbound::PLAY_PLAYER_LOADED;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_PLAYER_LOADED)]
|
#[java_packet(PLAY_PLAYER_LOADED)]
|
||||||
pub struct SPlayerLoaded;
|
pub struct SPlayerLoaded;
|
||||||
|
|
||||||
impl ServerPacket for SPlayerLoaded {
|
impl<'a> ServerPacket<'a> for SPlayerLoaded {
|
||||||
fn read(
|
fn read(
|
||||||
_bytebuf: impl Read,
|
_bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self)
|
Ok(Self)
|
||||||
|
|||||||
@ -7,7 +7,6 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_MOVE_PLAYER_POS)]
|
#[java_packet(PLAY_MOVE_PLAYER_POS)]
|
||||||
pub struct SPlayerPosition {
|
pub struct SPlayerPosition {
|
||||||
@ -16,8 +15,8 @@ pub struct SPlayerPosition {
|
|||||||
pub collision: u8,
|
pub collision: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlayerPosition {
|
impl<'a> ServerPacket<'a> for SPlayerPosition {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
position: Vector3::new(
|
position: Vector3::new(
|
||||||
bytebuf.get_f64_be()?,
|
bytebuf.get_f64_be()?,
|
||||||
|
|||||||
@ -7,7 +7,6 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
pub const FLAG_ON_GROUND: u8 = 0x01;
|
pub const FLAG_ON_GROUND: u8 = 0x01;
|
||||||
pub const FLAG_IN_WALL: u8 = 0x02;
|
pub const FLAG_IN_WALL: u8 = 0x02;
|
||||||
@ -21,8 +20,8 @@ pub struct SPlayerPositionRotation {
|
|||||||
pub collision: u8,
|
pub collision: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlayerPositionRotation {
|
impl<'a> ServerPacket<'a> for SPlayerPositionRotation {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
position: Vector3::new(
|
position: Vector3::new(
|
||||||
bytebuf.get_f64_be()?,
|
bytebuf.get_f64_be()?,
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_MOVE_PLAYER_ROT;
|
use pumpkin_data::packet::serverbound::PLAY_MOVE_PLAYER_ROT;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_MOVE_PLAYER_ROT)]
|
#[java_packet(PLAY_MOVE_PLAYER_ROT)]
|
||||||
pub struct SPlayerRotation {
|
pub struct SPlayerRotation {
|
||||||
@ -14,8 +13,8 @@ pub struct SPlayerRotation {
|
|||||||
pub ground: bool,
|
pub ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlayerRotation {
|
impl<'a> ServerPacket<'a> for SPlayerRotation {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
yaw: bytebuf.get_f32_be()?,
|
yaw: bytebuf.get_f32_be()?,
|
||||||
pitch: bytebuf.get_f32_be()?,
|
pitch: bytebuf.get_f32_be()?,
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::PLAY_CHAT_SESSION_UPDATE;
|
use pumpkin_data::packet::serverbound::PLAY_CHAT_SESSION_UPDATE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
@ -18,22 +16,24 @@ pub struct SPlayerSession {
|
|||||||
pub key_signature: Box<[u8]>,
|
pub key_signature: Box<[u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SPlayerSession {
|
impl<'a> ServerPacket<'a> for SPlayerSession {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
let session_id = read.get_uuid()?;
|
let session_id = read.get_uuid()?;
|
||||||
let expires_at = read.get_i64_be()?;
|
let expires_at = read.get_i64_be()?;
|
||||||
|
|
||||||
let public_key_length = read.get_var_int()?.0 as usize;
|
let public_key_length = read.get_var_int()?.0 as usize;
|
||||||
let public_key = read.read_boxed_slice(public_key_length)?;
|
let mut public_key = vec![0u8; public_key_length];
|
||||||
|
read.read_bytes_to_buf(&mut public_key)?;
|
||||||
|
|
||||||
let key_signature_length = read.get_var_int()?.0 as usize;
|
let key_signature_length = read.get_var_int()?.0 as usize;
|
||||||
let key_signature = read.read_boxed_slice(key_signature_length)?;
|
let mut key_signature = vec![0u8; key_signature_length];
|
||||||
|
read.read_bytes_to_buf(&mut key_signature)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
session_id,
|
session_id,
|
||||||
expires_at,
|
expires_at,
|
||||||
public_key,
|
public_key: public_key.into_boxed_slice(),
|
||||||
key_signature,
|
key_signature: key_signature.into_boxed_slice(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_RECIPE_BOOK_CHANGE_SETTINGS;
|
use pumpkin_data::packet::serverbound::PLAY_RECIPE_BOOK_CHANGE_SETTINGS;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -16,8 +15,8 @@ pub struct SRecipeBookChangeSettings {
|
|||||||
pub is_filtering: bool,
|
pub is_filtering: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SRecipeBookChangeSettings {
|
impl<'a> ServerPacket<'a> for SRecipeBookChangeSettings {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
book_type: bytebuf.get_var_int()?,
|
book_type: bytebuf.get_var_int()?,
|
||||||
is_open: bytebuf.get_bool()?,
|
is_open: bytebuf.get_bool()?,
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_RECIPE_BOOK_SEEN_RECIPE;
|
use pumpkin_data::packet::serverbound::PLAY_RECIPE_BOOK_SEEN_RECIPE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -14,8 +13,8 @@ pub struct SRecipeBookSeenRecipe {
|
|||||||
pub recipe_display_id: VarInt,
|
pub recipe_display_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SRecipeBookSeenRecipe {
|
impl<'a> ServerPacket<'a> for SRecipeBookSeenRecipe {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
recipe_display_id: bytebuf.get_var_int()?,
|
recipe_display_id: bytebuf.get_var_int()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,22 +1,21 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_data::packet::serverbound::PLAY_RENAME_ITEM;
|
use pumpkin_data::packet::serverbound::PLAY_RENAME_ITEM;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[java_packet(PLAY_RENAME_ITEM)]
|
#[java_packet(PLAY_RENAME_ITEM)]
|
||||||
pub struct SRenameItem {
|
pub struct SRenameItem<'a> {
|
||||||
pub item_name: String,
|
pub item_name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SRenameItem {
|
impl<'a> ServerPacket<'a> for SRenameItem<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
item_name: bytebuf.get_str_bounded(32767)?.into_string(),
|
item_name: bytebuf.get_str_bounded_borrowed(32767)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_data::packet::serverbound::PLAY_SEEN_ADVANCEMENTS;
|
use pumpkin_data::packet::serverbound::PLAY_SEEN_ADVANCEMENTS;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::identifier::Identifier;
|
use pumpkin_util::identifier::Identifier;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[java_packet(PLAY_SEEN_ADVANCEMENTS)]
|
#[java_packet(PLAY_SEEN_ADVANCEMENTS)]
|
||||||
@ -15,14 +14,14 @@ pub enum SSeenAdvancement {
|
|||||||
CloseTab,
|
CloseTab,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSeenAdvancement {
|
impl<'a> ServerPacket<'a> for SSeenAdvancement {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
let action = bytebuf.get_var_int()?;
|
let action = bytebuf.get_var_int()?;
|
||||||
match action.0 {
|
match action.0 {
|
||||||
0 => {
|
0 => {
|
||||||
let id_str = bytebuf.get_str()?;
|
let id_str = bytebuf.get_str_borrowed()?;
|
||||||
let id =
|
let id =
|
||||||
Identifier::parse(&id_str).map_err(|e| ReadingError::Message(e.to_string()))?;
|
Identifier::parse(id_str).map_err(|e| ReadingError::Message(e.to_string()))?;
|
||||||
Ok(Self::OpenTab(id))
|
Ok(Self::OpenTab(id))
|
||||||
}
|
}
|
||||||
1 => Ok(Self::CloseTab),
|
1 => Ok(Self::CloseTab),
|
||||||
|
|||||||
@ -8,15 +8,14 @@ use crate::{
|
|||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_SELECT_TRADE)]
|
#[java_packet(PLAY_SELECT_TRADE)]
|
||||||
pub struct SSelectTrade {
|
pub struct SSelectTrade {
|
||||||
pub selected_slot: VarInt,
|
pub selected_slot: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSelectTrade {
|
impl<'a> ServerPacket<'a> for SSelectTrade {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
selected_slot: bytebuf.get_var_int()?,
|
selected_slot: bytebuf.get_var_int()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_SET_BEACON;
|
use pumpkin_data::packet::serverbound::PLAY_SET_BEACON;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::codec::var_int::VarInt;
|
use crate::codec::var_int::VarInt;
|
||||||
|
|
||||||
@ -15,8 +14,8 @@ pub struct SSetBeacon {
|
|||||||
pub secondary_effect: Option<VarInt>,
|
pub secondary_effect: Option<VarInt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSetBeacon {
|
impl<'a> ServerPacket<'a> for SSetBeacon {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
primary_effect: bytebuf.get_option(NetworkReadExt::get_var_int)?,
|
primary_effect: bytebuf.get_option(NetworkReadExt::get_var_int)?,
|
||||||
secondary_effect: bytebuf.get_option(NetworkReadExt::get_var_int)?,
|
secondary_effect: bytebuf.get_option(NetworkReadExt::get_var_int)?,
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_data::packet::serverbound::PLAY_SET_COMMAND_BLOCK;
|
use pumpkin_data::packet::serverbound::PLAY_SET_COMMAND_BLOCK;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::codec::var_int::VarInt;
|
use crate::codec::var_int::VarInt;
|
||||||
|
|
||||||
#[java_packet(PLAY_SET_COMMAND_BLOCK)]
|
#[java_packet(PLAY_SET_COMMAND_BLOCK)]
|
||||||
pub struct SSetCommandBlock {
|
pub struct SSetCommandBlock<'a> {
|
||||||
pub pos: BlockPos,
|
pub pos: BlockPos,
|
||||||
pub command: String,
|
pub command: &'a str,
|
||||||
pub mode: VarInt,
|
pub mode: VarInt,
|
||||||
|
|
||||||
/// Operation mode flags
|
/// Operation mode flags
|
||||||
@ -23,11 +22,11 @@ pub struct SSetCommandBlock {
|
|||||||
pub flags: i8,
|
pub flags: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSetCommandBlock {
|
impl<'a> ServerPacket<'a> for SSetCommandBlock<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
pos: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
pos: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
||||||
command: bytebuf.get_str_bounded(32767)?.into_string(),
|
command: bytebuf.get_str_bounded_borrowed(32767)?,
|
||||||
mode: bytebuf.get_var_int()?,
|
mode: bytebuf.get_var_int()?,
|
||||||
flags: bytebuf.get_i8()?,
|
flags: bytebuf.get_i8()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -14,9 +14,9 @@ pub struct SSetCreativeSlot {
|
|||||||
pub clicked_item: ItemStackSerializer<'static>,
|
pub clicked_item: ItemStackSerializer<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSetCreativeSlot {
|
impl<'a> ServerPacket<'a> for SSetCreativeSlot {
|
||||||
fn read(
|
fn read(
|
||||||
mut read: impl std::io::Read,
|
mut read: &mut &'a [u8],
|
||||||
_version: &JavaMinecraftVersion,
|
_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
let slot = read.get_i16_be()?;
|
let slot = read.get_i16_be()?;
|
||||||
|
|||||||
@ -5,15 +5,14 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_SET_CARRIED_ITEM;
|
use pumpkin_data::packet::serverbound::PLAY_SET_CARRIED_ITEM;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_SET_CARRIED_ITEM)]
|
#[java_packet(PLAY_SET_CARRIED_ITEM)]
|
||||||
pub struct SSetHeldItem {
|
pub struct SSetHeldItem {
|
||||||
pub slot: i16,
|
pub slot: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSetHeldItem {
|
impl<'a> ServerPacket<'a> for SSetHeldItem {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
slot: bytebuf.get_i16_be()?,
|
slot: bytebuf.get_i16_be()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,36 +1,35 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_data::packet::serverbound::PLAY_SET_JIGSAW_BLOCK;
|
use pumpkin_data::packet::serverbound::PLAY_SET_JIGSAW_BLOCK;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::codec::var_int::VarInt;
|
use crate::codec::var_int::VarInt;
|
||||||
|
|
||||||
#[java_packet(PLAY_SET_JIGSAW_BLOCK)]
|
#[java_packet(PLAY_SET_JIGSAW_BLOCK)]
|
||||||
pub struct SSetJigsawBlock {
|
pub struct SSetJigsawBlock<'a> {
|
||||||
pub pos: BlockPos,
|
pub pos: BlockPos,
|
||||||
pub name: String,
|
pub name: &'a str,
|
||||||
pub target: String,
|
pub target: &'a str,
|
||||||
pub pool: String,
|
pub pool: &'a str,
|
||||||
pub final_state: String,
|
pub final_state: &'a str,
|
||||||
pub joint: String,
|
pub joint: &'a str,
|
||||||
pub selection_priority: VarInt,
|
pub selection_priority: VarInt,
|
||||||
pub placement_priority: VarInt,
|
pub placement_priority: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSetJigsawBlock {
|
impl<'a> ServerPacket<'a> for SSetJigsawBlock<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
pos: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
pos: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
||||||
name: bytebuf.get_str_bounded(32767)?.into_string(),
|
name: bytebuf.get_str_bounded_borrowed(32767)?,
|
||||||
target: bytebuf.get_str_bounded(32767)?.into_string(),
|
target: bytebuf.get_str_bounded_borrowed(32767)?,
|
||||||
pool: bytebuf.get_str_bounded(32767)?.into_string(),
|
pool: bytebuf.get_str_bounded_borrowed(32767)?,
|
||||||
final_state: bytebuf.get_str_bounded(32767)?.into_string(),
|
final_state: bytebuf.get_str_bounded_borrowed(32767)?,
|
||||||
joint: bytebuf.get_str_bounded(32767)?.into_string(),
|
joint: bytebuf.get_str_bounded_borrowed(32767)?,
|
||||||
selection_priority: bytebuf.get_var_int()?,
|
selection_priority: bytebuf.get_var_int()?,
|
||||||
placement_priority: bytebuf.get_var_int()?,
|
placement_priority: bytebuf.get_var_int()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -4,24 +4,27 @@ use pumpkin_util::math::position::BlockPos;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
#[java_packet(PLAY_SET_TEST_BLOCK)]
|
#[java_packet(PLAY_SET_TEST_BLOCK)]
|
||||||
pub struct SSetTestBlock {
|
pub struct SSetTestBlock<'a> {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
pub mode: TestBlockMode,
|
pub mode: TestBlockMode,
|
||||||
pub message: String,
|
pub message: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSetTestBlock {
|
impl<'a> ServerPacket<'a> for SSetTestBlock<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(
|
||||||
|
mut bytebuf: &mut &'a [u8],
|
||||||
|
_version: &JavaMinecraftVersion,
|
||||||
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
position: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
position: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
||||||
mode: TestBlockMode::read(&mut bytebuf)?,
|
mode: TestBlockMode::read(&mut bytebuf)?,
|
||||||
message: bytebuf.get_str()?.into_string(),
|
message: bytebuf.get_str_borrowed()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_SWING;
|
use pumpkin_data::packet::serverbound::PLAY_SWING;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -14,8 +13,8 @@ pub struct SSwingArm {
|
|||||||
pub hand: VarInt,
|
pub hand: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SSwingArm {
|
impl<'a> ServerPacket<'a> for SSwingArm {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
hand: bytebuf.get_var_int()?,
|
hand: bytebuf.get_var_int()?,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,16 +5,15 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_TELEPORT_TO_ENTITY;
|
use pumpkin_data::packet::serverbound::PLAY_TELEPORT_TO_ENTITY;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[java_packet(PLAY_TELEPORT_TO_ENTITY)]
|
#[java_packet(PLAY_TELEPORT_TO_ENTITY)]
|
||||||
pub struct STeleportToEntity {
|
pub struct STeleportToEntity {
|
||||||
pub target: uuid::Uuid,
|
pub target: uuid::Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for STeleportToEntity {
|
impl<'a> ServerPacket<'a> for STeleportToEntity {
|
||||||
fn read(
|
fn read(
|
||||||
mut bytebuf: impl Read,
|
bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@ -12,18 +12,18 @@ use pumpkin_util::version::JavaMinecraftVersion;
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
#[java_packet(PLAY_TEST_INSTANCE_BLOCK_ACTION)]
|
#[java_packet(PLAY_TEST_INSTANCE_BLOCK_ACTION)]
|
||||||
pub struct STestInstanceBlockAction {
|
pub struct STestInstanceBlockAction<'a> {
|
||||||
pub pos: BlockPos,
|
pub pos: BlockPos,
|
||||||
pub action: TestInstanceBlockAction,
|
pub action: TestInstanceBlockAction,
|
||||||
pub data: TestInstanceBlockData,
|
pub data: TestInstanceBlockData<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for STestInstanceBlockAction {
|
impl<'a> ServerPacket<'a> for STestInstanceBlockAction<'a> {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
pos: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
pos: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
||||||
action: TestInstanceBlockAction::read(&mut bytebuf)?,
|
action: TestInstanceBlockAction::read(bytebuf)?,
|
||||||
data: TestInstanceBlockData::read(&mut bytebuf)?,
|
data: TestInstanceBlockData::read(bytebuf)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,18 +72,18 @@ impl VarIntVector3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestInstanceBlockData {
|
pub struct TestInstanceBlockData<'a> {
|
||||||
pub test: Option<String>,
|
pub test: Option<&'a str>,
|
||||||
pub size: VarIntVector3,
|
pub size: VarIntVector3,
|
||||||
pub rotation: pumpkin_data::block_rotation::Rotation,
|
pub rotation: pumpkin_data::block_rotation::Rotation,
|
||||||
pub ignore_entities: bool,
|
pub ignore_entities: bool,
|
||||||
pub status: TestInstanceBlockStatus,
|
pub status: TestInstanceBlockStatus,
|
||||||
pub error_message: Option<String>,
|
pub error_message: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestInstanceBlockData {
|
impl<'a> TestInstanceBlockData<'a> {
|
||||||
fn read(bytebuf: &mut impl Read) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8]) -> Result<Self, ReadingError> {
|
||||||
let test = bytebuf.get_option(|b| b.get_str().map(String::from))?;
|
let test = bytebuf.get_option(crate::ser::NetworkReadSliceExt::get_str_borrowed)?;
|
||||||
let size = VarIntVector3::read(bytebuf)?;
|
let size = VarIntVector3::read(bytebuf)?;
|
||||||
let rotation = match bytebuf.get_var_int()?.0 {
|
let rotation = match bytebuf.get_var_int()?.0 {
|
||||||
0 => pumpkin_data::block_rotation::Rotation::None,
|
0 => pumpkin_data::block_rotation::Rotation::None,
|
||||||
@ -104,7 +104,8 @@ impl TestInstanceBlockData {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let error_message = bytebuf.get_option(|b| b.get_str().map(String::from))?;
|
let error_message =
|
||||||
|
bytebuf.get_option(crate::ser::NetworkReadSliceExt::get_str_borrowed)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
test,
|
test,
|
||||||
|
|||||||
@ -1,35 +1,33 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use pumpkin_data::packet::serverbound::PLAY_SIGN_UPDATE;
|
use pumpkin_data::packet::serverbound::PLAY_SIGN_UPDATE;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::{math::position::BlockPos, version::JavaMinecraftVersion};
|
use pumpkin_util::{math::position::BlockPos, version::JavaMinecraftVersion};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerPacket,
|
ServerPacket,
|
||||||
ser::{NetworkReadExt, ReadingError},
|
ser::{NetworkReadExt, NetworkReadSliceExt, ReadingError},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[java_packet(PLAY_SIGN_UPDATE)]
|
#[java_packet(PLAY_SIGN_UPDATE)]
|
||||||
pub struct SUpdateSign {
|
pub struct SUpdateSign<'a> {
|
||||||
pub location: BlockPos,
|
pub location: BlockPos,
|
||||||
pub is_front_text: bool,
|
pub is_front_text: bool,
|
||||||
pub line_1: Box<str>,
|
pub line_1: &'a str,
|
||||||
pub line_2: Box<str>,
|
pub line_2: &'a str,
|
||||||
pub line_3: Box<str>,
|
pub line_3: &'a str,
|
||||||
pub line_4: Box<str>,
|
pub line_4: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_LINE_LENGTH: usize = 386;
|
const MAX_LINE_LENGTH: usize = 386;
|
||||||
|
|
||||||
impl ServerPacket for SUpdateSign {
|
impl<'a> ServerPacket<'a> for SUpdateSign<'a> {
|
||||||
fn read(mut read: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(read: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
location: BlockPos::from_i64(read.get_i64_be()?),
|
location: BlockPos::from_i64(read.get_i64_be()?),
|
||||||
is_front_text: read.get_bool()?,
|
is_front_text: read.get_bool()?,
|
||||||
line_1: read.get_str_bounded(MAX_LINE_LENGTH)?,
|
line_1: read.get_str_bounded_borrowed(MAX_LINE_LENGTH)?,
|
||||||
line_2: read.get_str_bounded(MAX_LINE_LENGTH)?,
|
line_2: read.get_str_bounded_borrowed(MAX_LINE_LENGTH)?,
|
||||||
line_3: read.get_str_bounded(MAX_LINE_LENGTH)?,
|
line_3: read.get_str_bounded_borrowed(MAX_LINE_LENGTH)?,
|
||||||
line_4: read.get_str_bounded(MAX_LINE_LENGTH)?,
|
line_4: read.get_str_bounded_borrowed(MAX_LINE_LENGTH)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::PLAY_USE_ITEM;
|
use pumpkin_data::packet::serverbound::PLAY_USE_ITEM;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -18,9 +17,9 @@ pub struct SUseItem {
|
|||||||
pub pitch: f32,
|
pub pitch: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SUseItem {
|
impl<'a> ServerPacket<'a> for SUseItem {
|
||||||
fn read(
|
fn read(
|
||||||
mut bytebuf: impl Read,
|
bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@ -6,7 +6,6 @@ use pumpkin_data::packet::serverbound::PLAY_USE_ITEM_ON;
|
|||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
|
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
|
|
||||||
@ -21,8 +20,8 @@ pub struct SUseItemOn {
|
|||||||
pub sequence: VarInt,
|
pub sequence: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SUseItemOn {
|
impl<'a> ServerPacket<'a> for SUseItemOn {
|
||||||
fn read(mut bytebuf: impl Read, _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
fn read(bytebuf: &mut &'a [u8], _version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
hand: bytebuf.get_var_int()?,
|
hand: bytebuf.get_var_int()?,
|
||||||
position: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
position: BlockPos::from_i64(bytebuf.get_i64_be()?),
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::{
|
|||||||
use pumpkin_data::packet::serverbound::STATUS_PING_REQUEST;
|
use pumpkin_data::packet::serverbound::STATUS_PING_REQUEST;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
/// Sent by the client to measure the round-trip time (latency) to the server.
|
/// Sent by the client to measure the round-trip time (latency) to the server.
|
||||||
///
|
///
|
||||||
@ -16,9 +15,9 @@ pub struct SStatusPingRequest {
|
|||||||
pub payload: i64,
|
pub payload: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerPacket for SStatusPingRequest {
|
impl<'a> ServerPacket<'a> for SStatusPingRequest {
|
||||||
fn read(
|
fn read(
|
||||||
mut bytebuf: impl Read,
|
bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@ -2,7 +2,6 @@ use crate::{ServerPacket, ser::ReadingError};
|
|||||||
use pumpkin_data::packet::serverbound::STATUS_STATUS_REQUEST;
|
use pumpkin_data::packet::serverbound::STATUS_STATUS_REQUEST;
|
||||||
use pumpkin_macros::java_packet;
|
use pumpkin_macros::java_packet;
|
||||||
use pumpkin_util::version::JavaMinecraftVersion;
|
use pumpkin_util::version::JavaMinecraftVersion;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
/// Sent by the client to request the server's current status information.
|
/// Sent by the client to request the server's current status information.
|
||||||
///
|
///
|
||||||
@ -11,9 +10,9 @@ use std::io::Read;
|
|||||||
#[java_packet(STATUS_STATUS_REQUEST)]
|
#[java_packet(STATUS_STATUS_REQUEST)]
|
||||||
pub struct SStatusRequest;
|
pub struct SStatusRequest;
|
||||||
|
|
||||||
impl ServerPacket for SStatusRequest {
|
impl<'a> ServerPacket<'a> for SStatusRequest {
|
||||||
fn read(
|
fn read(
|
||||||
_bytebuf: impl Read,
|
_bytebuf: &mut &'a [u8],
|
||||||
_protocol_version: &JavaMinecraftVersion,
|
_protocol_version: &JavaMinecraftVersion,
|
||||||
) -> Result<Self, ReadingError> {
|
) -> Result<Self, ReadingError> {
|
||||||
Ok(Self)
|
Ok(Self)
|
||||||
|
|||||||
@ -253,8 +253,8 @@ pub trait ClientPacket: MultiVersionJavaPacket {
|
|||||||
) -> Result<(), WritingError>;
|
) -> Result<(), WritingError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ServerPacket: MultiVersionJavaPacket + Sized {
|
pub trait ServerPacket<'a>: MultiVersionJavaPacket + Sized {
|
||||||
fn read(read: impl Read, version: &JavaMinecraftVersion) -> Result<Self, ReadingError>;
|
fn read(read: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BClientPacket: Packet {
|
pub trait BClientPacket: Packet {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use core::str;
|
use core::str;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -61,34 +62,40 @@ pub trait NetworkReadExt {
|
|||||||
fn get_i128_be(&mut self) -> Result<i128, ReadingError>;
|
fn get_i128_be(&mut self) -> Result<i128, ReadingError>;
|
||||||
fn get_u128_be(&mut self) -> Result<u128, ReadingError>;
|
fn get_u128_be(&mut self) -> Result<u128, ReadingError>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_i16(&mut self) -> Result<i16, ReadingError> {
|
fn get_i16(&mut self) -> Result<i16, ReadingError> {
|
||||||
self.get_i16_be()
|
self.get_i16_be()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn get_u16(&mut self) -> Result<u16, ReadingError> {
|
fn get_u16(&mut self) -> Result<u16, ReadingError> {
|
||||||
self.get_u16_be()
|
self.get_u16_be()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn get_i32(&mut self) -> Result<i32, ReadingError> {
|
fn get_i32(&mut self) -> Result<i32, ReadingError> {
|
||||||
self.get_i32_be()
|
self.get_i32_be()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn get_u32(&mut self) -> Result<u32, ReadingError> {
|
fn get_u32(&mut self) -> Result<u32, ReadingError> {
|
||||||
self.get_u32_be()
|
self.get_u32_be()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn get_i64(&mut self) -> Result<i64, ReadingError> {
|
fn get_i64(&mut self) -> Result<i64, ReadingError> {
|
||||||
self.get_i64_be()
|
self.get_i64_be()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn get_u64(&mut self) -> Result<u64, ReadingError> {
|
fn get_u64(&mut self) -> Result<u64, ReadingError> {
|
||||||
self.get_u64_be()
|
self.get_u64_be()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn get_f32(&mut self) -> Result<f32, ReadingError> {
|
fn get_f32(&mut self) -> Result<f32, ReadingError> {
|
||||||
self.get_f32_be()
|
self.get_f32_be()
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn get_f64(&mut self) -> Result<f64, ReadingError> {
|
fn get_f64(&mut self) -> Result<f64, ReadingError> {
|
||||||
self.get_f64_be()
|
self.get_f64_be()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_boxed_slice(&mut self, count: usize) -> Result<Box<[u8]>, ReadingError>;
|
fn read_bytes_to_buf(&mut self, buf: &mut [u8]) -> Result<(), ReadingError>;
|
||||||
|
|
||||||
fn read_remaining_to_boxed_slice(&mut self, bound: usize) -> Result<Box<[u8]>, ReadingError>;
|
|
||||||
|
|
||||||
fn get_bool(&mut self) -> Result<bool, ReadingError>;
|
fn get_bool(&mut self) -> Result<bool, ReadingError>;
|
||||||
fn get_var_int(&mut self) -> Result<VarInt, ReadingError>;
|
fn get_var_int(&mut self) -> Result<VarInt, ReadingError>;
|
||||||
@ -96,23 +103,154 @@ pub trait NetworkReadExt {
|
|||||||
fn get_var_long(&mut self) -> Result<VarLong, ReadingError>;
|
fn get_var_long(&mut self) -> Result<VarLong, ReadingError>;
|
||||||
fn get_var_ulong(&mut self) -> Result<VarULong, ReadingError>;
|
fn get_var_ulong(&mut self) -> Result<VarULong, ReadingError>;
|
||||||
fn get_str_bounded(&mut self, bound: usize) -> Result<Box<str>, ReadingError>;
|
fn get_str_bounded(&mut self, bound: usize) -> Result<Box<str>, ReadingError>;
|
||||||
fn get_str(&mut self) -> Result<Box<str>, ReadingError>;
|
#[inline]
|
||||||
|
fn get_str(&mut self) -> Result<Box<str>, ReadingError> {
|
||||||
|
self.get_str_bounded(i32::MAX as usize)
|
||||||
|
}
|
||||||
fn get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError>;
|
fn get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError>;
|
||||||
fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError>;
|
fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_option<G>(
|
fn get_option<G>(
|
||||||
&mut self,
|
&mut self,
|
||||||
parse: impl FnOnce(&mut Self) -> Result<G, ReadingError>,
|
parse: impl FnOnce(&mut Self) -> Result<G, ReadingError>,
|
||||||
) -> Result<Option<G>, ReadingError>;
|
) -> Result<Option<G>, ReadingError> {
|
||||||
|
if self.get_bool()? {
|
||||||
|
Ok(Some(parse(self)?))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_list<G>(
|
fn get_list<G>(
|
||||||
&mut self,
|
&mut self,
|
||||||
parse: impl Fn(&mut Self) -> Result<G, ReadingError>,
|
parse: impl Fn(&mut Self) -> Result<G, ReadingError>,
|
||||||
) -> Result<Vec<G>, ReadingError>;
|
) -> Result<Vec<G>, ReadingError> {
|
||||||
|
const MAX_LIST_SIZE: usize = 65536;
|
||||||
|
|
||||||
|
let len = self.get_var_int()?.0 as usize;
|
||||||
|
if len > MAX_LIST_SIZE {
|
||||||
|
return Err(ReadingError::TooLarge(format!(
|
||||||
|
"List length {len} exceeds limit"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
let mut list = Vec::with_capacity(len);
|
||||||
|
for _ in 0..len {
|
||||||
|
list.push(parse(self)?);
|
||||||
|
}
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait NetworkReadSliceExt<'a> {
|
||||||
|
fn get_str_borrowed(&mut self) -> Result<&'a str, ReadingError>;
|
||||||
|
fn get_str_bounded_borrowed(&mut self, bound: usize) -> Result<&'a str, ReadingError>;
|
||||||
|
fn read_slice_borrowed(&mut self, count: usize) -> Result<&'a [u8], ReadingError>;
|
||||||
|
fn read_remaining_slice_borrowed(&mut self, bound: usize) -> Result<&'a [u8], ReadingError>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn read_cow_slice_borrowed(&mut self, count: usize) -> Result<Cow<'a, [u8]>, ReadingError> {
|
||||||
|
Ok(Cow::Borrowed(self.read_slice_borrowed(count)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn read_remaining_to_cow_slice_borrowed(
|
||||||
|
&mut self,
|
||||||
|
bound: usize,
|
||||||
|
) -> Result<Cow<'a, [u8]>, ReadingError> {
|
||||||
|
Ok(Cow::Borrowed(self.read_remaining_slice_borrowed(bound)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_cow_str_borrowed(&mut self) -> Result<Cow<'a, str>, ReadingError> {
|
||||||
|
self.get_cow_str_bounded_borrowed(i32::MAX as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_cow_str_bounded_borrowed(&mut self, bound: usize) -> Result<Cow<'a, str>, ReadingError> {
|
||||||
|
Ok(Cow::Borrowed(self.get_str_bounded_borrowed(bound)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> NetworkReadSliceExt<'a> for &'a [u8] {
|
||||||
|
#[inline]
|
||||||
|
fn read_slice_borrowed(&mut self, count: usize) -> Result<&'a [u8], ReadingError> {
|
||||||
|
if self.len() < count {
|
||||||
|
return Err(ReadingError::Incomplete(format!(
|
||||||
|
"EOF, Tried to read {count} bytes but only {} bytes left",
|
||||||
|
self.len()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
let (head, tail) = self.split_at(count);
|
||||||
|
*self = tail;
|
||||||
|
Ok(head)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn read_remaining_slice_borrowed(&mut self, bound: usize) -> Result<&'a [u8], ReadingError> {
|
||||||
|
if self.len() > bound {
|
||||||
|
return Err(ReadingError::TooLarge(
|
||||||
|
"Read remaining too long".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let slice = *self;
|
||||||
|
*self = &[];
|
||||||
|
Ok(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_str_bounded_borrowed(&mut self, bound: usize) -> Result<&'a str, ReadingError> {
|
||||||
|
let bytes_len = self.get_var_uint()?.0 as usize;
|
||||||
|
|
||||||
|
let maximum_utf8_bytes = bound.saturating_mul(3);
|
||||||
|
if bytes_len > maximum_utf8_bytes {
|
||||||
|
return Err(ReadingError::TooLarge(format!(
|
||||||
|
"string has too many bytes ({bytes_len} > {maximum_utf8_bytes})"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes = self.read_slice_borrowed(bytes_len)?;
|
||||||
|
let string =
|
||||||
|
std::str::from_utf8(bytes).map_err(|e| ReadingError::Message(e.to_string()))?;
|
||||||
|
|
||||||
|
if string.encode_utf16().nth(bound).is_some() {
|
||||||
|
return Err(ReadingError::TooLarge(format!(
|
||||||
|
"string has too many UTF-16 characters (more than the maximum limit {bound})"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_str_borrowed(&mut self) -> Result<&'a str, ReadingError> {
|
||||||
|
self.get_str_bounded_borrowed(i32::MAX as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, R: NetworkReadSliceExt<'a> + ?Sized> NetworkReadSliceExt<'a> for &mut R {
|
||||||
|
#[inline]
|
||||||
|
fn get_str_borrowed(&mut self) -> Result<&'a str, ReadingError> {
|
||||||
|
(**self).get_str_borrowed()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn get_str_bounded_borrowed(&mut self, bound: usize) -> Result<&'a str, ReadingError> {
|
||||||
|
(**self).get_str_bounded_borrowed(bound)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_slice_borrowed(&mut self, count: usize) -> Result<&'a [u8], ReadingError> {
|
||||||
|
(**self).read_slice_borrowed(count)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_remaining_slice_borrowed(&mut self, bound: usize) -> Result<&'a [u8], ReadingError> {
|
||||||
|
(**self).read_remaining_slice_borrowed(bound)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! get_number_be {
|
macro_rules! get_number_be {
|
||||||
($name:ident, $type:ty) => {
|
($name:ident, $type:ty) => {
|
||||||
|
#[inline]
|
||||||
fn $name(&mut self) -> Result<$type, ReadingError> {
|
fn $name(&mut self) -> Result<$type, ReadingError> {
|
||||||
let mut buf = [0u8; std::mem::size_of::<$type>()];
|
let mut buf = [0u8; std::mem::size_of::<$type>()];
|
||||||
self.read_exact(&mut buf)
|
self.read_exact(&mut buf)
|
||||||
@ -137,58 +275,38 @@ impl<R: Read> NetworkReadExt for R {
|
|||||||
get_number_be!(get_f32_be, f32);
|
get_number_be!(get_f32_be, f32);
|
||||||
get_number_be!(get_f64_be, f64);
|
get_number_be!(get_f64_be, f64);
|
||||||
|
|
||||||
fn read_boxed_slice(&mut self, length: usize) -> Result<Box<[u8]>, ReadingError> {
|
#[inline]
|
||||||
// Increase this to at least 2MB to handle larger Bedrock batches
|
fn read_bytes_to_buf(&mut self, buf: &mut [u8]) -> Result<(), ReadingError> {
|
||||||
const MAX_SLICE_LENGTH: usize = 2 * 1024 * 1024; // 2MB
|
self.read_exact(buf)
|
||||||
if !(0..=MAX_SLICE_LENGTH).contains(&length) {
|
.map_err(|err| ReadingError::Incomplete(err.to_string()))
|
||||||
return Err(ReadingError::Message(format!(
|
|
||||||
"read_boxed_slice: length {length} out of bounds"
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
let mut buf = vec![0u8; length];
|
|
||||||
self.read_exact(&mut buf)
|
|
||||||
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
|
|
||||||
|
|
||||||
Ok(buf.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_remaining_to_boxed_slice(&mut self, bound: usize) -> Result<Box<[u8]>, ReadingError> {
|
|
||||||
let mut return_buf = Vec::new();
|
|
||||||
|
|
||||||
// Take one extra byte to check for exceeding bound
|
|
||||||
self.take(bound as u64 + 1)
|
|
||||||
.read_to_end(&mut return_buf)
|
|
||||||
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
|
|
||||||
|
|
||||||
if return_buf.len() > bound {
|
|
||||||
return Err(ReadingError::TooLarge(
|
|
||||||
"Read remaining too long".to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(return_buf.into_boxed_slice())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_bool(&mut self) -> Result<bool, ReadingError> {
|
fn get_bool(&mut self) -> Result<bool, ReadingError> {
|
||||||
let byte = self.get_u8()?;
|
let byte = self.get_u8()?;
|
||||||
Ok(byte != 0)
|
Ok(byte != 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_var_int(&mut self) -> Result<VarInt, ReadingError> {
|
fn get_var_int(&mut self) -> Result<VarInt, ReadingError> {
|
||||||
VarInt::decode(self)
|
VarInt::decode(self)
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn get_var_uint(&mut self) -> Result<VarUInt, ReadingError> {
|
fn get_var_uint(&mut self) -> Result<VarUInt, ReadingError> {
|
||||||
VarUInt::decode(self)
|
VarUInt::decode(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_var_long(&mut self) -> Result<VarLong, ReadingError> {
|
fn get_var_long(&mut self) -> Result<VarLong, ReadingError> {
|
||||||
VarLong::decode(self)
|
VarLong::decode(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_var_ulong(&mut self) -> Result<VarULong, ReadingError> {
|
fn get_var_ulong(&mut self) -> Result<VarULong, ReadingError> {
|
||||||
VarULong::decode(self)
|
VarULong::decode(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_str_bounded(&mut self, bound: usize) -> Result<Box<str>, ReadingError> {
|
fn get_str_bounded(&mut self, bound: usize) -> Result<Box<str>, ReadingError> {
|
||||||
let bytes_len = self.get_var_uint()?.0 as usize;
|
let bytes_len = self.get_var_uint()?.0 as usize;
|
||||||
|
|
||||||
@ -203,11 +321,28 @@ impl<R: Read> NetworkReadExt for R {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = self.read_boxed_slice(bytes_len)?;
|
if bytes_len <= 128 {
|
||||||
|
let mut stack_buf = [0u8; 128];
|
||||||
|
let slice = &mut stack_buf[..bytes_len];
|
||||||
|
self.read_exact(slice)
|
||||||
|
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
|
||||||
|
|
||||||
|
let string =
|
||||||
|
std::str::from_utf8(slice).map_err(|e| ReadingError::Message(e.to_string()))?;
|
||||||
|
|
||||||
|
if string.encode_utf16().nth(bound).is_some() {
|
||||||
|
return Err(ReadingError::TooLarge(format!(
|
||||||
|
"string has too many UTF-16 characters (more than the maximum limit {bound})"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(string.into())
|
||||||
|
} else {
|
||||||
|
let mut data = vec![0u8; bytes_len];
|
||||||
|
self.read_bytes_to_buf(&mut data)?;
|
||||||
let string =
|
let string =
|
||||||
std::str::from_utf8(&data).map_err(|e| ReadingError::Message(e.to_string()))?;
|
std::str::from_utf8(&data).map_err(|e| ReadingError::Message(e.to_string()))?;
|
||||||
|
|
||||||
// Next, if we're able to find the (bound + 1)th UTF-16 character, the string is too big.
|
|
||||||
if string.encode_utf16().nth(bound).is_some() {
|
if string.encode_utf16().nth(bound).is_some() {
|
||||||
return Err(ReadingError::TooLarge(format!(
|
return Err(ReadingError::TooLarge(format!(
|
||||||
"string has too many UTF-16 characters (more than the maximum limit {bound})"
|
"string has too many UTF-16 characters (more than the maximum limit {bound})"
|
||||||
@ -216,11 +351,9 @@ impl<R: Read> NetworkReadExt for R {
|
|||||||
|
|
||||||
Ok(string.into())
|
Ok(string.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_str(&mut self) -> Result<Box<str>, ReadingError> {
|
|
||||||
self.get_str_bounded(i32::MAX as usize)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError> {
|
fn get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError> {
|
||||||
let mut bytes = [0u8; 16];
|
let mut bytes = [0u8; 16];
|
||||||
self.read_exact(&mut bytes)
|
self.read_exact(&mut bytes)
|
||||||
@ -228,40 +361,31 @@ impl<R: Read> NetworkReadExt for R {
|
|||||||
Ok(uuid::Uuid::from_bytes(bytes))
|
Ok(uuid::Uuid::from_bytes(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError> {
|
fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError> {
|
||||||
let bytes = self.read_boxed_slice(bits.div_ceil(8))?;
|
let byte_count = bits.div_ceil(8);
|
||||||
Ok(bytes)
|
let mut bytes = vec![0u8; byte_count];
|
||||||
|
self.read_bytes_to_buf(&mut bytes)?;
|
||||||
|
Ok(bytes.into_boxed_slice())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn read_remaining_bytes(read: &mut impl Read, bound: usize) -> Result<Box<[u8]>, ReadingError> {
|
||||||
|
let mut return_buf = Vec::with_capacity(bound.min(1024));
|
||||||
|
|
||||||
|
// Take one extra byte to check for exceeding bound
|
||||||
|
read.take(bound as u64 + 1)
|
||||||
|
.read_to_end(&mut return_buf)
|
||||||
|
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
|
||||||
|
|
||||||
|
if return_buf.len() > bound {
|
||||||
|
return Err(ReadingError::TooLarge(
|
||||||
|
"Read remaining too long".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_option<G>(
|
Ok(return_buf.into_boxed_slice())
|
||||||
&mut self,
|
|
||||||
parse: impl FnOnce(&mut Self) -> Result<G, ReadingError>,
|
|
||||||
) -> Result<Option<G>, ReadingError> {
|
|
||||||
if self.get_bool()? {
|
|
||||||
Ok(Some(parse(self)?))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_list<G>(
|
|
||||||
&mut self,
|
|
||||||
parse: impl Fn(&mut Self) -> Result<G, ReadingError>,
|
|
||||||
) -> Result<Vec<G>, ReadingError> {
|
|
||||||
const MAX_LIST_SIZE: usize = 65536;
|
|
||||||
|
|
||||||
let len = self.get_var_int()?.0 as usize;
|
|
||||||
if len > MAX_LIST_SIZE {
|
|
||||||
return Err(ReadingError::TooLarge(format!(
|
|
||||||
"List length {len} exceeds limit"
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
let mut list = Vec::with_capacity(len);
|
|
||||||
for _ in 0..len {
|
|
||||||
list.push(parse(self)?);
|
|
||||||
}
|
|
||||||
Ok(list)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NetworkWriteExt {
|
pub trait NetworkWriteExt {
|
||||||
|
|||||||
@ -240,3 +240,162 @@ impl<T: PacketRead> PacketRead for Option<T> {
|
|||||||
bool::read(reader)?.then(|| T::read(reader)).transpose()
|
bool::read(reader)?.then(|| T::read(reader)).transpose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for bool {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.is_empty() {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected bool byte"));
|
||||||
|
}
|
||||||
|
let b = buf[0];
|
||||||
|
*buf = &buf[1..];
|
||||||
|
Ok(b != 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for u8 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.is_empty() {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected u8"));
|
||||||
|
}
|
||||||
|
let b = buf[0];
|
||||||
|
*buf = &buf[1..];
|
||||||
|
Ok(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for i8 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
u8::read_slice(buf).map(|b| b as Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for i16 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 2 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected i16"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(2);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_le_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for i32 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 4 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected i32"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(4);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_le_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for i64 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 8 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected i64"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(8);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_le_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for u16 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 2 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected u16"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(2);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_le_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for u32 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 4 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected u32"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(4);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_le_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for u64 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 8 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected u64"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(8);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_le_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for f32 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 4 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected f32"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(4);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_le_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for f64 {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 8 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected f64"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(8);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_le_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for &'a str {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
crate::serial::read_str_slice(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: crate::serial::PacketReadSlice<'a>> crate::serial::PacketReadSlice<'a> for Option<T> {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
bool::read_slice(buf)?
|
||||||
|
.then(|| T::read_slice(buf))
|
||||||
|
.transpose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for uuid::Uuid {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
if buf.len() < 16 {
|
||||||
|
return Err(Error::new(ErrorKind::UnexpectedEof, "expected Uuid"));
|
||||||
|
}
|
||||||
|
let (bytes, rest) = buf.split_at(16);
|
||||||
|
*buf = rest;
|
||||||
|
Ok(Self::from_bytes(bytes.try_into().unwrap()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for crate::codec::var_int::VarInt {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
Self::read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for crate::codec::var_uint::VarUInt {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
Self::read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> crate::serial::PacketReadSlice<'a> for crate::codec::var_ulong::VarULong {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
|
||||||
|
Self::read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -16,3 +16,32 @@ pub trait PacketRead: Sized {
|
|||||||
Err(Error::other("Not implemented"))
|
Err(Error::other("Not implemented"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait PacketReadSlice<'a>: Sized {
|
||||||
|
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_str_slice<'a>(buf: &mut &'a [u8]) -> Result<&'a str, Error> {
|
||||||
|
use crate::codec::var_uint::VarUInt;
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
|
||||||
|
const MAX_STRING_LENGTH: usize = 32767;
|
||||||
|
|
||||||
|
let len = VarUInt::read(buf)?.0 as usize;
|
||||||
|
if len > MAX_STRING_LENGTH {
|
||||||
|
return Err(Error::new(
|
||||||
|
ErrorKind::InvalidData,
|
||||||
|
format!("String length {len} exceeds maximum of {MAX_STRING_LENGTH}"),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if len > buf.len() {
|
||||||
|
return Err(Error::new(
|
||||||
|
ErrorKind::UnexpectedEof,
|
||||||
|
"Not enough bytes for string",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let (str_bytes, rest) = buf.split_at(len);
|
||||||
|
*buf = rest;
|
||||||
|
std::str::from_utf8(str_bytes)
|
||||||
|
.map_err(|_| Error::new(ErrorKind::InvalidData, "Invalid UTF-8 sequence"))
|
||||||
|
}
|
||||||
|
|||||||
@ -124,6 +124,13 @@ impl PacketWrite for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PacketWrite for str {
|
||||||
|
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||||
|
VarUInt(self.len() as _).write(writer)?;
|
||||||
|
writer.write_all(self.as_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: PacketWrite> PacketWrite for Vector3<T> {
|
impl<T: PacketWrite> PacketWrite for Vector3<T> {
|
||||||
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||||
self.x.write(writer)?;
|
self.x.write(writer)?;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user