mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
perf: ditch serde because its slower
i rather trade performance and compile time over convenience
This commit is contained in:
101
Cargo.lock
generated
101
Cargo.lock
generated
@@ -120,7 +120,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -213,9 +213,9 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.13.0"
|
||||
version = "2.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@@ -485,7 +485,7 @@ version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1047,7 +1047,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1131,7 +1131,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1147,7 +1147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1300,7 +1300,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2159,7 +2159,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2186,7 +2186,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2360,7 +2360,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2403,7 +2403,7 @@ dependencies = [
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2432,7 +2432,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2520,7 +2520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2600,7 +2600,7 @@ dependencies = [
|
||||
"itertools 0.14.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2632,7 +2632,7 @@ checksum = "5a7ac85c0bb3fb351f10d531230aaa5e366b46d7c4e5328e5f02801d6dac1165"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2701,7 +2701,7 @@ dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 3.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2759,7 +2759,7 @@ dependencies = [
|
||||
"proc-macro-error2",
|
||||
"pumpkin-data",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 3.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2835,7 +2835,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.11.0",
|
||||
"syn",
|
||||
"syn 3.0.0",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"ureq",
|
||||
@@ -3085,7 +3085,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3230,7 +3230,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3265,7 +3265,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3398,7 +3398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3455,6 +3455,17 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2fac314a64dc9a36e61a9eb4261a5e9bbfbc922b27e518af97bc32b926cf967"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "1.0.2"
|
||||
@@ -3469,7 +3480,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3507,7 +3518,7 @@ dependencies = [
|
||||
"fastrand",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3545,7 +3556,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3556,7 +3567,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3622,9 +3633,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.52.3"
|
||||
version = "1.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
|
||||
checksum = "d988bcd52dbe076d3d46903332f58c912b87a2c49b1428419a5845154762ffee"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -3645,7 +3656,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3835,7 +3846,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3998,9 +4009,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.23.4"
|
||||
version = "1.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53"
|
||||
checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239"
|
||||
dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"js-sys",
|
||||
@@ -4078,7 +4089,7 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -4262,7 +4273,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
"wasmtime-internal-component-util",
|
||||
"wasmtime-internal-wit-bindgen",
|
||||
"wit-parser 0.251.0",
|
||||
@@ -4370,7 +4381,7 @@ checksum = "e747f4a074699ba1b4e4d841fb263f9b7df5bd1555181c4752bf5990d21ba676"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4490,7 +4501,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4552,7 +4563,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4563,7 +4574,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4826,7 +4837,7 @@ dependencies = [
|
||||
"heck",
|
||||
"indexmap",
|
||||
"prettyplease",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
"wasm-metadata",
|
||||
"wit-bindgen-core",
|
||||
"wit-component",
|
||||
@@ -4842,7 +4853,7 @@ dependencies = [
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
"wit-bindgen-core",
|
||||
"wit-bindgen-rust",
|
||||
]
|
||||
@@ -4946,7 +4957,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -4967,7 +4978,7 @@ checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4987,7 +4998,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -5027,7 +5038,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -98,8 +98,8 @@ strip = false
|
||||
|
||||
[workspace.dependencies]
|
||||
serde_json5 = "0.2.1"
|
||||
tokio = { version = "1.52", default-features = false }
|
||||
syn = { version = "2.0", default-features = false, features = ["printing"] }
|
||||
tokio = { version = "1.53", default-features = false }
|
||||
syn = { version = "3.0", default-features = false, features = ["full", "parsing", "printing", "proc-macro", "clone-impls", "derive"] }
|
||||
|
||||
thiserror = { version = "2.0", default-features = false }
|
||||
|
||||
@@ -110,7 +110,7 @@ futures = { version = "0.3", default-features = false, features = ["executor"] }
|
||||
rayon = { version = "1.12", default-features = false }
|
||||
crossbeam = { version = "0.8", default-features = false, features = ["std"] }
|
||||
|
||||
uuid = { version = "1.23", default-features = false, features = ["serde", "v3", "v4", "std"] }
|
||||
uuid = { version = "1.24", default-features = false, features = ["serde", "v3", "v4", "std"] }
|
||||
serde = { version = "1.0", default-features = false, features = ["derive", "std"] }
|
||||
serde_repr = { version = "0.1", default-features = false }
|
||||
serde_json = { version = "1.0", default-features = false, features = ["std"] }
|
||||
@@ -120,7 +120,7 @@ proc-macro-error2 = { version = "2", default-features = false }
|
||||
aes = { version = "0.9", default-features = false }
|
||||
async-compression = { version = "0.4.42", default-features = false }
|
||||
base64 = { version = "0.22.1", default-features = false, features = ["std"] }
|
||||
bitflags = { version = "2.13.0", default-features = false, features = ["std"] }
|
||||
bitflags = { version = "2.13.1", default-features = false, features = ["std"] }
|
||||
cesu8 = { version = "1.1", default-features = false }
|
||||
cfb8 = { version = "0.9", default-features = false }
|
||||
ctr = { version = "0.10.1", default-features = false }
|
||||
|
||||
@@ -17,9 +17,9 @@ pumpkin-data = { workspace = true, features = ["packet", "item_id_remap", "entit
|
||||
pumpkin-macros.workspace = true
|
||||
pumpkin-world.workspace = true
|
||||
pumpkin-util.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
||||
uuid.workspace = true
|
||||
serde.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio = { workspace = true, features = ["net"] }
|
||||
bytes.workspace = true
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use crate::ReadingError;
|
||||
use crate::WritingError;
|
||||
use crate::ser::NetworkReadExt;
|
||||
@@ -34,11 +32,3 @@ impl BitSet {
|
||||
Ok(Self(array.into_boxed_slice()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for BitSet {
|
||||
fn serialize<S: Serializer>(&self, _serializer: S) -> Result<S::Ok, S::Error> {
|
||||
Err(serde::ser::Error::custom(
|
||||
"BitSet serialization not implemented",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
use crate::VarInt;
|
||||
use crate::codec::data_component::{deserialize, serialize};
|
||||
use crate::ser::{NetworkReadExt, ReadingError, WritingError, deserializer, serializer};
|
||||
use crate::ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError};
|
||||
use pumpkin_data::data_component::DataComponent;
|
||||
use pumpkin_data::data_component_impl::{CustomNameImpl, DataComponentImpl};
|
||||
use pumpkin_data::item::Item;
|
||||
@@ -9,13 +9,8 @@ use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_nbt::tag::NbtTag;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
use serde::ser::SerializeStruct;
|
||||
use serde::{
|
||||
Deserialize, Serialize, Serializer,
|
||||
de::{self, DeserializeSeed, SeqAccess},
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::io::{Cursor, Read};
|
||||
use std::io::Cursor;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ItemStackSerializer<'a>(pub Cow<'a, ItemStack>);
|
||||
@@ -35,67 +30,52 @@ fn item_component_counts(stack: &ItemStack) -> (u8, u8) {
|
||||
(to_add, to_remove)
|
||||
}
|
||||
|
||||
fn serialize_any_item_stack_with_id<S: Serializer>(
|
||||
fn serialize_any_item_stack_with_id(
|
||||
stack: &ItemStack,
|
||||
item_id: u16,
|
||||
is_template: bool,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
write: &mut impl NetworkWriteExt,
|
||||
) -> Result<(), WritingError> {
|
||||
if stack.is_empty() {
|
||||
VarInt(0).serialize(serializer)
|
||||
write.put_var_int(&VarInt(0))
|
||||
} else {
|
||||
let (to_add, to_remove) = item_component_counts(stack);
|
||||
let mut seq = serializer.serialize_struct("", 0)?;
|
||||
if is_template {
|
||||
seq.serialize_field("", &VarInt::from(item_id))?;
|
||||
seq.serialize_field("", &VarInt::from(stack.item_count))?;
|
||||
write.put_var_int(&VarInt::from(item_id))?;
|
||||
write.put_var_int(&VarInt::from(stack.item_count))?;
|
||||
} else {
|
||||
seq.serialize_field("", &VarInt::from(stack.item_count))?;
|
||||
seq.serialize_field("", &VarInt::from(item_id))?;
|
||||
write.put_var_int(&VarInt::from(stack.item_count))?;
|
||||
write.put_var_int(&VarInt::from(item_id))?;
|
||||
}
|
||||
seq.serialize_field::<VarInt>("", &VarInt::from(to_add))?;
|
||||
seq.serialize_field::<VarInt>("", &VarInt::from(to_remove))?;
|
||||
write.put_var_int(&VarInt::from(to_add))?;
|
||||
write.put_var_int(&VarInt::from(to_remove))?;
|
||||
|
||||
for (id, data) in &stack.patch {
|
||||
if let Some(data) = data {
|
||||
seq.serialize_field::<VarInt>("", &VarInt::from(id.to_id()))?;
|
||||
serialize(*id, data.as_ref(), &mut seq)?;
|
||||
write.put_var_int(&VarInt::from(id.to_id()))?;
|
||||
serialize(*id, data.as_ref(), write)?;
|
||||
}
|
||||
}
|
||||
|
||||
for (id, data) in &stack.patch {
|
||||
if data.is_none() {
|
||||
seq.serialize_field::<VarInt>("", &VarInt::from(id.to_id()))?;
|
||||
write.put_var_int(&VarInt::from(id.to_id()))?;
|
||||
}
|
||||
}
|
||||
|
||||
seq.end()
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
fn serialize_item_stack_with_id<S: Serializer>(
|
||||
|
||||
fn serialize_item_stack_with_id(
|
||||
stack: &ItemStack,
|
||||
item_id: u16,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
serialize_any_item_stack_with_id(stack, item_id, false, serializer)
|
||||
write: &mut impl NetworkWriteExt,
|
||||
) -> Result<(), WritingError> {
|
||||
serialize_any_item_stack_with_id(stack, item_id, false, write)
|
||||
}
|
||||
|
||||
struct ComponentAccess<R: Read> {
|
||||
deserializer: deserializer::Deserializer<R>,
|
||||
}
|
||||
|
||||
impl<'de, R: Read> SeqAccess<'de> for ComponentAccess<R> {
|
||||
type Error = ReadingError;
|
||||
|
||||
fn next_element_seed<T: DeserializeSeed<'de>>(
|
||||
&mut self,
|
||||
seed: T,
|
||||
) -> Result<Option<T::Value>, Self::Error> {
|
||||
seed.deserialize(&mut self.deserializer).map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_component_id(read: &mut impl Read) -> Result<DataComponent, ReadingError> {
|
||||
fn read_component_id(read: &mut impl NetworkReadExt) -> Result<DataComponent, ReadingError> {
|
||||
let id_val = read.get_var_int()?.0;
|
||||
let id_u8 = id_val
|
||||
.try_into()
|
||||
@@ -122,7 +102,7 @@ fn decode_custom_name(component_data: &[u8]) -> Result<Box<dyn DataComponentImpl
|
||||
}
|
||||
|
||||
fn read_length_prefixed_component(
|
||||
read: &mut impl Read,
|
||||
read: &mut impl NetworkReadExt,
|
||||
) -> Result<(DataComponent, Box<dyn DataComponentImpl>), ReadingError> {
|
||||
let id = read_component_id(read)?;
|
||||
let byte_len = read.get_var_int()?.0;
|
||||
@@ -134,114 +114,82 @@ fn read_length_prefixed_component(
|
||||
let component_impl = if id == DataComponent::CustomName {
|
||||
decode_custom_name(component_data.as_ref())?
|
||||
} else {
|
||||
let cursor = Cursor::new(component_data);
|
||||
let mut access = ComponentAccess {
|
||||
deserializer: deserializer::Deserializer::new(cursor),
|
||||
};
|
||||
deserialize(id, &mut access)?
|
||||
let mut cursor = Cursor::new(component_data);
|
||||
deserialize(id, &mut cursor)?
|
||||
};
|
||||
|
||||
Ok((id, component_impl))
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ItemStackSerializer<'static> {
|
||||
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
struct Visitor;
|
||||
impl<'de> de::Visitor<'de> for Visitor {
|
||||
type Value = ItemStackSerializer<'static>;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid Slot encoded in a byte sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
const MAX_COMPONENTS: i32 = 256;
|
||||
|
||||
let item_count = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or_else(|| de::Error::custom("Failed to decode VarInt"))?;
|
||||
|
||||
if item_count.0 == 0 {
|
||||
return Ok(ItemStackSerializer(Cow::Borrowed(ItemStack::EMPTY)));
|
||||
}
|
||||
|
||||
let item_id = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or_else(|| de::Error::custom("No item id VarInt!"))?;
|
||||
|
||||
let num_to_add = seq.next_element::<VarInt>()?.map_or(0, |v| v.0);
|
||||
let num_to_remove = seq.next_element::<VarInt>()?.map_or(0, |v| v.0);
|
||||
|
||||
if num_to_add < 0 || num_to_remove < 0 {
|
||||
return Err(de::Error::custom("Negative component count"));
|
||||
}
|
||||
|
||||
let total_components = num_to_add
|
||||
.checked_add(num_to_remove)
|
||||
.ok_or_else(|| de::Error::custom("Component count overflow"))?;
|
||||
|
||||
if total_components > MAX_COMPONENTS {
|
||||
return Err(de::Error::custom("Too many components in ItemStack patch"));
|
||||
}
|
||||
|
||||
let mut patch = Vec::with_capacity((num_to_add + num_to_remove) as usize);
|
||||
|
||||
for _ in 0..num_to_add {
|
||||
let id_val = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or_else(|| de::Error::custom("Missing component ID"))?
|
||||
.0;
|
||||
let id = DataComponent::try_from_id(id_val as u8).ok_or_else(|| {
|
||||
de::Error::custom(format!("Unknown component ID: {id_val}"))
|
||||
})?;
|
||||
|
||||
// Minecraft protocol sends a byte length for the component data here
|
||||
let _byte_len = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or_else(|| de::Error::custom("No data len VarInt!"))?;
|
||||
|
||||
let component_impl = deserialize(id, &mut seq)?;
|
||||
|
||||
patch.push((id, Some(component_impl)));
|
||||
}
|
||||
|
||||
for _ in 0..num_to_remove {
|
||||
let id_val = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or_else(|| de::Error::custom("Missing remove component ID"))?
|
||||
.0;
|
||||
let id = DataComponent::try_from_id(id_val as u8)
|
||||
.ok_or_else(|| de::Error::custom("Unknown component ID"))?;
|
||||
patch.push((id, None));
|
||||
}
|
||||
|
||||
let item_id_u16: u16 = item_id
|
||||
.0
|
||||
.try_into()
|
||||
.map_err(|_| de::Error::custom("Invalid item id!"))?;
|
||||
|
||||
Ok(ItemStackSerializer(Cow::Owned(
|
||||
ItemStack::new_with_component(
|
||||
item_count.0 as u8,
|
||||
Item::from_id(item_id_u16).unwrap_or(&Item::AIR),
|
||||
patch,
|
||||
),
|
||||
)))
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_seq(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ItemStackSerializer<'_> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serialize_item_stack_with_id(self.0.as_ref(), self.0.item.id, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemStackSerializer<'_> {
|
||||
pub fn read(
|
||||
read: &mut impl NetworkReadExt,
|
||||
) -> Result<ItemStackSerializer<'static>, ReadingError> {
|
||||
const MAX_COMPONENTS: i32 = 256;
|
||||
|
||||
let item_count = read.get_var_int()?;
|
||||
if item_count.0 == 0 {
|
||||
return Ok(ItemStackSerializer(Cow::Borrowed(ItemStack::EMPTY)));
|
||||
}
|
||||
|
||||
let item_id = read.get_var_int()?;
|
||||
let num_to_add = read.get_var_int()?.0;
|
||||
let num_to_remove = read.get_var_int()?.0;
|
||||
|
||||
if num_to_add < 0 || num_to_remove < 0 {
|
||||
return Err(ReadingError::Message("Negative component count".into()));
|
||||
}
|
||||
|
||||
let total_components = num_to_add
|
||||
.checked_add(num_to_remove)
|
||||
.ok_or_else(|| ReadingError::Message("Component count overflow".into()))?;
|
||||
|
||||
if total_components > MAX_COMPONENTS {
|
||||
return Err(ReadingError::Message(
|
||||
"Too many components in ItemStack patch".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut patch = Vec::with_capacity((num_to_add + num_to_remove) as usize);
|
||||
|
||||
for _ in 0..num_to_add {
|
||||
let id_val = read.get_var_int()?.0;
|
||||
let id = DataComponent::try_from_id(id_val as u8)
|
||||
.ok_or_else(|| ReadingError::Message(format!("Unknown component ID: {id_val}")))?;
|
||||
|
||||
let _byte_len = read.get_var_int()?;
|
||||
|
||||
let component_impl = deserialize(id, read)?;
|
||||
patch.push((id, Some(component_impl)));
|
||||
}
|
||||
|
||||
for _ in 0..num_to_remove {
|
||||
let id_val = read.get_var_int()?.0;
|
||||
let id = DataComponent::try_from_id(id_val as u8)
|
||||
.ok_or_else(|| ReadingError::Message("Unknown component ID".into()))?;
|
||||
patch.push((id, None));
|
||||
}
|
||||
|
||||
let item_id_u16: u16 = item_id
|
||||
.0
|
||||
.try_into()
|
||||
.map_err(|_| ReadingError::Message("Invalid item id!".into()))?;
|
||||
|
||||
Ok(ItemStackSerializer(Cow::Owned(
|
||||
ItemStack::new_with_component(
|
||||
item_count.0 as u8,
|
||||
Item::from_id(item_id_u16).unwrap_or(&Item::AIR),
|
||||
patch,
|
||||
),
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn write(&self, write: &mut impl NetworkWriteExt) -> Result<(), WritingError> {
|
||||
serialize_item_stack_with_id(self.0.as_ref(), self.0.item.id, write)
|
||||
}
|
||||
|
||||
pub fn read_length_prefixed_optional(
|
||||
mut read: impl Read,
|
||||
read: &mut impl NetworkReadExt,
|
||||
) -> Result<ItemStackSerializer<'static>, ReadingError> {
|
||||
const MAX_COMPONENTS: i32 = 256;
|
||||
|
||||
@@ -275,12 +223,12 @@ impl ItemStackSerializer<'_> {
|
||||
let mut patch = Vec::with_capacity(total_components as usize);
|
||||
|
||||
for _ in 0..num_to_add {
|
||||
let (id, component_impl) = read_length_prefixed_component(&mut read)?;
|
||||
let (id, component_impl) = read_length_prefixed_component(read)?;
|
||||
patch.push((id, Some(component_impl)));
|
||||
}
|
||||
|
||||
for _ in 0..num_to_remove {
|
||||
patch.push((read_component_id(&mut read)?, None));
|
||||
patch.push((read_component_id(read)?, None));
|
||||
}
|
||||
|
||||
let item_id_u16 = item_id
|
||||
@@ -299,12 +247,11 @@ impl ItemStackSerializer<'_> {
|
||||
|
||||
pub fn write_with_version(
|
||||
&self,
|
||||
write: impl std::io::Write,
|
||||
write: &mut impl NetworkWriteExt,
|
||||
version: &JavaMinecraftVersion,
|
||||
) -> Result<(), WritingError> {
|
||||
let remapped_item_id = remap_item_id_for_version(self.0.item.id, *version);
|
||||
let mut network_serializer = serializer::Serializer::new(write);
|
||||
serialize_item_stack_with_id(self.0.as_ref(), remapped_item_id, &mut network_serializer)
|
||||
serialize_item_stack_with_id(self.0.as_ref(), remapped_item_id, write)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
@@ -346,6 +293,49 @@ pub struct ItemComponentHash {
|
||||
pub removed: Vec<VarInt>,
|
||||
}
|
||||
|
||||
impl ItemComponentHash {
|
||||
pub fn read(read: &mut impl NetworkReadExt) -> Result<Self, ReadingError> {
|
||||
const MAX_COMPONENTS: i32 = 256;
|
||||
|
||||
let mut added = Vec::new();
|
||||
let mut removed = Vec::new();
|
||||
|
||||
let added_length = read.get_var_int()?;
|
||||
if added_length.0 < 0 || added_length.0 > MAX_COMPONENTS {
|
||||
return Err(ReadingError::Message("added_length out of bounds".into()));
|
||||
}
|
||||
for _ in 0..added_length.0 {
|
||||
let component_id = read.get_var_int()?;
|
||||
let component_value = read.get_i32()?;
|
||||
added.push((component_id, component_value));
|
||||
}
|
||||
|
||||
let removed_length = read.get_var_int()?;
|
||||
if removed_length.0 < 0 || removed_length.0 > MAX_COMPONENTS {
|
||||
return Err(ReadingError::Message("removed_length out of bounds".into()));
|
||||
}
|
||||
for _ in 0..removed_length.0 {
|
||||
let component_id = read.get_var_int()?;
|
||||
removed.push(component_id);
|
||||
}
|
||||
|
||||
Ok(Self { added, removed })
|
||||
}
|
||||
|
||||
pub fn write(&self, write: &mut impl NetworkWriteExt) -> Result<(), WritingError> {
|
||||
write.put_var_int(&VarInt::from(self.added.len() as i32))?;
|
||||
for (id, val) in &self.added {
|
||||
write.put_var_int(id)?;
|
||||
write.put_i32(*val)?;
|
||||
}
|
||||
write.put_var_int(&VarInt::from(self.removed.len() as i32))?;
|
||||
for id in &self.removed {
|
||||
write.put_var_int(id)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ItemStackHash {
|
||||
item_id: VarInt,
|
||||
@@ -353,7 +343,39 @@ pub struct ItemStackHash {
|
||||
components: ItemComponentHash,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OptionalItemStackHash(pub Option<ItemStackHash>);
|
||||
|
||||
impl OptionalItemStackHash {
|
||||
pub fn read(read: &mut impl NetworkReadExt) -> Result<Self, ReadingError> {
|
||||
let is_some = read.get_bool()?;
|
||||
if is_some {
|
||||
let item_id = read.get_var_int()?;
|
||||
let count = read.get_var_int()?;
|
||||
let components = ItemComponentHash::read(read)?;
|
||||
|
||||
Ok(Self(Some(ItemStackHash {
|
||||
item_id,
|
||||
count,
|
||||
components,
|
||||
})))
|
||||
} else {
|
||||
Ok(Self(None))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, write: &mut impl NetworkWriteExt) -> Result<(), WritingError> {
|
||||
if let Some(hash) = &self.0 {
|
||||
write.put_bool(true)?;
|
||||
write.put_var_int(&hash.item_id)?;
|
||||
write.put_var_int(&hash.count)?;
|
||||
hash.components.write(write)?;
|
||||
} else {
|
||||
write.put_bool(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn hash_equals(&self, other: &ItemStack) -> bool {
|
||||
if let Some(hash) = &self.0 {
|
||||
@@ -404,121 +426,26 @@ impl OptionalItemStackHash {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OptionalItemStackHash(pub Option<ItemStackHash>);
|
||||
|
||||
impl<'de> Deserialize<'de> for OptionalItemStackHash {
|
||||
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
struct Visitor;
|
||||
impl<'de> de::Visitor<'de> for Visitor {
|
||||
type Value = OptionalItemStackHash;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid Slot encoded in a byte sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let is_some = seq
|
||||
.next_element::<bool>()?
|
||||
.ok_or(de::Error::custom("No is some bool!"))?;
|
||||
if is_some {
|
||||
let item_id = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or(de::Error::custom("No item id VarInt!"))?;
|
||||
let count = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or(de::Error::custom("No item count VarInt!"))?;
|
||||
|
||||
let hashed_components = seq
|
||||
.next_element::<ItemComponentHash>()?
|
||||
.ok_or(de::Error::custom("No item component hash!"))?;
|
||||
|
||||
let item_stack_hash = ItemStackHash {
|
||||
item_id,
|
||||
count,
|
||||
components: hashed_components,
|
||||
};
|
||||
Ok(OptionalItemStackHash(Some(item_stack_hash)))
|
||||
} else {
|
||||
Ok(OptionalItemStackHash(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ItemComponentHash {
|
||||
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
struct Visitor;
|
||||
impl<'de> de::Visitor<'de> for Visitor {
|
||||
type Value = ItemComponentHash;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid Slot encoded in a byte sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
const MAX_COMPONENTS: i32 = 256;
|
||||
|
||||
let mut added = Vec::new();
|
||||
let mut removed = Vec::new();
|
||||
|
||||
let added_length = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or(de::Error::custom("No added length VarInt!"))?;
|
||||
if added_length.0 < 0 || added_length.0 > MAX_COMPONENTS {
|
||||
return Err(de::Error::custom("added_length out of bounds"));
|
||||
}
|
||||
for _ in 0..added_length.0 {
|
||||
let component_id = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or(de::Error::custom("No component id VarInt!"))?;
|
||||
let component_value = seq
|
||||
.next_element::<i32>()?
|
||||
.ok_or(de::Error::custom("No component value i32!"))?;
|
||||
added.push((component_id, component_value));
|
||||
}
|
||||
|
||||
let removed_length = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or(de::Error::custom("No removed length VarInt!"))?;
|
||||
if removed_length.0 < 0 || removed_length.0 > MAX_COMPONENTS {
|
||||
return Err(de::Error::custom("removed_length out of bounds"));
|
||||
}
|
||||
for _ in 0..removed_length.0 {
|
||||
let component_id = seq
|
||||
.next_element::<VarInt>()?
|
||||
.ok_or(de::Error::custom("No component id VarInt!"))?;
|
||||
removed.push(component_id);
|
||||
}
|
||||
|
||||
Ok(ItemComponentHash { added, removed })
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ItemStackTemplateSerializer<'a>(pub Cow<'a, ItemStack>);
|
||||
|
||||
impl ItemStackTemplateSerializer<'_> {
|
||||
pub fn write_with_version(
|
||||
&self,
|
||||
write: impl std::io::Write,
|
||||
write: &mut impl NetworkWriteExt,
|
||||
version: &JavaMinecraftVersion,
|
||||
) -> Result<(), WritingError> {
|
||||
let remapped_item_id = remap_item_id_for_version(self.0.item.id, *version);
|
||||
let mut network_serializer = serializer::Serializer::new(write);
|
||||
serialize_any_item_stack_with_id(
|
||||
self.0.as_ref(),
|
||||
remapped_item_id,
|
||||
*version >= JavaMinecraftVersion::V_26_1,
|
||||
&mut network_serializer,
|
||||
write,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn write(&self, write: &mut impl NetworkWriteExt) -> Result<(), WritingError> {
|
||||
serialize_any_item_stack_with_id(self.0.as_ref(), self.0.item.id, true, write)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ItemStack> for ItemStackTemplateSerializer<'_> {
|
||||
@@ -526,12 +453,3 @@ impl From<ItemStack> for ItemStackTemplateSerializer<'_> {
|
||||
ItemStackTemplateSerializer(Cow::Owned(item))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ItemStackTemplateSerializer<'_> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serialize_any_item_stack_with_id(self.0.as_ref(), self.0.item.id, true, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +1,65 @@
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
pub struct Le64(pub i64);
|
||||
|
||||
impl Serialize for Le64 {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_bytes(&self.0.to_le_bytes())
|
||||
impl Le64 {
|
||||
pub fn write(
|
||||
&self,
|
||||
write: &mut impl crate::ser::NetworkWriteExt,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.0.to_le_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Le32(pub i32);
|
||||
|
||||
impl Serialize for Le32 {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_bytes(&self.0.to_le_bytes())
|
||||
impl Le32 {
|
||||
pub fn write(
|
||||
&self,
|
||||
write: &mut impl crate::ser::NetworkWriteExt,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.0.to_le_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Le16(pub i16);
|
||||
|
||||
impl Serialize for Le16 {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_bytes(&self.0.to_le_bytes())
|
||||
impl Le16 {
|
||||
pub fn write(
|
||||
&self,
|
||||
write: &mut impl crate::ser::NetworkWriteExt,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.0.to_le_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
// Unsigned
|
||||
|
||||
pub struct LeU64(pub u64);
|
||||
|
||||
impl Serialize for LeU64 {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_bytes(&self.0.to_le_bytes())
|
||||
impl LeU64 {
|
||||
pub fn write(
|
||||
&self,
|
||||
write: &mut impl crate::ser::NetworkWriteExt,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.0.to_le_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LeU32(pub u32);
|
||||
|
||||
impl Serialize for LeU32 {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_bytes(&self.0.to_le_bytes())
|
||||
impl LeU32 {
|
||||
pub fn write(
|
||||
&self,
|
||||
write: &mut impl crate::ser::NetworkWriteExt,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.0.to_le_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LeU16(pub u16);
|
||||
|
||||
impl Serialize for LeU16 {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_bytes(&self.0.to_le_bytes())
|
||||
impl LeU16 {
|
||||
pub fn write(
|
||||
&self,
|
||||
write: &mut impl crate::ser::NetworkWriteExt,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.0.to_le_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
use std::fmt::Formatter;
|
||||
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
|
||||
use crate::{
|
||||
VarInt,
|
||||
ser::{NetworkWriteExt, ReadingError, WritingError},
|
||||
};
|
||||
use serde::{
|
||||
Deserializer, Serialize,
|
||||
de::{self, Visitor},
|
||||
ser::Serializer,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct LpVector3d(pub Vector3<f64>);
|
||||
@@ -153,42 +146,6 @@ fn from_long(quantized: i64, scale: f64) -> f64 {
|
||||
(normalized / 0.5) * scale
|
||||
}
|
||||
|
||||
impl Serialize for LpVector3d {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut buf = Vec::new();
|
||||
self.write(&mut buf)
|
||||
.map_err(|e| serde::ser::Error::custom(e.to_string()))?;
|
||||
serializer.serialize_bytes(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserialize<'de> for LpVector3d {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct VelocityVisitor;
|
||||
|
||||
impl Visitor<'_> for VelocityVisitor {
|
||||
type Value = LpVector3d;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a byte array representing bit-packed velocity")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let mut cursor = std::io::Cursor::new(v);
|
||||
LpVector3d::read(&mut cursor).map_err(de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(VelocityVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{LpVector3d, encode_legacy_velocity_component};
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use crate::codec::var_int::VarInt;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct OptionalInt(pub Option<i32>);
|
||||
|
||||
impl Serialize for OptionalInt {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
// Vanilla logic: empty is 0, otherwise value + 1
|
||||
impl OptionalInt {
|
||||
pub fn write(
|
||||
&self,
|
||||
write: &mut impl crate::ser::NetworkWriteExt,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
let val = self.0.map_or(0, |id| id + 1);
|
||||
VarInt(val).serialize(serializer)
|
||||
write.write_var_int(&crate::codec::var_int::VarInt(val))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use pumpkin_data::recipes::RecipeCategoryTypes;
|
||||
use serde::Serialize;
|
||||
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_data::tag::Taggable;
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum OwnedRecipeIngredient {
|
||||
Simple(String),
|
||||
Tagged(String),
|
||||
@@ -30,14 +29,14 @@ impl OwnedRecipeIngredient {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedRecipeResult {
|
||||
pub item_id: String,
|
||||
pub count: u8,
|
||||
// TODO: Add components/enchantments if needed for the display result
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum OwnedCraftingRecipe {
|
||||
Shaped {
|
||||
category: RecipeCategoryTypes,
|
||||
@@ -55,7 +54,7 @@ pub enum OwnedCraftingRecipe {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedCookingRecipe {
|
||||
pub recipe_id: String,
|
||||
pub category: RecipeCategoryTypes,
|
||||
@@ -66,7 +65,7 @@ pub struct OwnedCookingRecipe {
|
||||
pub result: OwnedRecipeResult,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum OwnedCookingRecipeType {
|
||||
Blasting(OwnedCookingRecipe),
|
||||
Smelting(OwnedCookingRecipe),
|
||||
@@ -74,7 +73,7 @@ pub enum OwnedCookingRecipeType {
|
||||
CampfireCooking(OwnedCookingRecipe),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum DynamicRecipe {
|
||||
Crafting(OwnedCraftingRecipe),
|
||||
Cooking(OwnedCookingRecipeType),
|
||||
|
||||
@@ -4,11 +4,6 @@ use std::{
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use bytes::BufMut;
|
||||
use serde::{
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
de::{SeqAccess, Visitor},
|
||||
};
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||
|
||||
use crate::{
|
||||
@@ -153,53 +148,6 @@ impl Deref for VarInt {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for VarInt {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut value = self.0 as u32;
|
||||
let mut buf = Vec::new();
|
||||
|
||||
while value > 0x7F {
|
||||
buf.put_u8(value as u8 | 0x80);
|
||||
value >>= 7;
|
||||
}
|
||||
|
||||
buf.put_u8(value as u8);
|
||||
|
||||
serializer.serialize_bytes(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for VarInt {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
struct VarIntVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for VarIntVisitor {
|
||||
type Value = VarInt;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid VarInt encoded in a byte sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let mut val = 0;
|
||||
for i in 0..VarInt::MAX_SIZE.get() {
|
||||
if let Some(byte) = seq.next_element::<u8>()? {
|
||||
val |= (i32::from(byte) & 0b0111_1111) << (i * 7);
|
||||
if byte & 0b1000_0000 == 0 {
|
||||
return Ok(VarInt(val));
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(serde::de::Error::custom("VarInt was too large"))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(VarIntVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl PacketWrite for VarInt {
|
||||
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
let mut val = ((self.0 << 1) ^ (self.0 >> 31)) as u32;
|
||||
|
||||
@@ -4,11 +4,6 @@ use std::{
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use serde::{
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
de::{self, SeqAccess, Visitor},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
WritingError,
|
||||
ser::{NetworkReadExt, NetworkWriteExt, ReadingError},
|
||||
@@ -92,53 +87,6 @@ impl Deref for VarLong {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for VarLong {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut value = self.0 as u64;
|
||||
let mut buf = Vec::new();
|
||||
|
||||
while value > 0x7F {
|
||||
buf.push(value as u8 | 0x80);
|
||||
value >>= 7;
|
||||
}
|
||||
|
||||
buf.push(value as u8);
|
||||
|
||||
serializer.serialize_bytes(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for VarLong {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
struct VarLongVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for VarLongVisitor {
|
||||
type Value = VarLong;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid VarInt encoded in a byte sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let mut val = 0;
|
||||
for i in 0..VarLong::MAX_SIZE.get() {
|
||||
if let Some(byte) = seq.next_element::<u8>()? {
|
||||
val |= (i64::from(byte) & 0b0111_1111) << (i * 7);
|
||||
if byte & 0b1000_0000 == 0 {
|
||||
return Ok(VarLong(val));
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(de::Error::custom("VarInt was too large"))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(VarLongVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl PacketRead for VarLong {
|
||||
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
||||
let mut val: u64 = 0;
|
||||
|
||||
@@ -3,11 +3,6 @@ use std::{
|
||||
num::NonZeroUsize,
|
||||
};
|
||||
|
||||
use bytes::BufMut;
|
||||
use serde::{
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
de::{SeqAccess, Visitor},
|
||||
};
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||
|
||||
use crate::{
|
||||
@@ -136,53 +131,6 @@ gen_from!(u64);
|
||||
gen_from!(isize);
|
||||
gen_from!(usize);
|
||||
|
||||
impl Serialize for VarUInt {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut value = self.0;
|
||||
let mut buf = Vec::with_capacity(5);
|
||||
|
||||
while value > 0x7F {
|
||||
buf.put_u8(value as u8 | 0x80);
|
||||
value >>= 7;
|
||||
}
|
||||
|
||||
buf.put_u8(value as u8);
|
||||
|
||||
serializer.serialize_bytes(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for VarUInt {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
struct VarIntVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for VarIntVisitor {
|
||||
type Value = VarUInt;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid VarInt encoded in a byte sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let mut val = 0;
|
||||
for i in 0..VarUInt::MAX_SIZE.get() {
|
||||
if let Some(byte) = seq.next_element::<u8>()? {
|
||||
val |= (u32::from(byte) & 0b0111_1111) << (i * 7);
|
||||
if byte & 0b1000_0000 == 0 {
|
||||
return Ok(VarUInt(val));
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(serde::de::Error::custom("VarInt was too large"))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(VarIntVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl PacketWrite for VarUInt {
|
||||
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
let mut val = self.0;
|
||||
|
||||
@@ -4,11 +4,6 @@ use std::{
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use serde::{
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
de::{self, SeqAccess, Visitor},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
WritingError,
|
||||
ser::{NetworkReadExt, NetworkWriteExt, ReadingError},
|
||||
@@ -115,53 +110,6 @@ impl Deref for VarULong {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for VarULong {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
let mut value = self.0;
|
||||
let mut buf = Vec::new();
|
||||
|
||||
while value > 0x7F {
|
||||
buf.push(value as u8 | 0x80);
|
||||
value >>= 7;
|
||||
}
|
||||
|
||||
buf.push(value as u8);
|
||||
|
||||
serializer.serialize_bytes(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for VarULong {
|
||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
struct VarLongVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for VarLongVisitor {
|
||||
type Value = VarULong;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid VarInt encoded in a byte sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
let mut val = 0;
|
||||
for i in 0..VarULong::MAX_SIZE.get() {
|
||||
if let Some(byte) = seq.next_element::<u8>()? {
|
||||
val |= (u64::from(byte) & 0b0111_1111) << (i * 7);
|
||||
if byte & 0b1000_0000 == 0 {
|
||||
return Ok(VarULong(val));
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(de::Error::custom("VarInt was too large"))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(VarLongVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl PacketWrite for VarULong {
|
||||
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
let mut x = self.0;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use pumpkin_data::packet::clientbound::CONFIG_RESOURCE_PACK_PUSH;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_RESOURCE_PACK_PUSH)]
|
||||
pub struct CConfigAddResourcePack<'a> {
|
||||
#[serde(with = "uuid::serde::compact")]
|
||||
pub uuid: &'a uuid::Uuid,
|
||||
pub url: &'a str,
|
||||
pub hash: &'a str, // max 40
|
||||
@@ -34,3 +35,23 @@ impl<'a> CConfigAddResourcePack<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CConfigAddResourcePack<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_uuid(self.uuid)?;
|
||||
write.write_string(self.url)?;
|
||||
write.write_string(self.hash)?;
|
||||
write.write_bool(self.forced)?;
|
||||
if let Some(_prompt) = &self.prompt_message {
|
||||
write.write_bool(true)?;
|
||||
// TODO
|
||||
} else {
|
||||
write.write_bool(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use pumpkin_data::packet::clientbound::CONFIG_CLEAR_DIALOG;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_CLEAR_DIALOG)]
|
||||
pub struct CConfigClearDialog;
|
||||
|
||||
@@ -18,3 +19,13 @@ impl Default for CConfigClearDialog {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CConfigClearDialog {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
_write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::CONFIG_DISCONNECT;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(serde::Serialize, Deserialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_DISCONNECT)]
|
||||
pub struct CConfigDisconnect<'a> {
|
||||
pub reason: &'a str,
|
||||
@@ -14,3 +16,14 @@ impl<'a> CConfigDisconnect<'a> {
|
||||
Self { reason }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CConfigDisconnect<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.reason)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@ use pumpkin_data::packet::clientbound::CONFIG_COOKIE_REQUEST;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::resource_location::ResourceLocation;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_COOKIE_REQUEST)]
|
||||
/// Requests a cookie that was previously stored.
|
||||
pub struct CCookieRequest<'a> {
|
||||
@@ -15,3 +18,14 @@ impl<'a> CCookieRequest<'a> {
|
||||
Self { key }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CCookieRequest<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.key)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
use pumpkin_data::packet::clientbound::CONFIG_FINISH_CONFIGURATION;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_FINISH_CONFIGURATION)]
|
||||
pub struct CFinishConfig;
|
||||
|
||||
impl ClientPacket for CFinishConfig {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
_write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::CONFIG_SELECT_KNOWN_PACKS;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::KnownPack;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(CONFIG_SELECT_KNOWN_PACKS)]
|
||||
pub struct CKnownPacks<'a> {
|
||||
pub known_packs: &'a [KnownPack<'a>],
|
||||
@@ -16,3 +17,17 @@ impl<'a> CKnownPacks<'a> {
|
||||
Self { known_packs }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CKnownPacks<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&crate::VarInt(self.known_packs.len() as i32))?;
|
||||
for pack in self.known_packs {
|
||||
pack.write(&mut write)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use crate::Link;
|
||||
use pumpkin_data::packet::clientbound::CONFIG_SERVER_LINKS;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_SERVER_LINKS)]
|
||||
pub struct CConfigServerLinks<'a> {
|
||||
pub links: &'a [Link<'a>],
|
||||
@@ -15,3 +17,17 @@ impl<'a> CConfigServerLinks<'a> {
|
||||
Self { links }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CConfigServerLinks<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&crate::VarInt(self.links.len() as i32))?;
|
||||
for link in self.links {
|
||||
link.write(&mut write)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ use crate::IdOr;
|
||||
use crate::java::client::dialog::DialogNBT;
|
||||
use pumpkin_data::packet::clientbound::CONFIG_SHOW_DIALOG;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_SHOW_DIALOG)]
|
||||
pub struct CConfigShowDialog<'a> {
|
||||
pub dialog: IdOr<DialogNBT<'a>>,
|
||||
@@ -16,3 +17,15 @@ impl<'a> CConfigShowDialog<'a> {
|
||||
Self { dialog }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CConfigShowDialog<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
self.dialog
|
||||
.write(&mut write, |w, dialog| dialog.write_packet_data(w, version))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@ use pumpkin_data::packet::clientbound::CONFIG_STORE_COOKIE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::resource_location::ResourceLocation;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_STORE_COOKIE)]
|
||||
/// Stores some arbitrary data on the client, which persists between server transfers.
|
||||
/// The Notchian (vanilla) client only accepts cookies of up to 5 KiB in size.
|
||||
@@ -17,3 +20,16 @@ impl<'a> CStoreCookie<'a> {
|
||||
Self { key, payload }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CStoreCookie<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.key)?;
|
||||
write.write_var_int(&crate::VarInt(self.payload.len() as i32))?;
|
||||
write.write_all(self.payload)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use crate::VarInt;
|
||||
use pumpkin_data::packet::clientbound::CONFIG_TRANSFER;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(CONFIG_TRANSFER)]
|
||||
pub struct CTransfer<'a> {
|
||||
pub host: &'a str,
|
||||
@@ -16,3 +18,15 @@ impl<'a> CTransfer<'a> {
|
||||
Self { host, port }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CTransfer<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.host)?;
|
||||
write.write_var_int(self.port)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
pub struct DialogNBT<'a>(pub DialogNBTSource<'a>);
|
||||
|
||||
impl<'a> DialogNBT<'a> {
|
||||
@@ -14,70 +15,67 @@ impl<'a> DialogNBT<'a> {
|
||||
pub const fn from_nbt(compound: &'a pumpkin_nbt::compound::NbtCompound) -> Self {
|
||||
Self(DialogNBTSource::Nbt(compound))
|
||||
}
|
||||
|
||||
#[allow(clippy::todo)]
|
||||
pub fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
match &self.0 {
|
||||
DialogNBTSource::Struct(_dialog) => {
|
||||
todo!("Serialize Dialog to NbtCompound manually")
|
||||
}
|
||||
DialogNBTSource::Nbt(nbt) => {
|
||||
let tag = pumpkin_nbt::tag::NbtTag::Compound((*nbt).clone());
|
||||
write.write_nbt(tag)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum DialogNBTSource<'a> {
|
||||
Struct(&'a Dialog),
|
||||
Nbt(&'a pumpkin_nbt::compound::NbtCompound),
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Dialog {
|
||||
pub r#type: String,
|
||||
pub title: TextComponent,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub body: Vec<DialogBody>,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub inputs: Vec<DialogInput>,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub buttons: Vec<ActionButton>,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub links: Vec<DialogLink>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub exit_action: Option<DialogAction>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub after_action: Option<String>,
|
||||
pub can_close_with_escape: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub external_title: Option<TextComponent>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum DialogBody {
|
||||
#[serde(rename = "minecraft:plain_message")]
|
||||
PlainMessage { contents: TextComponent },
|
||||
#[serde(rename = "minecraft:item")]
|
||||
Item { item: i32 }, // TODO: ItemStack serialization to NBT
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum DialogInput {
|
||||
#[serde(rename = "minecraft:boolean")]
|
||||
Boolean {
|
||||
label: TextComponent,
|
||||
default_value: bool,
|
||||
},
|
||||
#[serde(rename = "minecraft:text")]
|
||||
Text {
|
||||
label: TextComponent,
|
||||
placeholder: TextComponent,
|
||||
default_value: String,
|
||||
},
|
||||
#[serde(rename = "minecraft:number_range")]
|
||||
NumberRange {
|
||||
label: TextComponent,
|
||||
min: f32,
|
||||
max: f32,
|
||||
initial: f32,
|
||||
step: f32,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
label_format: Option<String>,
|
||||
},
|
||||
#[serde(rename = "minecraft:single_option")]
|
||||
SingleOption {
|
||||
label: TextComponent,
|
||||
options: Vec<TextComponent>,
|
||||
@@ -85,30 +83,23 @@ pub enum DialogInput {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct ActionButton {
|
||||
pub text: TextComponent,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tooltip: Option<TextComponent>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub width: Option<u32>,
|
||||
pub action: DialogAction,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum DialogAction {
|
||||
#[serde(rename = "minecraft:open_url")]
|
||||
OpenUrl { url: String },
|
||||
#[serde(rename = "minecraft:custom")]
|
||||
OpenUrl {
|
||||
url: String,
|
||||
},
|
||||
Custom {
|
||||
id: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
payload: Option<Vec<u8>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct DialogLink {
|
||||
pub label: crate::Label,
|
||||
pub url: String,
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use pumpkin_data::packet::clientbound::LOGIN_COOKIE_REQUEST;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::resource_location::ResourceLocation;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sent by the server to retrieve a previously stored cookie from the client.
|
||||
///
|
||||
/// This occurs during the login phase, allowing the server to identify
|
||||
/// returning players or retrieve session data stored during a previous visit.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(LOGIN_COOKIE_REQUEST)]
|
||||
pub struct CLoginCookieRequest<'a> {
|
||||
/// The unique identifier of the cookie being requested.
|
||||
@@ -20,3 +22,14 @@ impl<'a> CLoginCookieRequest<'a> {
|
||||
Self { key }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CLoginCookieRequest<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.key)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use pumpkin_data::packet::clientbound::LOGIN_HELLO;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sent by the server to initiate the encryption handshake.
|
||||
///
|
||||
/// This packet provides the client with the server's public key and a
|
||||
/// verification token, allowing the client to generate a shared secret
|
||||
/// for secure communication.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(LOGIN_HELLO)]
|
||||
pub struct CEncryptionRequest<'a> {
|
||||
/// The server's ID string. In modern Minecraft, this is usually
|
||||
@@ -39,3 +41,19 @@ impl<'a> CEncryptionRequest<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CEncryptionRequest<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.server_id)?;
|
||||
write.write_var_int(&crate::VarInt(self.public_key.len() as i32))?;
|
||||
write.write_all(self.public_key)?;
|
||||
write.write_var_int(&crate::VarInt(self.verify_token.len() as i32))?;
|
||||
write.write_all(self.verify_token)?;
|
||||
write.write_bool(self.should_authenticate)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
use pumpkin_data::packet::clientbound::LOGIN_LOGIN_DISCONNECT;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sent by the server to reject a login attempt or kick a player during the login phase
|
||||
///
|
||||
/// This is used for reasons such as the server being full, the player being banned,
|
||||
/// or version mismatches. After this packet is sent, the connection is closed.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(LOGIN_LOGIN_DISCONNECT)]
|
||||
pub struct CLoginDisconnect {
|
||||
/// A JSON-encoded chat component explaining why the player was disconnected.
|
||||
@@ -19,3 +21,14 @@ impl CLoginDisconnect {
|
||||
Self { json_reason }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CLoginDisconnect {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(&self.json_reason)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use pumpkin_data::packet::clientbound::{LOGIN_GAME_PROFILE, LOGIN_LOGIN_FINISHED};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{ClientPacket, Property, packet::MultiVersionJavaPacket, ser::NetworkWriteExt};
|
||||
|
||||
@@ -60,10 +59,7 @@ impl ClientPacket for CLoginSuccess<'_> {
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_uuid(self.uuid)?;
|
||||
write.write_string(self.username)?;
|
||||
write.write_list(self.properties, |write, property| {
|
||||
let mut serializer = crate::ser::serializer::Serializer::new(write);
|
||||
property.serialize(&mut serializer)
|
||||
})?;
|
||||
write.write_list(self.properties, |write, property| property.write(write))?;
|
||||
if version < &JavaMinecraftVersion::V_1_21_2 {
|
||||
write.write_bool(self.strict_error_handling)?;
|
||||
} else if version >= &JavaMinecraftVersion::V_26_2 {
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use pumpkin_data::packet::clientbound::LOGIN_LOGIN_COMPRESSION;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sent by the server to enable network compression for all subsequent packets.
|
||||
///
|
||||
/// Once this packet is sent, both the server and the client must compress any
|
||||
/// packet with a size equal to or greater than the specified threshold.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(LOGIN_LOGIN_COMPRESSION)]
|
||||
pub struct CSetCompression {
|
||||
/// The packet size threshold (in bytes) at which compression is applied.
|
||||
@@ -24,3 +25,14 @@ impl CSetCompression {
|
||||
Self { threshold }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetCompression {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.threshold)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_BLOCK_CHANGED_ACK;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::VarInt;
|
||||
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
/// Sent by the server to acknowledge a sequence of block changes initiated by the client.
|
||||
///
|
||||
/// This packet is critical for preventing "ghost blocks" and synchronization issues.
|
||||
/// It tells the client that the server has processed all actions up to a specific point.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(PLAY_BLOCK_CHANGED_ACK)]
|
||||
pub struct CAcknowledgeBlockChange {
|
||||
/// The ID of the last sequence processed by the server.
|
||||
@@ -25,3 +24,14 @@ impl CAcknowledgeBlockChange {
|
||||
Self { sequence_id }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CAcknowledgeBlockChange {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.sequence_id)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_ACTION_BAR_TEXT;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
/// Updates the text displayed above the player's hotbar (the Action Bar).
|
||||
///
|
||||
/// Unlike chat messages, Action Bar text is transient and generally used for
|
||||
/// non-critical status information like "Now entering: Wilderness" or
|
||||
/// mana/stamina counters.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_ACTION_BAR_TEXT)]
|
||||
pub struct CActionBar<'a> {
|
||||
/// The text component to be displayed.
|
||||
@@ -22,3 +22,14 @@ impl<'a> CActionBar<'a> {
|
||||
Self { action_bar }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CActionBar<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.action_bar.encode())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,41 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_AWARD_STATS;
|
||||
use pumpkin_macros::java_packet;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::codec::var_int::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
#[java_packet(PLAY_AWARD_STATS)]
|
||||
pub struct CAwardStats<'a> {
|
||||
pub stats: &'a [Statistic],
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct Statistic {
|
||||
pub category_id: VarInt,
|
||||
pub statistic_id: VarInt,
|
||||
pub value: VarInt,
|
||||
}
|
||||
|
||||
impl Statistic {
|
||||
pub fn write(&self, mut write: impl std::io::Write) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.category_id)?;
|
||||
write.write_var_int(&self.statistic_id)?;
|
||||
write.write_var_int(&self.value)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CAwardStats<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&VarInt(self.stats.len() as i32))?;
|
||||
for stat in self.stats {
|
||||
stat.write(&mut write)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_BLOCK_DESTRUCTION;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Updates the visual "breaking" progress of a block for all clients.
|
||||
///
|
||||
/// This packet controls the overlay of cracks that appear on a block when
|
||||
/// it is being mined. It is often used to show other players' mining progress.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_BLOCK_DESTRUCTION)]
|
||||
pub struct CSetBlockDestroyStage {
|
||||
/// A unique ID for this destruction instance. Usually the miner's Entity ID.
|
||||
@@ -33,3 +33,16 @@ impl CSetBlockDestroyStage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetBlockDestroyStage {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_block_pos(&self.location)?;
|
||||
write.write_i8(self.destroy_stage)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_BLOCK_EVENT;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Triggers a physical block animation or sound effect.
|
||||
///
|
||||
/// This is used for simple block interactions that don't necessarily change
|
||||
/// NBT data, such as chests opening/closing, pistons extending, or note blocks playing.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_BLOCK_EVENT)]
|
||||
pub struct CBlockEvent {
|
||||
/// The coordinates where the event occurs.
|
||||
@@ -40,3 +40,17 @@ impl CBlockEvent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CBlockEvent {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_block_pos(&self.location)?;
|
||||
write.write_u8(self.action_id)?;
|
||||
write.write_u8(self.action_parameter)?;
|
||||
write.write_var_int(&self.block_type)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_CHUNK_CACHE_CENTER;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Updates the center of the player's loaded chunk radius (the "view center").
|
||||
///
|
||||
/// This packet tells the client which chunk coordinate it should use as the
|
||||
/// focal point for loading and unloading chunks. It is typically sent when
|
||||
/// a player moves across a chunk boundary.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_CHUNK_CACHE_CENTER)]
|
||||
pub struct CCenterChunk {
|
||||
/// The X coordinate of the center chunk.
|
||||
@@ -17,3 +17,15 @@ pub struct CCenterChunk {
|
||||
/// The Z coordinate of the center chunk.
|
||||
pub chunk_z: VarInt,
|
||||
}
|
||||
|
||||
impl ClientPacket for CCenterChunk {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.chunk_x)?;
|
||||
write.write_var_int(&self.chunk_z)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_CHANGE_DIFFICULTY;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Notifies the client of a change in the world's difficulty level or lock status.
|
||||
///
|
||||
/// This updates the client's internal state, which affects certain UI elements
|
||||
/// and client-side behavior (though actual game logic like mob damage is
|
||||
/// primarily handled by the server).
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_CHANGE_DIFFICULTY)]
|
||||
pub struct CChangeDifficulty {
|
||||
/// The current difficulty level of the world.
|
||||
@@ -28,3 +29,15 @@ impl CChangeDifficulty {
|
||||
Self { difficulty, locked }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CChangeDifficulty {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_u8(self.difficulty)?;
|
||||
write.write_bool(self.locked)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::codec::var_int::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_CHUNK_BATCH_FINISHED;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::codec::var_int::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Notifies the client that the server has finished sending a batch of chunks.
|
||||
///
|
||||
/// Introduced in modern protocol versions to optimize world loading, this packet
|
||||
/// allows the client to acknowledge the receipt of a group of chunks, helping
|
||||
/// the server regulate the flow of data and prevent network congestion.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_CHUNK_BATCH_FINISHED)]
|
||||
pub struct CChunkBatchEnd {
|
||||
/// The number of chunks sent in the batch that just finished.
|
||||
@@ -24,3 +24,14 @@ impl CChunkBatchEnd {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CChunkBatchEnd {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.batch_size)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
use crate::ClientPacket;
|
||||
use pumpkin_data::packet::clientbound::PLAY_CHUNK_BATCH_START;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
/// Signals the beginning of a new batch of chunk data packets.
|
||||
///
|
||||
/// This packet initiates a synchronized chunk loading sequence. In modern
|
||||
/// protocol versions, the server must wrap chunk data transmissions between
|
||||
/// a `Start` and `End` packet to manage client-side backpressure and
|
||||
/// network throughput.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_CHUNK_BATCH_START)]
|
||||
pub struct CChunkBatchStart;
|
||||
|
||||
impl ClientPacket for CChunkBatchStart {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
_write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::ClientPacket;
|
||||
use pumpkin_data::packet::clientbound::PLAY_CLEAR_DIALOG;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
#[java_packet(PLAY_CLEAR_DIALOG)]
|
||||
pub struct CPlayClearDialog;
|
||||
|
||||
@@ -18,3 +17,13 @@ impl Default for CPlayClearDialog {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CPlayClearDialog {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
_write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_CLEAR_TITLES;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
/// Removes any currently displayed Title or Subtitle from the player's screen.
|
||||
///
|
||||
/// This packet is used to immediately hide titles that are currently in their
|
||||
/// "stay" or "fade-out" phases.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_CLEAR_TITLES)]
|
||||
pub struct CClearTitle {
|
||||
/// If true, the client also resets the title timings (fade-in, stay, fade-out)
|
||||
@@ -23,3 +23,14 @@ impl CClearTitle {
|
||||
Self { reset }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CClearTitle {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_bool(self.reset)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_CONTAINER_CLOSE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Notifies the client that a container (inventory, chest, etc.) has been closed.
|
||||
///
|
||||
/// This is used by the server to force the player's UI to shut, for example,
|
||||
/// if the player moves too far away from a chest or if an NPC's trade window
|
||||
/// is invalidated.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_CONTAINER_CLOSE)]
|
||||
pub struct CCloseContainer {
|
||||
/// The ID of the container window to close.
|
||||
@@ -24,3 +24,14 @@ impl CCloseContainer {
|
||||
Self { sync_id: window_id }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CCloseContainer {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.sync_id)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_PLAYER_COMBAT_KILL;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Notifies the client that a player has died.
|
||||
///
|
||||
/// This packet is responsible for triggering the death screen on the client
|
||||
/// and displaying the death message in the chat for the deceased player.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_PLAYER_COMBAT_KILL)]
|
||||
pub struct CCombatDeath<'a> {
|
||||
/// The Entity ID of the player who died.
|
||||
@@ -24,3 +24,15 @@ impl<'a> CCombatDeath<'a> {
|
||||
Self { player_id, message }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CCombatDeath<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.player_id)?;
|
||||
write.write_slice(&self.message.encode())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_COMMAND_SUGGESTIONS;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sent by the server to provide a list of "tab-completion" suggestions.
|
||||
///
|
||||
/// This packet responds to a client's request for help with commands,
|
||||
/// appearing as a scrollable list of options while the player is typing
|
||||
/// in the chat bar.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_COMMAND_SUGGESTIONS)]
|
||||
pub struct CCommandSuggestions {
|
||||
/// The unique ID of the request this response is for.
|
||||
@@ -44,7 +44,7 @@ impl CCommandSuggestions {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug, Serialize)]
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub struct CommandSuggestion {
|
||||
pub suggestion: String,
|
||||
pub tooltip: Option<TextComponent>,
|
||||
@@ -58,4 +58,32 @@ impl CommandSuggestion {
|
||||
tooltip,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, mut write: impl std::io::Write) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(&self.suggestion)?;
|
||||
if let Some(tooltip) = &self.tooltip {
|
||||
write.write_bool(true)?;
|
||||
write.write_slice(&tooltip.encode())?;
|
||||
} else {
|
||||
write.write_bool(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CCommandSuggestions {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.id)?;
|
||||
write.write_var_int(&self.start)?;
|
||||
write.write_var_int(&self.length)?;
|
||||
write.write_var_int(&VarInt(self.matches.len() as i32))?;
|
||||
for match_ in &self.matches {
|
||||
match_.write(&mut write)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_COOKIE_REQUEST;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::resource_location::ResourceLocation;
|
||||
use serde::Serialize;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sent by the server to request a "cookie" (stored data) from the client.
|
||||
///
|
||||
/// Introduced in modern Minecraft versions, cookies allow servers to store
|
||||
/// small amounts of persistent data on the client side that can be retrieved
|
||||
/// even across different server instances or sub-servers in a network.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_COOKIE_REQUEST)]
|
||||
pub struct CPlayCookieRequest<'a> {
|
||||
/// The unique identifier (namespace:path) of the cookie to retrieve.
|
||||
@@ -21,3 +22,14 @@ impl<'a> CPlayCookieRequest<'a> {
|
||||
Self { key }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CPlayCookieRequest<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.key)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_DAMAGE_EVENT;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Notifies the client that an entity has taken damage.
|
||||
///
|
||||
@@ -11,7 +12,6 @@ use crate::VarInt;
|
||||
/// directional knockback visuals, and sound effects. It provides the client
|
||||
/// with specific details about the damage source to ensure the visual feedback
|
||||
/// matches the cause.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_DAMAGE_EVENT)]
|
||||
pub struct CDamageEvent {
|
||||
/// The Entity ID of the entity taking damage.
|
||||
@@ -48,3 +48,25 @@ impl CDamageEvent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CDamageEvent {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_var_int(&self.source_type_id)?;
|
||||
write.write_var_int(&self.source_cause_id)?;
|
||||
write.write_var_int(&self.source_direct_id)?;
|
||||
if let Some(pos) = &self.source_position {
|
||||
write.write_bool(true)?;
|
||||
write.write_f64(pos.x)?;
|
||||
write.write_f64(pos.y)?;
|
||||
write.write_f64(pos.z)?;
|
||||
} else {
|
||||
write.write_bool(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_DISCONNECT;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Forces the client to disconnect from the server while in the "Play" state.
|
||||
///
|
||||
/// This packet displays the provided reason to the player on a dedicated
|
||||
/// disconnection screen. It is used for kicks, server shutdowns, or when
|
||||
/// a player is banned.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_DISCONNECT)]
|
||||
pub struct CPlayDisconnect<'a> {
|
||||
/// The message shown to the player explaining why they were disconnected.
|
||||
@@ -23,3 +24,14 @@ impl<'a> CPlayDisconnect<'a> {
|
||||
Self { reason }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CPlayDisconnect<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.reason.encode())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_DISGUISED_CHAT;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sends a chat message that is not cryptographically signed by a player.
|
||||
///
|
||||
/// Introduced to support server-side "disguised" identities (like /say or NPC chat),
|
||||
/// this packet bypasses the player-to-player chat signing requirements while
|
||||
/// still allowing the client to format the message using the standard chat registry.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_DISGUISED_CHAT)]
|
||||
pub struct CDisguisedChatMessage<'a> {
|
||||
/// The raw content of the message.
|
||||
@@ -41,3 +41,22 @@ impl<'a> CDisguisedChatMessage<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CDisguisedChatMessage<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.message.encode())?;
|
||||
write.write_var_int(&self.chat_type)?;
|
||||
write.write_slice(&self.sender_name.encode())?;
|
||||
if let Some(target) = self.target_name {
|
||||
write.write_bool(true)?;
|
||||
write.write_slice(&target.encode())?;
|
||||
} else {
|
||||
write.write_bool(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::{
|
||||
packet::clientbound::PLAY_SET_DISPLAY_OBJECTIVE, scoreboard::ScoreboardDisplaySlot,
|
||||
};
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Instructs the client to display a specific scoreboard objective in a given slot.
|
||||
///
|
||||
/// This packet is the final step in showing a scoreboard to a player. After
|
||||
/// an objective is created and populated with scores, this packet "maps"
|
||||
/// that objective to a visual location like the sidebar or the player list.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_DISPLAY_OBJECTIVE)]
|
||||
pub struct CDisplayObjective {
|
||||
/// The display slot/position for the objective.
|
||||
@@ -30,3 +30,15 @@ impl CDisplayObjective {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CDisplayObjective {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.position)?;
|
||||
write.write_string(&self.score_name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_ANIMATE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Triggers a specific animation for an entity that is visible to the client.
|
||||
///
|
||||
/// This is primarily used for player-driven animations like swinging an arm
|
||||
/// or showing damage, but it can apply to other entities as well.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_ANIMATE)]
|
||||
pub struct CEntityAnimation {
|
||||
/// The Entity ID of the entity performing the animation.
|
||||
@@ -28,6 +28,18 @@ impl CEntityAnimation {
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CEntityAnimation {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_u8(self.animation)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Animation {
|
||||
SwingMainArm,
|
||||
|
||||
@@ -7,13 +7,22 @@ use pumpkin_data::{
|
||||
};
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{
|
||||
ClientPacket, VarInt,
|
||||
ser::{NetworkWriteExt, WritingError, serializer},
|
||||
ser::{NetworkWriteExt, WritingError},
|
||||
};
|
||||
|
||||
pub trait MetadataSerializer {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError>;
|
||||
}
|
||||
|
||||
impl<T: MetadataSerializer + ?Sized> MetadataSerializer for &T {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
(*self).write_metadata(writer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the "Data Tracker" values for an entity.
|
||||
///
|
||||
/// Entity Metadata (or `DataWatchers`) controls persistent visual states that
|
||||
@@ -41,17 +50,13 @@ impl CSetEntityMetadata {
|
||||
impl ClientPacket for CSetEntityMetadata {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
write: impl Write,
|
||||
mut write: impl Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), WritingError> {
|
||||
let mut write = write;
|
||||
|
||||
// 1. Entity ID
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
|
||||
write
|
||||
.write_all(&self.metadata)
|
||||
.map_err(WritingError::IoError)
|
||||
write.write_slice(&self.metadata)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,10 +78,10 @@ impl<T> Metadata<T> {
|
||||
pub fn write<W: std::io::Write>(
|
||||
&self,
|
||||
mut writer: W,
|
||||
version: &pumpkin_util::version::JavaMinecraftVersion,
|
||||
version: &JavaMinecraftVersion,
|
||||
) -> Result<(), WritingError>
|
||||
where
|
||||
T: Serialize,
|
||||
T: MetadataSerializer,
|
||||
{
|
||||
let resolved_index = self.index.get(version);
|
||||
|
||||
@@ -95,12 +100,7 @@ impl<T> Metadata<T> {
|
||||
|
||||
if self.r#type == MetaDataType::BLOCK_STATE {
|
||||
let mut serialized_value = Vec::new();
|
||||
{
|
||||
let mut serializer = serializer::Serializer::new(&mut serialized_value);
|
||||
self.value
|
||||
.serialize(&mut serializer)
|
||||
.map_err(|e| WritingError::Serde(e.to_string()))?;
|
||||
};
|
||||
self.value.write_metadata(&mut serialized_value)?;
|
||||
|
||||
let mut cursor = Cursor::new(serialized_value);
|
||||
let decoded_state = VarInt::decode(&mut cursor).map_err(|e| {
|
||||
@@ -115,12 +115,7 @@ impl<T> Metadata<T> {
|
||||
|
||||
if self.r#type == MetaDataType::ITEM_STACK {
|
||||
let mut serialized_value = Vec::new();
|
||||
{
|
||||
let mut serializer = serializer::Serializer::new(&mut serialized_value);
|
||||
self.value
|
||||
.serialize(&mut serializer)
|
||||
.map_err(|e| WritingError::Serde(e.to_string()))?;
|
||||
};
|
||||
self.value.write_metadata(&mut serialized_value)?;
|
||||
|
||||
let mut cursor = Cursor::new(serialized_value);
|
||||
let item_count = VarInt::decode(&mut cursor).map_err(|e| {
|
||||
@@ -138,18 +133,134 @@ impl<T> Metadata<T> {
|
||||
writer.write_var_int(&VarInt(i32::from(remapped_id)))?;
|
||||
let remainder_start = cursor.position() as usize;
|
||||
let inner = cursor.into_inner();
|
||||
writer.write_all(&inner[remainder_start..]).map_err(|e| {
|
||||
WritingError::Message(format!("Failed to write item stack remainder: {e}"))
|
||||
})?;
|
||||
writer.write_slice(&inner[remainder_start..])?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut serializer = serializer::Serializer::new(&mut writer);
|
||||
self.value
|
||||
.serialize(&mut serializer)
|
||||
.map_err(|e| WritingError::Serde(e.to_string()))?;
|
||||
self.value.write_metadata(&mut writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for bool {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_bool(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for i8 {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_i8(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for u8 {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_u8(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for i16 {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_i16(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for u16 {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_u16(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for i32 {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_i32(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for u32 {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_u32(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for f32 {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_f32(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for VarInt {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_var_int(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for String {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_string(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for pumpkin_util::text::TextComponent {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_slice(&self.encode())
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for Option<pumpkin_util::text::TextComponent> {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
if let Some(text) = self {
|
||||
writer.write_bool(true)?;
|
||||
writer.write_slice(&text.encode())?;
|
||||
} else {
|
||||
writer.write_bool(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for crate::codec::item_stack_seralizer::ItemStackSerializer<'_> {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
self.write(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for Option<String> {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
if let Some(s) = self {
|
||||
writer.write_bool(true)?;
|
||||
writer.write_string(s)?;
|
||||
} else {
|
||||
writer.write_bool(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for pumpkin_util::math::position::BlockPos {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
writer.write_block_pos(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for Option<pumpkin_util::math::position::BlockPos> {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
if let Some(pos) = self {
|
||||
writer.write_bool(true)?;
|
||||
writer.write_block_pos(pos)?;
|
||||
} else {
|
||||
writer.write_bool(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataSerializer for crate::codec::optional_int::OptionalInt {
|
||||
fn write_metadata(&self, writer: &mut impl std::io::Write) -> Result<(), WritingError> {
|
||||
let val = self.0.map_or(0, |id| id + 1);
|
||||
writer.write_var_int(&VarInt(val))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_ENTITY_POSITION_SYNC;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::VarInt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Updates the exact position, rotation, and velocity of an entity.
|
||||
///
|
||||
@@ -14,7 +15,6 @@ use crate::VarInt;
|
||||
/// Note: This packet must NOT be used for the player receiving the packet or
|
||||
/// any entity the player is currently riding.
|
||||
#[java_packet(PLAY_ENTITY_POSITION_SYNC)]
|
||||
#[derive(Serialize)]
|
||||
pub struct CEntityPositionSync {
|
||||
/// The Entity ID of the entity being moved.
|
||||
pub entity_id: VarInt,
|
||||
@@ -51,3 +51,23 @@ impl CEntityPositionSync {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CEntityPositionSync {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_f64(self.position.x)?;
|
||||
write.write_f64(self.position.y)?;
|
||||
write.write_f64(self.position.z)?;
|
||||
write.write_f64(self.delta.x)?;
|
||||
write.write_f64(self.delta.y)?;
|
||||
write.write_f64(self.delta.z)?;
|
||||
write.write_f32(self.yaw)?;
|
||||
write.write_f32(self.pitch)?;
|
||||
write.write_bool(self.on_ground)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,12 +65,15 @@ impl ClientPacket for CEntitySoundEffect {
|
||||
IdOr::Value(value) => IdOr::Value(value.clone()),
|
||||
};
|
||||
|
||||
write.write_serialize(&sound_event)?;
|
||||
write.write_serialize(&self.sound_category)?;
|
||||
write.write_serialize(&self.entity_id)?;
|
||||
write.write_serialize(&self.volume)?;
|
||||
write.write_serialize(&self.pitch)?;
|
||||
write.write_serialize(&self.seed)
|
||||
crate::IdOr::<crate::SoundEvent>::write(&sound_event, &mut write, |w, e| {
|
||||
w.write_string(&e.sound_name)?;
|
||||
w.write_option(&e.range, |w2, r| w2.write_f32(*r))
|
||||
})?;
|
||||
write.write_var_int(&self.sound_category)?;
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_f32(self.volume)?;
|
||||
write.write_f32(self.pitch)?;
|
||||
write.write_i64(self.seed)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_ENTITY_EVENT;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sends a status update for a specific entity.
|
||||
///
|
||||
@@ -8,7 +11,6 @@ use serde::{Deserialize, Serialize};
|
||||
/// warrant a complex packet of their own. It primarily handles visual
|
||||
/// and logical state triggers, such as tool breaking, totem usage,
|
||||
/// or sheep shearing.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(PLAY_ENTITY_EVENT)]
|
||||
pub struct CEntityStatus {
|
||||
/// The Entity ID of the entity affected by the status change.
|
||||
@@ -27,3 +29,15 @@ impl CEntityStatus {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CEntityStatus {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_i32_be(self.entity_id)?;
|
||||
write.write_i8(self.entity_status)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_EXPLODE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use crate::{IdOr, SoundEvent, codec::var_int::VarInt};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Notifies the client that an explosion has occurred.
|
||||
///
|
||||
/// This is a high-level packet that handles the visual, auditory, and physical
|
||||
/// effects of an explosion in a single call. It triggers the explosion particles,
|
||||
/// plays the sound at the source, and applies knockback to the player.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_EXPLODE)]
|
||||
pub struct CExplosion {
|
||||
/// The center coordinates of the explosion.
|
||||
@@ -54,3 +55,34 @@ impl CExplosion {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CExplosion {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_f64_be(self.center.x)?;
|
||||
write.write_f64_be(self.center.y)?;
|
||||
write.write_f64_be(self.center.z)?;
|
||||
write.write_f32_be(self.radius)?;
|
||||
write.write_i32_be(self.block_count)?;
|
||||
write.write_option(&self.knockback, |w, k| {
|
||||
w.write_f64_be(k.x)?;
|
||||
w.write_f64_be(k.y)?;
|
||||
w.write_f64_be(k.z)?;
|
||||
Ok(())
|
||||
})?;
|
||||
write.write_var_int(&self.particle)?;
|
||||
match &self.sound {
|
||||
IdOr::Id(id) => write.write_var_int(&VarInt((*id + 1) as i32))?,
|
||||
IdOr::Value(event) => {
|
||||
write.write_var_int(&VarInt(0))?;
|
||||
write.write_string(&event.sound_name)?;
|
||||
write.write_option(&event.range, |w, r| w.write_f32_be(*r))?;
|
||||
}
|
||||
}
|
||||
write.write_var_int(&self.block_particles_pool_size)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_GAME_EVENT;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Updates the game state or triggers specific environmental changes.
|
||||
///
|
||||
/// This packet is the primary way the server communicates global or
|
||||
/// context-specific transitions, such as changing the weather,
|
||||
/// altering the player's gamemode, or displaying the credits.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(PLAY_GAME_EVENT)]
|
||||
pub struct CGameEvent {
|
||||
/// The ID of the event type.
|
||||
@@ -43,3 +45,15 @@ pub enum GameEvent {
|
||||
LimitedCrafting,
|
||||
StartWaitingChunks,
|
||||
}
|
||||
|
||||
impl ClientPacket for CGameEvent {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_u8(self.event)?;
|
||||
write.write_f32_be(self.value)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_ROTATE_HEAD;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Rotates an entity's head to a specific yaw.
|
||||
///
|
||||
@@ -10,7 +12,6 @@ use crate::VarInt;
|
||||
/// While standard movement packets update the body, this packet is
|
||||
/// required to make an entity (like a player or a mob) look in a
|
||||
/// specific direction without necessarily turning its entire body.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(PLAY_ROTATE_HEAD)]
|
||||
pub struct CHeadRot {
|
||||
/// The Entity ID of the entity whose head is rotating.
|
||||
@@ -28,3 +29,15 @@ impl CHeadRot {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CHeadRot {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_u8(self.head_yaw)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_HURT_ANIMATION;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Triggers the "hurt" visual effect on an entity.
|
||||
///
|
||||
/// This packet causes the entity to turn red and perform a directional
|
||||
/// camera shake or model tilt. It is typically sent immediately after
|
||||
/// an entity's health is reduced.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(PLAY_HURT_ANIMATION)]
|
||||
pub struct CHurtAnimation {
|
||||
/// The Entity ID of the entity that was hurt.
|
||||
@@ -25,3 +26,15 @@ impl CHurtAnimation {
|
||||
Self { entity_id, yaw }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CHurtAnimation {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_f32_be(self.yaw)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_INITIALIZE_BORDER;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use crate::{VarInt, codec::var_long::VarLong};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Fully initializes the world border for the client.
|
||||
///
|
||||
/// This packet is sent when a player joins the world or changes dimensions.
|
||||
/// It synchronizes the current position, size, and all warning parameters
|
||||
/// to ensure the client-side visual barrier matches the server's authority.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_INITIALIZE_BORDER)]
|
||||
pub struct CInitializeWorldBorder {
|
||||
/// The X coordinate of the center of the world border.
|
||||
@@ -57,3 +58,21 @@ impl CInitializeWorldBorder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CInitializeWorldBorder {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_f64_be(self.x)?;
|
||||
write.write_f64_be(self.z)?;
|
||||
write.write_f64_be(self.old_diameter)?;
|
||||
write.write_f64_be(self.new_diameter)?;
|
||||
write.write_var_long(&self.speed)?;
|
||||
write.write_var_int(&self.portal_teleport_boundary)?;
|
||||
write.write_var_int(&self.warning_blocks)?;
|
||||
write.write_var_int(&self.warning_time)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ use pumpkin_data::packet::clientbound::PLAY_COOLDOWN;
|
||||
|
||||
use crate::codec::var_int::VarInt;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_COOLDOWN)]
|
||||
pub struct CItemCooldown {
|
||||
pub group: String,
|
||||
@@ -17,3 +19,15 @@ impl CItemCooldown {
|
||||
Self { group, cooldown }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CItemCooldown {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(&self.group)?;
|
||||
write.write_var_int(&self.cooldown)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_KEEP_ALIVE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Maintains the connection and measures latency (ping) between client and server.
|
||||
///
|
||||
@@ -8,7 +11,6 @@ use serde::{Deserialize, Serialize};
|
||||
/// The client must respond with the exact same ID. If the server does not receive
|
||||
/// a response within a timeout period (usually 30 seconds), it will disconnect
|
||||
/// the player with a "Timed Out" message.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(PLAY_KEEP_ALIVE)]
|
||||
pub struct CKeepAlive {
|
||||
/// A unique random identifier for this specific keep-alive request.
|
||||
@@ -22,3 +24,14 @@ impl CKeepAlive {
|
||||
Self { keep_alive_id }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CKeepAlive {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_i64_be(self.keep_alive_id)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_MERCHANT_OFFERS;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::codec::item_stack_seralizer::ItemStackSerializer;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct MerchantOffer {
|
||||
pub base_cost_a: ItemStackSerializer<'static>, // TODO: item cost
|
||||
pub output: ItemStackSerializer<'static>,
|
||||
@@ -19,7 +21,28 @@ pub struct MerchantOffer {
|
||||
pub demand: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
impl MerchantOffer {
|
||||
fn write(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
version: JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
self.base_cost_a.write_with_version(&mut write, &version)?;
|
||||
self.output.write_with_version(&mut write, &version)?;
|
||||
write.write_option(&self.cost_b, |w, cost_b| {
|
||||
cost_b.write_with_version(w, &version)
|
||||
})?;
|
||||
write.write_bool(self.is_disabled)?;
|
||||
write.write_i32_be(self.uses)?;
|
||||
write.write_i32_be(self.max_uses)?;
|
||||
write.write_i32_be(self.xp)?;
|
||||
write.write_i32_be(self.special_price)?;
|
||||
write.write_f32_be(self.price_multiplier)?;
|
||||
write.write_i32_be(self.demand)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[java_packet(PLAY_MERCHANT_OFFERS)]
|
||||
pub struct CMerchantOffers {
|
||||
pub window_id: VarInt,
|
||||
@@ -50,3 +73,22 @@ impl CMerchantOffers {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CMerchantOffers {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.window_id)?;
|
||||
write.write_var_int(&VarInt(self.offers.len() as i32))?;
|
||||
for offer in &self.offers {
|
||||
offer.write(&mut write, *version)?;
|
||||
}
|
||||
write.write_var_int(&self.villager_level)?;
|
||||
write.write_var_int(&self.experience)?;
|
||||
write.write_bool(self.is_regular_villager)?;
|
||||
write.write_bool(self.can_restock)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ use pumpkin_data::packet::clientbound::PLAY_OPEN_SCREEN;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Instructs the client to open a specific type of GUI (inventory, chest, etc.).
|
||||
///
|
||||
@@ -12,7 +14,6 @@ use crate::VarInt;
|
||||
/// or when a command/plugin forces an interface to open. It establishes a
|
||||
/// `sync_id` which must be used in all subsequent "Set Slot" or "Click Slot"
|
||||
/// packets to ensure the server and client are talking about the same window.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_OPEN_SCREEN)]
|
||||
pub struct COpenScreen<'a> {
|
||||
/// A unique identifier for the current window session.
|
||||
@@ -40,3 +41,18 @@ impl<'a> COpenScreen<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for COpenScreen<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.sync_id)?;
|
||||
write.write_var_int(&self.window_type)?;
|
||||
// Write the text component as JSON string
|
||||
let buf = self.window_title.encode();
|
||||
write.write_slice(&buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_OPEN_SIGN_EDITOR;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Opens the sign text input screen for the client.
|
||||
///
|
||||
/// This packet is sent by the server to force the client to show the
|
||||
/// sign editing interface. This usually happens immediately after a
|
||||
/// player places a sign or interacts with an existing one (if allowed).
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_OPEN_SIGN_EDITOR)]
|
||||
pub struct COpenSignEditor {
|
||||
/// The world coordinates of the sign block to be edited.
|
||||
@@ -27,3 +29,15 @@ impl COpenSignEditor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for COpenSignEditor {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_block_pos(&self.location)?;
|
||||
write.write_bool(self.is_front_text)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_PONG_RESPONSE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Responds to a client-initiated ping request to synchronize game state.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(PLAY_PONG_RESPONSE)]
|
||||
pub struct CPingResponse {
|
||||
/// The unique identifier sent by the client in the initial Ping packet.
|
||||
@@ -17,3 +19,14 @@ impl CPingResponse {
|
||||
Self { payload }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CPingResponse {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_i64_be(self.payload)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_PLAYER_ABILITIES;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Updates the player's movement and interaction abilities.
|
||||
///
|
||||
/// This packet informs the client about the player's state (flying, invulnerable)
|
||||
/// and sets the movement speeds. While the client applies these visuals,
|
||||
/// the server must still validate these states to prevent cheating.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_PLAYER_ABILITIES)]
|
||||
pub struct CPlayerAbilities {
|
||||
/// A bitmask of player states.
|
||||
@@ -34,3 +36,16 @@ impl CPlayerAbilities {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CPlayerAbilities {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_i8(self.flags)?;
|
||||
write.write_f32_be(self.flying_speed)?;
|
||||
write.write_f32_be(self.field_of_view)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,9 @@ impl ClientPacket for CPlayerInfoUpdate<'_> {
|
||||
PlayerAction::UpdateListed(listed) => p.write_bool(*listed)?,
|
||||
PlayerAction::UpdateLatency(latency) => p.write_var_int(latency)?,
|
||||
PlayerAction::UpdateDisplayName(display_name) => {
|
||||
p.write_option(display_name, crate::ser::NetworkWriteExt::write_serialize)?;
|
||||
p.write_option(display_name, |w, text_component| {
|
||||
w.write_slice(&text_component.encode())
|
||||
})?;
|
||||
}
|
||||
PlayerAction::UpdateListOrder(order) => p.write_var_int(order)?,
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_PLAYER_INFO_REMOVE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Serialize, ser::SerializeSeq};
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sent by the server to remove one or more players from the client's player list (tab list).
|
||||
///
|
||||
/// This packet is typically used when a player leaves the server or becomes invisible
|
||||
/// to the recipient (e.g., moving out of tracking range).
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_PLAYER_INFO_REMOVE)]
|
||||
pub struct CRemovePlayerInfo<'a> {
|
||||
/// A list of UUIDs corresponding to the players that should be removed.
|
||||
///
|
||||
/// The field uses a custom serializer to format the UUIDs according to the
|
||||
/// Minecraft protocol's VarInt-prefixed array format.
|
||||
#[serde(serialize_with = "serialize_slice_uuids")]
|
||||
pub players: &'a [uuid::Uuid],
|
||||
}
|
||||
|
||||
@@ -24,13 +23,16 @@ impl<'a> CRemovePlayerInfo<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_slice_uuids<S: serde::Serializer>(
|
||||
uuids: &[uuid::Uuid],
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
let mut seq = serializer.serialize_seq(Some(uuids.len()))?;
|
||||
for uuid in uuids {
|
||||
seq.serialize_element(uuid.as_bytes())?;
|
||||
impl ClientPacket for CRemovePlayerInfo<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&VarInt(self.players.len() as i32))?;
|
||||
for uuid in self.players {
|
||||
write.write_uuid(uuid)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_REMOVE_ENTITIES;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Sent by the server to instruct the client to remove (despawn) one or more entities.
|
||||
///
|
||||
/// This is typically sent when an entity leaves the player's tracking range,
|
||||
/// is killed, or is otherwise removed from the world.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_REMOVE_ENTITIES)]
|
||||
pub struct CRemoveEntities<'a> {
|
||||
/// A list of entity IDs to be removed.
|
||||
@@ -21,3 +22,17 @@ impl<'a> CRemoveEntities<'a> {
|
||||
Self { entity_ids }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CRemoveEntities<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&VarInt(self.entity_ids.len() as i32))?;
|
||||
for id in self.entity_ids {
|
||||
write.write_var_int(id)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use crate::codec::var_int::VarInt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_REMOVE_MOB_EFFECT;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_REMOVE_MOB_EFFECT)]
|
||||
pub struct CRemoveMobEffect {
|
||||
pub entity_id: VarInt,
|
||||
@@ -19,3 +21,15 @@ impl CRemoveMobEffect {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CRemoveMobEffect {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_var_int(&self.effect_id)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_RESET_SCORE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_RESET_SCORE)]
|
||||
pub struct CResetScore {
|
||||
pub entity_name: String,
|
||||
@@ -18,3 +20,15 @@ impl CResetScore {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CResetScore {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(&self.entity_name)?;
|
||||
write.write_option(&self.objective_name, |w, obj| w.write_string(obj))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SELECT_ADVANCEMENTS_TAB;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::identifier::Identifier;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_SELECT_ADVANCEMENTS_TAB)]
|
||||
pub struct CSelectAdvancementsTab {
|
||||
pub tab_id: Option<Identifier>,
|
||||
@@ -15,3 +17,14 @@ impl CSelectAdvancementsTab {
|
||||
Self { tab_id }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSelectAdvancementsTab {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_option(&self.tab_id, |w, id| w.write_string(&id.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use crate::Link;
|
||||
use pumpkin_data::packet::clientbound::PLAY_SERVER_LINKS;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SERVER_LINKS)]
|
||||
pub struct CPlayServerLinks<'a> {
|
||||
pub links: &'a [Link<'a>],
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_BORDER_CENTER;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_SET_BORDER_CENTER)]
|
||||
pub struct CSetBorderCenter {
|
||||
pub x: f64,
|
||||
@@ -15,3 +17,15 @@ impl CSetBorderCenter {
|
||||
Self { x, z }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetBorderCenter {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_f64_be(self.x)?;
|
||||
write.write_f64_be(self.z)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_BORDER_LERP_SIZE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::codec::var_long::VarLong;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_BORDER_LERP_SIZE)]
|
||||
pub struct CSetBorderLerpSize {
|
||||
pub old_diameter: f64,
|
||||
@@ -22,3 +23,16 @@ impl CSetBorderLerpSize {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetBorderLerpSize {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_f64_be(self.old_diameter)?;
|
||||
write.write_f64_be(self.new_diameter)?;
|
||||
write.write_var_long(&self.speed)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_BORDER_SIZE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_SET_BORDER_SIZE)]
|
||||
pub struct CSetBorderSize {
|
||||
pub diameter: f64,
|
||||
@@ -14,3 +16,14 @@ impl CSetBorderSize {
|
||||
Self { diameter }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetBorderSize {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_f64_be(self.diameter)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_BORDER_WARNING_DELAY;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_BORDER_WARNING_DELAY)]
|
||||
pub struct CSetBorderWarningDelay {
|
||||
pub warning_time: VarInt,
|
||||
@@ -16,3 +17,14 @@ impl CSetBorderWarningDelay {
|
||||
Self { warning_time }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetBorderWarningDelay {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.warning_time)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_BORDER_WARNING_DISTANCE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_BORDER_WARNING_DISTANCE)]
|
||||
pub struct CSetBorderWarningDistance {
|
||||
pub warning_blocks: VarInt,
|
||||
@@ -16,3 +17,14 @@ impl CSetBorderWarningDistance {
|
||||
Self { warning_blocks }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetBorderWarningDistance {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.warning_blocks)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_CAMERA;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use crate::{VarInt, packet::MultiVersionJavaPacket};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CSetCamera {
|
||||
pub camera_id: VarInt,
|
||||
}
|
||||
@@ -16,6 +16,17 @@ impl CSetCamera {
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetCamera {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.camera_id)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiVersionJavaPacket for CSetCamera {
|
||||
fn to_id(version: JavaMinecraftVersion) -> i32 {
|
||||
PLAY_SET_CAMERA.to_id(version)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_CONTAINER_SET_DATA;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_CONTAINER_SET_DATA)]
|
||||
pub struct CSetContainerProperty {
|
||||
pub window_id: VarInt,
|
||||
@@ -22,3 +23,16 @@ impl CSetContainerProperty {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetContainerProperty {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.window_id)?;
|
||||
write.write_i16(self.property)?;
|
||||
write.write_i16(self.value)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ impl<'a> CSetCursorItem<'a> {
|
||||
impl ClientPacket for CSetCursorItem<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
write: impl Write,
|
||||
mut write: impl Write,
|
||||
version: &JavaMinecraftVersion,
|
||||
) -> Result<(), WritingError> {
|
||||
self.stack.write_with_version(write, version)
|
||||
self.stack.write_with_version(&mut write, version)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_EXPERIENCE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_EXPERIENCE)]
|
||||
pub struct CSetExperience {
|
||||
pub progress: f32,
|
||||
@@ -22,3 +23,16 @@ impl CSetExperience {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetExperience {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_f32(self.progress)?;
|
||||
write.write_var_int(&self.level)?;
|
||||
write.write_var_int(&self.total_experience)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_HEALTH;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_HEALTH)]
|
||||
pub struct CSetHealth {
|
||||
pub health: f32,
|
||||
@@ -22,3 +23,16 @@ impl CSetHealth {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetHealth {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_f32(self.health)?;
|
||||
write.write_var_int(&self.food)?;
|
||||
write.write_f32(self.food_saturation)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::{PLAY_SET_CARRIED_ITEM, PLAY_SET_HELD_SLOT};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::packet::MultiVersionJavaPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CSetSelectedSlot {
|
||||
pub slot: i8,
|
||||
}
|
||||
@@ -16,6 +16,17 @@ impl CSetSelectedSlot {
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetSelectedSlot {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_i8(self.slot)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiVersionJavaPacket for CSetSelectedSlot {
|
||||
fn to_id(version: JavaMinecraftVersion) -> i32 {
|
||||
if version >= JavaMinecraftVersion::V_1_21_2 {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_PASSENGERS;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_PASSENGERS)]
|
||||
pub struct CSetPassengers<'a> {
|
||||
pub entity_id: VarInt,
|
||||
@@ -20,3 +21,18 @@ impl<'a> CSetPassengers<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSetPassengers<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_var_int(&crate::VarInt(self.passengers.len() as i32))?;
|
||||
for passenger in self.passengers {
|
||||
write.write_var_int(passenger)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,6 @@ impl ClientPacket for CSetPlayerInventory<'_> {
|
||||
) -> Result<(), WritingError> {
|
||||
let mut write = write;
|
||||
write.write_var_int(&self.slot)?;
|
||||
self.item.write_with_version(write, version)
|
||||
self.item.write_with_version(&mut write, version)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_TITLE_TEXT;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_TITLE_TEXT)]
|
||||
pub struct CTitleText<'a> {
|
||||
pub title: &'a TextComponent,
|
||||
@@ -16,3 +17,14 @@ impl<'a> CTitleText<'a> {
|
||||
Self { title }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CTitleText<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.title.encode())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_SET_TITLES_ANIMATION;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SET_TITLES_ANIMATION)]
|
||||
pub struct CTitleAnimation {
|
||||
pub fade_in_ticks: i32,
|
||||
@@ -21,3 +22,16 @@ impl CTitleAnimation {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CTitleAnimation {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_i32_be(self.fade_in_ticks)?;
|
||||
write.write_i32_be(self.stay_ticks)?;
|
||||
write.write_i32_be(self.fade_out_ticks)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use crate::IdOr;
|
||||
use crate::java::client::dialog::DialogNBT;
|
||||
use crate::{ClientPacket, IdOr, ser::WritingError};
|
||||
use pumpkin_data::packet::clientbound::PLAY_SHOW_DIALOG;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_SHOW_DIALOG)]
|
||||
pub struct CPlayShowDialog<'a> {
|
||||
pub dialog: IdOr<DialogNBT<'a>>,
|
||||
@@ -16,3 +15,14 @@ impl<'a> CPlayShowDialog<'a> {
|
||||
Self { dialog }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CPlayShowDialog<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
version: &JavaMinecraftVersion,
|
||||
) -> Result<(), WritingError> {
|
||||
self.dialog
|
||||
.write(&mut write, |w, value| value.write_packet_data(w, version))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,17 @@ impl ClientPacket for CSoundEffect {
|
||||
IdOr::Value(value) => IdOr::Value(value.clone()),
|
||||
};
|
||||
|
||||
write.write_serialize(&sound_event)?;
|
||||
write.write_serialize(&self.sound_category)?;
|
||||
write.write_serialize(&self.position)?;
|
||||
write.write_serialize(&self.volume)?;
|
||||
write.write_serialize(&self.pitch)?;
|
||||
write.write_serialize(&self.seed)
|
||||
crate::IdOr::<crate::SoundEvent>::write(&sound_event, &mut write, |w, e| {
|
||||
w.write_string(&e.sound_name)?;
|
||||
w.write_option(&e.range, |w2, r| w2.write_f32_be(*r))
|
||||
})?;
|
||||
write.write_var_int(&self.sound_category)?;
|
||||
write.write_i32_be(self.position.x * 8)?;
|
||||
write.write_i32_be(self.position.y * 8)?;
|
||||
write.write_i32_be(self.position.z * 8)?;
|
||||
write.write_f32_be(self.volume)?;
|
||||
write.write_f32_be(self.pitch)?;
|
||||
write.write_i64_be(self.seed as i64)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_STORE_COOKIE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::resource_location::ResourceLocation;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Stores some arbitrary data on the client, which persists between server transfers.
|
||||
/// The Notchian client only accepts cookies of up to 5 kiB in size.
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_STORE_COOKIE)]
|
||||
pub struct CStoreCookie<'a> {
|
||||
pub key: &'a ResourceLocation,
|
||||
@@ -18,3 +20,18 @@ impl<'a> CStoreCookie<'a> {
|
||||
Self { key, payload }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CStoreCookie<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.key)?;
|
||||
write.write_var_int(&crate::VarInt(self.payload.len() as i32))?;
|
||||
write
|
||||
.write_all(self.payload)
|
||||
.map_err(|_| crate::ser::WritingError::Message("IO Error".into()))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ use pumpkin_data::packet::clientbound::PLAY_SET_SUBTITLE_TEXT;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_SET_SUBTITLE_TEXT)]
|
||||
pub struct CSubtitle<'a> {
|
||||
pub subtitle: &'a TextComponent,
|
||||
@@ -16,3 +18,14 @@ impl<'a> CSubtitle<'a> {
|
||||
Self { subtitle }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSubtitle<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.subtitle.encode())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ use pumpkin_data::packet::clientbound::PLAY_SYSTEM_CHAT;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_SYSTEM_CHAT)]
|
||||
pub struct CSystemChatMessage<'a> {
|
||||
pub content: &'a TextComponent,
|
||||
@@ -17,3 +19,15 @@ impl<'a> CSystemChatMessage<'a> {
|
||||
Self { content, overlay }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CSystemChatMessage<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.content.encode())?;
|
||||
write.write_bool(self.overlay)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_TAB_LIST;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
/// Updates the header and footer of the player list (Tab List).
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_TAB_LIST)]
|
||||
pub struct CTabList<'a> {
|
||||
/// The text to be displayed at the top of the player list.
|
||||
@@ -19,3 +21,15 @@ impl<'a> CTabList<'a> {
|
||||
Self { header, footer }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CTabList<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_slice(&self.header.encode())?;
|
||||
write.write_slice(&self.footer.encode())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use crate::VarInt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_TAKE_ITEM_ENTITY;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_TAKE_ITEM_ENTITY)]
|
||||
pub struct CTakeItemEntity {
|
||||
/// The entity id of the item entity.
|
||||
@@ -24,3 +26,16 @@ impl CTakeItemEntity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CTakeItemEntity {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.entity_id)?;
|
||||
write.write_var_int(&self.collector_entity_id)?;
|
||||
write.write_var_int(&self.stack_amount)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_TICKING_STATE;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_TICKING_STATE)]
|
||||
pub struct CTickingState {
|
||||
pub tick_rate: f32,
|
||||
@@ -18,3 +20,15 @@ impl CTickingState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CTickingState {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_f32_be(self.tick_rate)?;
|
||||
write.write_bool(self.is_frozen)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_TICKING_STEP;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_TICKING_STEP)]
|
||||
pub struct CTickingStep {
|
||||
pub tick_steps: VarInt,
|
||||
@@ -16,3 +17,14 @@ impl CTickingStep {
|
||||
Self { tick_steps }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CTickingStep {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_var_int(&self.tick_steps)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::ClientPacket;
|
||||
use crate::VarInt;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_data::packet::clientbound::PLAY_TRANSFER;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[java_packet(PLAY_TRANSFER)]
|
||||
pub struct CTransfer<'a> {
|
||||
pub host: &'a str,
|
||||
@@ -16,3 +17,15 @@ impl<'a> CTransfer<'a> {
|
||||
Self { host, port }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CTransfer<'_> {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_string(self.host)?;
|
||||
write.write_var_int(&self.port)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_FORGET_LEVEL_CHUNK;
|
||||
use pumpkin_macros::java_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
#[java_packet(PLAY_FORGET_LEVEL_CHUNK)]
|
||||
pub struct CUnloadChunk {
|
||||
pub z: i32,
|
||||
@@ -15,3 +17,15 @@ impl CUnloadChunk {
|
||||
Self { z, x }
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CUnloadChunk {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_i32_be(self.z)?;
|
||||
write.write_i32_be(self.x)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +1,18 @@
|
||||
use crate::codec::item_stack_seralizer::ItemStackTemplateSerializer;
|
||||
use crate::codec::var_int::VarInt;
|
||||
use pumpkin_data::Advancement;
|
||||
use pumpkin_data::advancement_data::{AdvancementDisplay, AdvancementProgressData};
|
||||
use pumpkin_data::advancement_data::AdvancementProgressData;
|
||||
use pumpkin_data::packet::clientbound::PLAY_UPDATE_ADVANCEMENTS;
|
||||
use pumpkin_macros::java_packet;
|
||||
use pumpkin_util::identifier::Identifier;
|
||||
use serde::ser::SerializeStruct;
|
||||
use serde::{Serialize, Serializer, ser::SerializeSeq};
|
||||
|
||||
fn serialize_advancements<S: Serializer>(
|
||||
advancements: &[&'static Advancement],
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
let mut seq = serializer.serialize_seq(Some(advancements.len()))?;
|
||||
for adv in advancements {
|
||||
seq.serialize_element(&AdvancementSer(adv))?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
use crate::ClientPacket;
|
||||
use crate::ser::NetworkWriteExt;
|
||||
use pumpkin_util::version::JavaMinecraftVersion;
|
||||
|
||||
pub struct AdvancementSer<'a>(pub &'a Advancement);
|
||||
|
||||
impl Serialize for AdvancementSer<'_> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let adv = self.0;
|
||||
let mut state = serializer.serialize_struct("Advancement", 5)?;
|
||||
state.serialize_field("id", &adv.id.to_string())?;
|
||||
state.serialize_field("parent", &adv.parent.clone().map(|p| p.to_string()))?;
|
||||
if let Some(display) = adv.display {
|
||||
state.serialize_field("display", &Some(DisplaySerializer(display)))?;
|
||||
} else {
|
||||
state.serialize_field("display", &None::<&DisplaySerializer>)?;
|
||||
}
|
||||
state.serialize_field("requirements", adv.requirements)?;
|
||||
state.serialize_field("send_telemetry", &adv.send_telemetry)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DisplaySerializer<'a>(pub &'a AdvancementDisplay);
|
||||
|
||||
impl Serialize for DisplaySerializer<'_> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let display = self.0;
|
||||
let mut state = serializer.serialize_struct("AdvancementDisplay", 8)?;
|
||||
|
||||
state.serialize_field("title", &display.get_title())?;
|
||||
state.serialize_field("description", &display.get_description())?;
|
||||
state.serialize_field(
|
||||
"icon",
|
||||
&ItemStackTemplateSerializer::from(display.item_icon.clone()),
|
||||
)?;
|
||||
state.serialize_field("frame_type", &VarInt(display.frame_type as i32))?;
|
||||
let flags = (display.has_background() as i32)
|
||||
| ((display.show_toast as i32) << 1)
|
||||
| ((display.hidden as i32) << 2);
|
||||
state.serialize_field("flags", &flags)?;
|
||||
if let Some(bg) = display.background_texture {
|
||||
state.serialize_field("background_texture", bg)?;
|
||||
}
|
||||
state.serialize_field("x", &display.x)?;
|
||||
state.serialize_field("y", &display.y)?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[java_packet(PLAY_UPDATE_ADVANCEMENTS)]
|
||||
#[allow(unused)]
|
||||
pub struct CUpdateAdvancements {
|
||||
pub reset: bool,
|
||||
#[serde(serialize_with = "serialize_advancements")]
|
||||
pub added: Vec<&'static Advancement>,
|
||||
pub removed: Vec<Identifier>,
|
||||
pub progress: Vec<AdvancementProgressData>,
|
||||
@@ -102,3 +38,82 @@ impl CUpdateAdvancements {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for CUpdateAdvancements {
|
||||
#[allow(clippy::unimplemented)]
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
_version: &JavaMinecraftVersion,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
write.write_bool(self.reset)?;
|
||||
|
||||
write.write_var_int(&VarInt(self.added.len() as i32))?;
|
||||
for adv in &self.added {
|
||||
write.write_string(&adv.id.to_string())?;
|
||||
|
||||
let has_parent = adv.parent.is_some();
|
||||
write.write_bool(has_parent)?;
|
||||
if let Some(ref p) = adv.parent {
|
||||
write.write_string(&p.to_string())?;
|
||||
}
|
||||
|
||||
let has_display = adv.display.is_some();
|
||||
write.write_bool(has_display)?;
|
||||
if let Some(display) = adv.display {
|
||||
write.write_slice(&display.get_title().encode())?;
|
||||
write.write_slice(&display.get_description().encode())?;
|
||||
|
||||
// Item icon
|
||||
// TODO: serialize item_icon (ItemStack)
|
||||
unimplemented!("Item serialization is not yet implemented without serde");
|
||||
|
||||
/*
|
||||
write.write_var_int(&VarInt(display.frame_type as i32))?;
|
||||
let flags = (display.has_background() as i32)
|
||||
| ((display.show_toast as i32) << 1)
|
||||
| ((display.hidden as i32) << 2);
|
||||
write.write_i32_be(flags)?;
|
||||
if let Some(bg) = display.background_texture {
|
||||
write.write_string(bg)?;
|
||||
}
|
||||
write.write_f32_be(display.x)?;
|
||||
write.write_f32_be(display.y)?;
|
||||
*/
|
||||
}
|
||||
|
||||
write.write_var_int(&VarInt(adv.requirements.len() as i32))?;
|
||||
for req in adv.requirements {
|
||||
write.write_var_int(&VarInt(req.len() as i32))?;
|
||||
for r in *req {
|
||||
write.write_string(r)?;
|
||||
}
|
||||
}
|
||||
|
||||
write.write_bool(adv.send_telemetry)?;
|
||||
}
|
||||
|
||||
write.write_var_int(&VarInt(self.removed.len() as i32))?;
|
||||
for rem in &self.removed {
|
||||
write.write_string(&rem.to_string())?;
|
||||
}
|
||||
|
||||
write.write_var_int(&VarInt(self.progress.len() as i32))?;
|
||||
for prog in &self.progress {
|
||||
write.write_string(&prog.id.to_string())?;
|
||||
write.write_var_int(&VarInt(prog.progress.len() as i32))?;
|
||||
for crit in &prog.progress {
|
||||
write.write_string(&crit.criterion_id)?;
|
||||
let has_date = crit.achieve_date.is_some();
|
||||
write.write_bool(has_date)?;
|
||||
if let Some(date) = crit.achieve_date {
|
||||
write.write_i64_be(date)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write.write_bool(self.show_advancements)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user