chore(protocol): Clean up Bedrock by using more derive (#2808)

This commit is contained in:
Demetrius Kanios
2026-08-13 11:18:26 -07:00
committed by GitHub
parent 0d5f868db6
commit e0d16c74f2
41 changed files with 205 additions and 654 deletions

View File

@@ -509,8 +509,18 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
.into();
};
let type_generic = match input.generics.params.len() {
0 => quote! {},
1 => quote! { <'_> },
_ => {
return syn::Error::new(name.span(), "Only up to one lifetime parameter is supported.")
.to_compile_error()
.into();
}
};
let expanded = quote! {
impl PacketWrite for #name {
impl PacketWrite for #name #type_generic {
fn write<W: std::io::Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
#(#fields)*
Ok(())
@@ -537,26 +547,19 @@ pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let (is_big_endian, no_prefix) = check_serial_attributes(&f.attrs);
let is_vec = is_vec(&f.ty);
if is_vec && !no_prefix {
// Vec with prefix: read VarUInt length, then data
if is_vec && no_prefix {
return syn::Error::new(name.span(), "Cannot handle non-prefixed vecs")
.to_compile_error();
}
// Non-Vec or Vec without no_prefix: read directly
if is_big_endian {
quote! {
#ident: {
let len = crate::codec::var_uint::VarUInt::read(reader)?.0 as usize;
let mut buf = vec![0u8; len];
reader.read_exact(&mut buf)?;
buf
}
#ident: PacketRead::read_be(reader)?
}
} else {
// Non-Vec or Vec with no_prefix: read directly
if is_big_endian {
quote! {
#ident: PacketRead::read_be(reader)?
}
} else {
quote! {
#ident: PacketRead::read(reader)?
}
quote! {
#ident: PacketRead::read(reader)?
}
}
})
@@ -566,8 +569,19 @@ pub fn derive_deserialize(input: TokenStream) -> TokenStream {
.into();
};
let type_generic = match input.generics.params.len() {
0 => quote! {},
1 => quote! { <'static> },
_ => {
return syn::Error::new(name.span(), "Only up to one lifetime parameter is supported.")
.to_compile_error()
.into();
}
};
let expanded = quote! {
impl PacketRead for #name {
impl PacketRead for #name #type_generic {
fn read<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
Ok(Self {
#(#fields),*
@@ -579,6 +593,56 @@ pub fn derive_deserialize(input: TokenStream) -> TokenStream {
expanded.into()
}
/// Derives the `PacketReadSlice` trait for a struct, enabling deserialization from a slice.
///
/// # Arguments
/// - `input` The input `TokenStream` representing the struct to derive `PacketReadSlice` for.
#[rustfmt::skip]
#[proc_macro_derive(PacketReadSlice, attributes(serial))]
pub fn derive_deserialize_from_slice(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let fields = if let syn::Data::Struct(data) = &input.data {
data.fields.iter().map(|f| {
let ident = f.ident.as_ref().unwrap();
let (is_big_endian, no_prefix) = check_serial_attributes(&f.attrs);
let is_vec = is_vec(&f.ty);
if is_vec && no_prefix {
return syn::Error::new(name.span(), "Cannot handle non-prefixed vecs.")
.to_compile_error();
}
// Non-Vec or Vec without no_prefix: read directly
if is_big_endian {
return syn::Error::new(name.span(), "Cannot handle big-endian encoded fields")
.to_compile_error();
}
quote! {
#ident: PacketReadSlice::read_slice(buf)?
}
})
} else {
return syn::Error::new(name.span(), "Only structs are supported")
.to_compile_error()
.into();
};
let expanded = quote! {
impl<'a> PacketReadSlice<'a> for #name<'a> {
fn read_slice(buf: &mut &'a [u8]) -> std::io::Result<Self> {
Ok(Self {
#(#fields),*
})
}
}
};
expanded.into()
}
/// Checks a field's `#[serial(...)]` attributes.
///
/// # Arguments

View File

@@ -8,7 +8,7 @@ use crate::codec::var_int::VarInt;
#[derive(Debug, PacketWrite)]
#[packet(27)]
pub struct SActorEvent {
pub struct CActorEvent {
pub entity_runtime_id: VarULong,
pub event_type: ActorEventType,
pub event_data: VarInt,

View File

@@ -1,16 +1,16 @@
use crate::{
codec::{var_long::VarLong, var_uint::VarUInt, var_ulong::VarULong},
codec::{var_long::VarLong, var_ulong::VarULong},
serial::PacketWrite,
};
use pumpkin_macros::packet;
use pumpkin_util::math::vector3::Vector3;
use std::io::{Error, Write};
use super::{
common::EntityLink,
set_actor_data::{EntityMetadata, PropertySyncData},
};
#[derive(PacketWrite)]
#[packet(13)]
pub struct CAddActor {
pub entity_unique_id: VarLong,
@@ -28,31 +28,6 @@ pub struct CAddActor {
pub links: Vec<EntityLink>,
}
impl PacketWrite for CAddActor {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.entity_unique_id.write(writer)?;
self.entity_runtime_id.write(writer)?;
self.entity_type.write(writer)?;
self.position.write(writer)?;
self.velocity.write(writer)?;
self.pitch.write(writer)?;
self.yaw.write(writer)?;
self.head_yaw.write(writer)?;
self.body_yaw.write(writer)?;
VarUInt(self.attributes.len() as u32).write(writer)?;
for attr in &self.attributes {
attr.write(writer)?;
}
self.metadata.write(writer)?;
self.synced_properties.write(writer)?;
VarUInt(self.links.len() as u32).write(writer)?;
for link in &self.links {
link.write(writer)?;
}
Ok(())
}
}
impl CAddActor {
#[allow(clippy::too_many_arguments)]
#[must_use]

View File

@@ -4,11 +4,11 @@ use crate::{
};
use pumpkin_macros::packet;
use pumpkin_util::math::vector3::Vector3;
use std::io::{Error, Write};
use super::set_actor_data::EntityMetadata;
use crate::bedrock::network_item::ItemStackWrapper;
#[derive(PacketWrite)]
#[packet(15)]
pub struct CAddItemActor {
pub entity_unique_id: VarLong,
@@ -19,16 +19,3 @@ pub struct CAddItemActor {
pub metadata: EntityMetadata,
pub from_fishing: bool,
}
impl PacketWrite for CAddItemActor {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.entity_unique_id.write(writer)?;
self.entity_runtime_id.write(writer)?;
self.item.write(writer)?;
self.position.write(writer)?;
self.velocity.write(writer)?;
self.metadata.write(writer)?;
self.from_fishing.write(writer)?;
Ok(())
}
}

View File

@@ -13,6 +13,7 @@ use super::{
set_actor_data::EntityMetadata,
};
#[derive(PacketWrite)]
#[packet(12)]
pub struct CAddPlayer {
pub uuid: Uuid,
@@ -34,31 +35,6 @@ pub struct CAddPlayer {
pub build_platform: BuildPlatform,
}
impl PacketWrite for CAddPlayer {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.uuid.write(writer)?;
self.username.write(writer)?;
self.entity_runtime_id.write(writer)?;
self.platform_chat_id.write(writer)?;
self.position.write(writer)?;
self.velocity.write(writer)?;
self.pitch.write(writer)?;
self.yaw.write(writer)?;
self.head_yaw.write(writer)?;
self.held_item.write(writer)?;
self.game_mode.write(writer)?;
self.metadata.write(writer)?;
self.properties.write(writer)?;
self.ability_data.write(writer)?;
VarUInt(self.links.len() as u32).write(writer)?;
for link in &self.links {
link.write(writer)?;
}
self.device_id.write(writer)?;
self.build_platform.write(writer)
}
}
impl CAddPlayer {
#[allow(clippy::too_many_arguments)]
#[must_use]
@@ -125,23 +101,10 @@ impl PacketWrite for EntityProperties {
}
}
#[derive(Default, Clone)]
#[derive(Default, Clone, PacketWrite)]
pub struct AbilityData {
pub entity_unique_id: i64,
pub player_permissions: u8,
pub command_permissions: u8,
pub layers: Vec<AbilityLayer>,
}
impl PacketWrite for AbilityData {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.entity_unique_id.write(writer)?;
self.player_permissions.write(writer)?;
self.command_permissions.write(writer)?;
(self.layers.len() as u8).write(writer)?;
for layer in &self.layers {
layer.write(writer)?;
}
Ok(())
}
}

View File

@@ -1,7 +1,7 @@
use crate::{codec::var_uint::VarUInt, serial::PacketWrite};
use pumpkin_macros::packet;
use std::io::{Error, Write};
#[derive(PacketWrite)]
#[packet(76)]
pub struct CAvailableCommands {
pub enum_values: Vec<String>,
@@ -14,102 +14,30 @@ pub struct CAvailableCommands {
pub constraints: Vec<CommandEnumConstraint>,
}
impl PacketWrite for CAvailableCommands {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
fn write_string_slice<W: Write>(writer: &mut W, slice: &[String]) -> Result<(), Error> {
VarUInt(slice.len() as u32).write(writer)?;
for s in slice {
s.write(writer)?;
}
Ok(())
}
// 1. Enum values
write_string_slice(writer, &self.enum_values)?;
// 2. Chained subcommand values (The flat string list)
write_string_slice(writer, &self.chained_subcommand_values)?;
// 3. Suffixes
write_string_slice(writer, &self.suffixes)?;
// 4. Enums
VarUInt(self.enums.len() as u32).write(writer)?;
for e in &self.enums {
e.write(writer)?;
}
// 5. Chained Subcommands
VarUInt(self.chained_subcommands.len() as u32).write(writer)?;
for cs in &self.chained_subcommands {
cs.write(writer)?;
}
// 6. Commands
VarUInt(self.commands.len() as u32).write(writer)?;
for cmd in &self.commands {
cmd.write(writer)?;
}
// 7. Dynamic (Soft) Enums
VarUInt(self.soft_enums.len() as u32).write(writer)?;
for se in &self.soft_enums {
se.write(writer)?;
}
// 8. Constraints
VarUInt(self.constraints.len() as u32).write(writer)?;
for c in &self.constraints {
c.write(writer)?;
}
Ok(())
}
}
// Represents a subcommand that can chain commands, e.g. /execute.
// Written as a flat list in section 3 of the packet; Commands reference
// entries by index via ChainedSubcommandOffsets.
#[derive(PacketWrite)]
pub struct ChainedSubcommand {
pub name: String,
pub values: Vec<ChainedSubcommandValue>,
}
#[derive(PacketWrite)]
pub struct ChainedSubcommandValue {
/// Index into the `ChainedSubcommandValues` flat list — `VarUInt`
pub index: u32,
pub index: VarUInt,
/// Argument type flags (basic types only, no `ARG_FLAG`_* modifiers) — `VarUInt`
pub value: u32,
}
impl PacketWrite for ChainedSubcommand {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.name.write(writer)?;
VarUInt(self.values.len() as u32).write(writer)?;
for v in &self.values {
VarUInt(v.index).write(writer)?;
VarUInt(v.value).write(writer)?;
}
Ok(())
}
pub value: VarUInt,
}
#[derive(PacketWrite)]
pub struct CommandEnum {
pub name: String,
pub value_indices: Vec<usize>,
}
impl CommandEnum {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.name.write(writer)?;
VarUInt(self.value_indices.len() as u32).write(writer)?;
for &index in &self.value_indices {
writer.write_all(&(index as u32).to_le_bytes())?;
}
Ok(())
}
pub value_indices: Vec<u32>,
}
#[derive(PacketWrite)]
pub struct Command {
pub name: String,
pub description: String,
@@ -124,28 +52,7 @@ pub struct Command {
pub overloads: Vec<CommandOverload>,
}
impl PacketWrite for Command {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.name.write(writer)?;
self.description.write(writer)?;
writer.write_all(&self.flags.to_le_bytes())?;
self.permission.write(writer)?;
writer.write_all(&self.aliases_enum_index.to_le_bytes())?;
// Chained subcommand offsets
VarUInt(self.chained_subcommand_offsets.len() as u32).write(writer)?;
for &offset in &self.chained_subcommand_offsets {
writer.write_all(&offset.to_le_bytes())?;
}
VarUInt(self.overloads.len() as u32).write(writer)?;
for overload in &self.overloads {
overload.write(writer)?;
}
Ok(())
}
}
#[derive(PacketWrite)]
pub struct CommandOverload {
/// Written as a single byte before parameter count ← MISSING in original
/// true = this overload uses chained subcommands instead of regular params
@@ -153,20 +60,7 @@ pub struct CommandOverload {
pub parameters: Vec<CommandParameter>,
}
impl PacketWrite for CommandOverload {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
// Chaining bool ← MISSING in original — client reads this byte first
writer.write_all(&[u8::from(self.chaining)])?;
VarUInt(self.parameters.len() as u32).write(writer)?;
for param in &self.parameters {
param.write(writer)?;
}
Ok(())
}
}
#[derive(Clone)]
#[derive(Clone, PacketWrite)]
pub struct CommandParameter {
pub name: String,
/// LE u32 — encodes type flags (`ARG_FLAG_VALID` | `ARG_FLAG_ENUM` | index, or raw type)
@@ -176,16 +70,6 @@ pub struct CommandParameter {
pub options: u8,
}
impl PacketWrite for CommandParameter {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.name.write(writer)?;
writer.write_all(&self.type_info.to_le_bytes())?;
writer.write_all(&[u8::from(self.optional)])?;
writer.write_all(&[self.options])?;
Ok(())
}
}
// Constants matching PocketMine's ARG_FLAG_* and ARG_TYPE_* values
pub mod arg_flags {
pub const ARG_FLAG_VALID: u32 = 0x100000;
@@ -224,34 +108,15 @@ pub mod command_permissions {
pub const INTERNAL: &str = "internal";
}
#[derive(Clone, PacketWrite)]
pub struct SoftEnum {
pub name: String,
pub values: Vec<String>,
}
impl PacketWrite for SoftEnum {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.name.write(writer)?;
VarUInt(self.values.len() as u32).write(writer)?;
for value in &self.values {
value.write(writer)?;
}
Ok(())
}
}
#[derive(Clone, PacketWrite)]
pub struct CommandEnumConstraint {
pub affected_value_index: i32,
pub enum_index: i32,
pub constraints: Vec<u8>,
}
impl PacketWrite for CommandEnumConstraint {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
writer.write_all(&self.affected_value_index.to_le_bytes())?;
writer.write_all(&self.enum_index.to_le_bytes())?;
VarUInt(self.constraints.len() as u32).write(writer)?;
writer.write_all(&self.constraints)?;
Ok(())
}
}

View File

@@ -5,6 +5,7 @@ use crate::{
};
use pumpkin_macros::packet;
use std::io::{Error, Write};
use uuid::Uuid;
#[derive(Clone, Debug)]
pub struct ItemDescriptorCount {
@@ -48,7 +49,7 @@ pub struct BedrockShapelessRecipe {
pub recipe_id: String,
pub input: Vec<ItemDescriptorCount>,
pub output: Vec<NetworkItemDescriptor>,
pub uuid: [u8; 16],
pub uuid: Uuid,
pub block: String,
pub priority: VarInt,
pub unlock_requirement: RecipeUnlockRequirement,
@@ -72,7 +73,7 @@ impl PacketWrite for BedrockShapelessRecipe {
}
// uuid
writer.write_all(&self.uuid)?;
self.uuid.write(writer)?;
// block
self.block.write(writer)?;
@@ -97,7 +98,7 @@ pub struct BedrockShapedRecipe {
pub height: VarInt,
pub input: Vec<ItemDescriptorCount>,
pub output: Vec<NetworkItemDescriptor>,
pub uuid: [u8; 16],
pub uuid: Uuid,
pub block: String,
pub priority: VarInt,
pub assume_symmetry: bool,
@@ -123,7 +124,7 @@ impl PacketWrite for BedrockShapedRecipe {
}
// uuid
writer.write_all(&self.uuid)?;
self.uuid.write(writer)?;
// block
self.block.write(writer)?;

View File

@@ -4,8 +4,8 @@ use crate::{
serial::PacketWrite,
};
use pumpkin_macros::packet;
use std::io::{Error, Write};
#[derive(PacketWrite)]
#[packet(50)]
pub struct CInventorySlot {
pub window_id: VarUInt,
@@ -14,23 +14,3 @@ pub struct CInventorySlot {
pub storage: Option<NetworkItemStackDescriptor>,
pub item: NetworkItemStackDescriptor,
}
impl PacketWrite for CInventorySlot {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.window_id.write(writer)?;
self.inventory_slot.write(writer)?;
self.container_name.is_some().write(writer)?;
if let Some(container_name) = &self.container_name {
container_name.write(writer)?;
}
self.storage.is_some().write(writer)?;
if let Some(storage) = &self.storage {
storage.write(writer)?;
}
self.item.write(writer)?;
Ok(())
}
}

View File

@@ -1,3 +1,4 @@
pub mod actor_event;
pub mod add_actor;
pub mod add_item_actor;
pub mod add_player;
@@ -22,6 +23,7 @@ pub mod item_registry;
pub mod item_stack_response;
pub mod level_chunk;
pub mod level_event;
pub mod level_sound_event;
pub mod mob_effect;
pub mod mob_equipment;
pub mod modal_form_request;
@@ -39,6 +41,7 @@ pub mod resource_packs_info;
pub mod respawn;
pub mod scoreboard;
pub mod set_actor_data;
pub mod set_actor_link;
pub mod set_actor_motion;
pub mod set_difficulty;
pub mod set_health;
@@ -54,9 +57,6 @@ pub mod update_abilities;
pub mod update_attributes;
pub mod update_block;
pub mod level_sound_event;
pub mod set_actor_link;
pub use add_actor::*;
pub use add_item_actor::*;
pub use add_player::*;

View File

@@ -1,6 +1,8 @@
use crate::serial::PacketWrite;
use pumpkin_macros::packet;
use std::io::{Error, Write};
#[derive(PacketWrite)]
pub struct ResourcePackEntry {
pub uuid: uuid::Uuid,
pub version: String,
@@ -14,23 +16,6 @@ pub struct ResourcePackEntry {
pub download_url: String,
}
impl PacketWrite for ResourcePackEntry {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.uuid.write(writer)?;
self.version.write(writer)?;
// Bedrock uses Little Endian u64 for size
writer.write_all(&self.size.to_le_bytes())?;
self.content_key.write(writer)?;
self.sub_pack_name.write(writer)?;
self.content_id.write(writer)?;
self.has_scripts.write(writer)?;
self.addon_pack.write(writer)?;
self.rtx_enabled.write(writer)?;
self.download_url.write(writer)?;
Ok(())
}
}
#[packet(6)]
pub struct CResourcePacksInfo {
pub resource_pack_required: bool,

View File

@@ -1,11 +1,9 @@
use std::io::{Error, Write};
use pumpkin_macros::packet;
use pumpkin_util::math::position::BlockPos;
use crate::{codec::var_int::VarInt, serial::PacketWrite};
#[derive(Clone, Copy)]
#[derive(Clone, Copy, PacketWrite)]
#[packet(43)]
pub struct CSetSpawnPosition {
pub spawn_type: VarInt,
@@ -30,13 +28,3 @@ impl CSetSpawnPosition {
}
}
}
impl PacketWrite for CSetSpawnPosition {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.spawn_type.write(writer)?;
self.position.write(writer)?;
self.dimension.write(writer)?;
self.spawn_position.write(writer)?;
Ok(())
}
}

View File

@@ -1,10 +1,9 @@
use std::io::{Error, Write};
use pumpkin_macros::packet;
use pumpkin_util::math::position::BlockPos;
use crate::{codec::var_uint::VarUInt, serial::PacketWrite};
#[derive(PacketWrite)]
#[packet(21)]
pub struct CUpdateBlock {
pub position: BlockPos,
@@ -24,13 +23,3 @@ impl CUpdateBlock {
}
}
}
impl PacketWrite for CUpdateBlock {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.position.write(writer)?;
self.block_runtime_id.write(writer)?;
self.flags.write(writer)?;
self.layer.write(writer)?;
Ok(())
}
}

View File

@@ -85,7 +85,7 @@ impl PacketWrite for AnimateSwingSource {
}
}
#[derive(Debug)]
#[derive(Debug, PacketRead, PacketWrite)]
#[packet(44)]
pub struct SAnimate {
pub action: AnimateAction,
@@ -94,33 +94,6 @@ pub struct SAnimate {
pub swing_source: Option<AnimateSwingSource>,
}
impl PacketRead for SAnimate {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let action = AnimateAction::read(reader)?;
let runtime_entity_id = VarULong::read(reader)?;
let data = f32::read(reader)?;
let swing_source = Option::<AnimateSwingSource>::read(reader)?;
Ok(Self {
action,
runtime_entity_id,
data,
swing_source,
})
}
}
impl PacketWrite for SAnimate {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.action.write(writer)?;
self.runtime_entity_id.write(writer)?;
self.data.write(writer)?;
self.swing_source.write(writer)
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -2,9 +2,9 @@ use pumpkin_macros::packet;
use std::borrow::Cow;
use uuid::Uuid;
use crate::serial::{PacketRead, PacketReadSlice, read_str_slice};
use crate::serial::{PacketRead, PacketReadSlice};
#[derive(Debug)]
#[derive(Debug, PacketRead, PacketReadSlice)]
#[packet(77)]
pub struct SCommandRequest<'a> {
pub command: Cow<'a, str>,
@@ -15,46 +15,3 @@ pub struct SCommandRequest<'a> {
pub is_internal_source: bool,
pub version: Cow<'a, str>,
}
impl<'a> PacketReadSlice<'a> for SCommandRequest<'a> {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, std::io::Error> {
let command = Cow::Borrowed(read_str_slice(buf)?);
let command_type = Cow::Borrowed(read_str_slice(buf)?);
let command_uuid = Uuid::read_slice(buf)?;
let request_id = Cow::Borrowed(read_str_slice(buf)?);
let player_actor_unique_id = i64::read_slice(buf)?;
let is_internal_source = bool::read_slice(buf)?;
let version = Cow::Borrowed(read_str_slice(buf)?);
Ok(Self {
command,
command_type,
command_uuid,
request_id,
player_actor_unique_id,
is_internal_source,
version,
})
}
}
impl PacketRead for SCommandRequest<'static> {
fn read<R: std::io::Read>(reader: &mut R) -> Result<Self, std::io::Error> {
let command = Cow::Owned(String::read(reader)?);
let command_type = Cow::Owned(String::read(reader)?);
let command_uuid = Uuid::read(reader)?;
let request_id = Cow::Owned(String::read(reader)?);
let player_actor_unique_id = i64::read(reader)?;
let is_internal_source = bool::read(reader)?;
let version = Cow::Owned(String::read(reader)?);
Ok(Self {
command,
command_type,
command_uuid,
request_id,
player_actor_unique_id,
is_internal_source,
version,
})
}
}

View File

@@ -1,13 +1,13 @@
use crate::codec::{var_uint::VarUInt, var_ulong::VarULong};
use crate::serial::{PacketRead, PacketReadSlice, PacketWrite, read_str_slice};
use crate::codec::var_uint::VarUInt;
use crate::codec::var_ulong::VarULong;
use crate::serial::{PacketRead, PacketReadSlice, PacketWrite};
use pumpkin_macros::packet;
use std::borrow::Cow;
use std::io::{Error, Write};
pub const EMOTE_FLAG_SERVER_SIDE: u8 = 1 << 0;
pub const EMOTE_FLAG_MUTE_CHAT: u8 = 1 << 1;
#[derive(Debug)]
#[derive(Debug, PacketRead, PacketReadSlice, PacketWrite)]
#[packet(138)]
pub struct SEmote<'a> {
pub runtime_entity_id: VarULong,
@@ -17,46 +17,3 @@ pub struct SEmote<'a> {
pub platform_id: Cow<'a, str>,
pub flags: u8,
}
impl<'a> PacketReadSlice<'a> for SEmote<'a> {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
let runtime_entity_id = VarULong::read_slice(buf)?;
let emote_length = VarUInt::read_slice(buf)?;
let emote_id = Cow::Borrowed(read_str_slice(buf)?);
let xuid = Cow::Borrowed(read_str_slice(buf)?);
let platform_id = Cow::Borrowed(read_str_slice(buf)?);
let flags = u8::read_slice(buf)?;
Ok(Self {
runtime_entity_id,
emote_length,
emote_id,
xuid,
platform_id,
flags,
})
}
}
impl PacketRead for SEmote<'static> {
fn read<R: std::io::Read>(reader: &mut R) -> Result<Self, Error> {
Ok(Self {
runtime_entity_id: VarULong::read(reader)?,
emote_length: VarUInt::read(reader)?,
emote_id: Cow::Owned(String::read(reader)?),
xuid: Cow::Owned(String::read(reader)?),
platform_id: Cow::Owned(String::read(reader)?),
flags: u8::read(reader)?,
})
}
}
impl PacketWrite for SEmote<'_> {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.runtime_entity_id.write(writer)?;
self.emote_length.write(writer)?;
self.emote_id.as_ref().write(writer)?;
self.xuid.as_ref().write(writer)?;
self.platform_id.as_ref().write(writer)?;
self.flags.write(writer)
}
}

View File

@@ -1,45 +1,18 @@
use std::io::{Error, Read, Write};
use uuid::Uuid;
use crate::{
codec::{var_uint::VarUInt, var_ulong::VarULong},
codec::var_ulong::VarULong,
serial::{PacketRead, PacketWrite},
};
use pumpkin_macros::packet;
#[derive(Debug)]
#[derive(Debug, PacketRead, PacketWrite)]
#[packet(152)]
pub struct SEmoteList {
pub runtime_entity_id: VarULong,
pub emote_pieces: Vec<Uuid>,
}
impl PacketRead for SEmoteList {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let runtime_entity_id = VarULong::read(reader)?;
let len = VarUInt::read(reader)?.0 as usize;
let mut emote_pieces = Vec::with_capacity(len);
for _ in 0..len {
emote_pieces.push(Uuid::read(reader)?);
}
Ok(Self {
runtime_entity_id,
emote_pieces,
})
}
}
impl PacketWrite for SEmoteList {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.runtime_entity_id.write(writer)?;
VarUInt(self.emote_pieces.len() as u32).write(writer)?;
for piece in &self.emote_pieces {
piece.write(writer)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -125,7 +125,7 @@ pub struct NormalTransactionData;
#[derive(Debug, PacketRead)]
pub struct MismatchTransactionData;
#[derive(Debug)]
#[derive(Debug, PacketRead)]
pub struct UseItemTransactionData {
pub action_type: VarInt,
pub trigger_type: u8,
@@ -140,25 +140,7 @@ pub struct UseItemTransactionData {
pub client_cooldown_state: u8,
}
impl PacketRead for UseItemTransactionData {
fn read<R: Read>(buf: &mut R) -> Result<Self, Error> {
Ok(Self {
action_type: VarInt::read(buf)?,
trigger_type: u8::read(buf)?,
block_position: BlockPos::read(buf)?,
block_face: i32::from(u8::read(buf)?),
hot_bar_slot: VarInt::read(buf)?,
item_in_hand: NetworkItemDescriptor::read(buf)?,
player_position: Vector3::read(buf)?,
click_position: Vector3::read(buf)?,
block_runtime_id: VarUInt::read(buf)?,
client_prediction: u8::read(buf)?,
client_cooldown_state: u8::read(buf)?,
})
}
}
#[derive(Debug)]
#[derive(Debug, PacketRead)]
pub struct UseItemOnEntityTransactionData {
pub target_entity_runtime_id: VarULong,
pub action_type: VarInt,
@@ -168,20 +150,7 @@ pub struct UseItemOnEntityTransactionData {
pub click_position: Vector3<f32>,
}
impl PacketRead for UseItemOnEntityTransactionData {
fn read<R: Read>(buf: &mut R) -> Result<Self, Error> {
Ok(Self {
target_entity_runtime_id: VarULong::read(buf)?,
action_type: VarInt::read(buf)?,
hot_bar_slot: VarInt::read(buf)?,
item_in_hand: NetworkItemDescriptor::read(buf)?,
player_position: Vector3::read(buf)?,
click_position: Vector3::read(buf)?,
})
}
}
#[derive(Debug)]
#[derive(Debug, PacketRead)]
pub struct ReleaseItemTransactionData {
pub action_type: VarInt,
pub hot_bar_slot: VarInt,
@@ -189,17 +158,6 @@ pub struct ReleaseItemTransactionData {
pub head_position: Vector3<f32>,
}
impl PacketRead for ReleaseItemTransactionData {
fn read<R: Read>(buf: &mut R) -> Result<Self, Error> {
Ok(Self {
action_type: VarInt::read(buf)?,
hot_bar_slot: VarInt::read(buf)?,
item_in_hand: NetworkItemDescriptor::read(buf)?,
head_position: Vector3::read(buf)?,
})
}
}
#[derive(Debug)]
#[packet(30)]
pub struct SInventoryTransaction {

View File

@@ -1,4 +1,4 @@
use std::io::{Error, ErrorKind, Read, Write};
use std::io::{Error, ErrorKind, Read};
use crate::{
bedrock::network_item::FullContainerName,
@@ -20,11 +20,11 @@ fn collection_length<R: Read>(reader: &mut R, name: &str) -> Result<usize, Error
Ok(len as usize)
}
#[derive(Debug)]
#[derive(Debug, PacketRead, PacketWrite)]
pub struct ItemStackRequestSlotInfo {
pub container_name: FullContainerName,
pub slot_id: u8,
pub stack_id: VarInt,
pub stack_id: i32,
}
#[derive(Debug)]
@@ -65,28 +65,6 @@ impl PacketRead for StackRequestItem {
}
}
impl PacketRead for ItemStackRequestSlotInfo {
fn read<R: Read>(buf: &mut R) -> Result<Self, Error> {
let container_name = FullContainerName::read(buf)?;
let slot_id = u8::read(buf)?;
let stack_id = VarInt(i32::read(buf)?);
Ok(Self {
container_name,
slot_id,
stack_id,
})
}
}
impl PacketWrite for ItemStackRequestSlotInfo {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.container_name.write(writer)?;
self.slot_id.write(writer)?;
self.stack_id.0.write(writer)?;
Ok(())
}
}
#[derive(Debug)]
pub enum ItemStackRequestAction {
Take {
@@ -349,14 +327,14 @@ mod tests {
dynamic_id: None,
},
slot_id: 4,
stack_id: VarInt(-2),
stack_id: -2,
};
let mut encoded = Vec::new();
slot.write(&mut encoded).unwrap();
assert_eq!(&encoded[encoded.len() - 4..], &(-2i32).to_le_bytes());
let decoded = ItemStackRequestSlotInfo::read(&mut encoded.as_slice()).unwrap();
assert_eq!(decoded.stack_id, VarInt(-2));
assert_eq!(decoded.stack_id, -2);
}
#[test]

View File

@@ -7,6 +7,7 @@ use crate::{MAX_PACKET_DATA_SIZE, codec::var_uint::VarUInt, serial::PacketRead};
#[packet(1)]
pub struct SLogin {
// https://mojang.github.io/bedrock-protocol-docs/html/LoginPacket.html
//#[serial(big_endian)]
pub protocol_version: i32,
// https://mojang.github.io/bedrock-protocol-docs/html/connectionRequest.html

View File

@@ -1,4 +1,3 @@
pub mod actor_event;
pub mod animate;
pub mod block_pick_request;
pub mod client_cache_blob_status;
@@ -27,7 +26,6 @@ pub mod set_local_player_as_initialized;
pub mod set_player_inventory_options;
pub mod text;
pub use actor_event::*;
pub use animate::*;
pub use block_pick_request::*;
pub use client_cache_blob_status::*;

View File

@@ -1,41 +1,12 @@
use crate::codec::var_uint::VarUInt;
use crate::serial::{PacketRead, PacketReadSlice, read_str_slice};
use crate::serial::{PacketRead, PacketReadSlice};
use pumpkin_macros::packet;
use std::borrow::Cow;
use std::io::{Error, Read};
#[derive(Debug)]
#[derive(Debug, PacketRead, PacketReadSlice)]
#[packet(101)]
pub struct SModalFormResponse<'a> {
pub form_id: VarUInt,
pub form_data: Option<Cow<'a, str>>,
pub cancel_reason: Option<u8>,
}
impl<'a> PacketReadSlice<'a> for SModalFormResponse<'a> {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
let form_id = VarUInt::read_slice(buf)?;
let form_data = bool::read_slice(buf)?
.then(|| read_str_slice(buf).map(Cow::Borrowed))
.transpose()?;
let cancel_reason = Option::<u8>::read_slice(buf)?;
Ok(Self {
form_id,
form_data,
cancel_reason,
})
}
}
impl PacketRead for SModalFormResponse<'static> {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
let form_id = VarUInt::read(reader)?;
let form_data = Option::<String>::read(reader)?.map(Cow::Owned);
let cancel_reason = Option::<u8>::read(reader)?;
Ok(Self {
form_id,
form_data,
cancel_reason,
})
}
}

View File

@@ -24,20 +24,13 @@ impl PacketRead for AbilityValue {
}
}
#[derive(PacketRead)]
#[packet(184)]
pub struct SRequestAbility {
pub ability: VarInt,
pub value: AbilityValue,
}
impl PacketRead for SRequestAbility {
fn read<R: Read>(buf: &mut R) -> Result<Self, Error> {
let ability = VarInt::read(buf)?;
let value = AbilityValue::read(buf)?;
Ok(Self { ability, value })
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -1,16 +1,8 @@
use crate::{codec::var_ulong::VarULong, serial::PacketRead};
use pumpkin_macros::packet;
use std::io::{Error, Read};
#[derive(PacketRead)]
#[packet(113)]
pub struct SSetLocalPlayerAsInitialized {
pub runtime_entity_id: VarULong,
}
impl PacketRead for SSetLocalPlayerAsInitialized {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
Ok(Self {
runtime_entity_id: VarULong::read(reader)?,
})
}
}

View File

@@ -1,7 +1,7 @@
use crate::{codec::var_int::VarInt, serial::PacketRead};
use pumpkin_macros::packet;
use std::io::{Error, Read};
#[derive(PacketRead)]
#[packet(307)]
pub struct SSetPlayerInventoryOptions {
pub left_inventory_tab: VarInt,
@@ -10,15 +10,3 @@ pub struct SSetPlayerInventoryOptions {
pub inventory_layout: VarInt,
pub crafting_layout: VarInt,
}
impl PacketRead for SSetPlayerInventoryOptions {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
Ok(Self {
left_inventory_tab: VarInt::read(reader)?,
right_inventory_tab: VarInt::read(reader)?,
filtering: bool::read(reader)?,
inventory_layout: VarInt::read(reader)?,
crafting_layout: VarInt::read(reader)?,
})
}
}

View File

@@ -1,4 +1,5 @@
use std::{
borrow::Cow,
io::{Error, ErrorKind, Read},
net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
};
@@ -8,7 +9,7 @@ use uuid::Uuid;
use crate::{
codec::{var_int::VarInt, var_uint::VarUInt},
serial::PacketRead,
serial::{PacketRead, PacketReadSlice, read_str_slice},
};
impl PacketRead for bool {
@@ -169,18 +170,13 @@ impl PacketRead for String {
}
}
impl PacketRead for Vec<u8> {
impl<T: PacketRead> PacketRead for Vec<T> {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
const MAX_VECTOR_BYTES: usize = 2 * 1024 * 1024; // 2 MB safety cap
let len = VarUInt::read(reader)?.0 as usize;
if len > MAX_VECTOR_BYTES {
return Err(Error::new(
ErrorKind::InvalidData,
format!("Byte vector length {len} exceeds maximum limit of {MAX_VECTOR_BYTES}"),
));
let len = VarUInt::read(reader)?.0 as _;
let mut buf = Self::with_capacity(len);
for _ in 0..len {
buf.push(T::read(reader)?);
}
let mut buf = vec![0u8; len];
reader.read_exact(&mut buf)?;
Ok(buf)
}
}
@@ -255,7 +251,13 @@ impl<T: PacketRead> PacketRead for Option<T> {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for bool {
impl PacketRead for Cow<'_, str> {
fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
Ok(Self::Owned(String::read(reader)?))
}
}
impl<'a> PacketReadSlice<'a> for bool {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.is_empty() {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected bool byte"));
@@ -266,7 +268,7 @@ impl<'a> crate::serial::PacketReadSlice<'a> for bool {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for u8 {
impl<'a> PacketReadSlice<'a> for u8 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.is_empty() {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected u8"));
@@ -277,13 +279,13 @@ impl<'a> crate::serial::PacketReadSlice<'a> for u8 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for i8 {
impl<'a> PacketReadSlice<'a> for i8 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
u8::read_slice(buf).map(|b| b as Self)
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for i16 {
impl<'a> PacketReadSlice<'a> for i16 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 2 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected i16"));
@@ -297,7 +299,7 @@ impl<'a> crate::serial::PacketReadSlice<'a> for i16 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for i32 {
impl<'a> PacketReadSlice<'a> for i32 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 4 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected i32"));
@@ -311,7 +313,7 @@ impl<'a> crate::serial::PacketReadSlice<'a> for i32 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for i64 {
impl<'a> PacketReadSlice<'a> for i64 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 8 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected i64"));
@@ -325,7 +327,7 @@ impl<'a> crate::serial::PacketReadSlice<'a> for i64 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for u16 {
impl<'a> PacketReadSlice<'a> for u16 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 2 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected u16"));
@@ -339,7 +341,7 @@ impl<'a> crate::serial::PacketReadSlice<'a> for u16 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for u32 {
impl<'a> PacketReadSlice<'a> for u32 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 4 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected u32"));
@@ -353,7 +355,7 @@ impl<'a> crate::serial::PacketReadSlice<'a> for u32 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for u64 {
impl<'a> PacketReadSlice<'a> for u64 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 8 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected u64"));
@@ -367,7 +369,7 @@ impl<'a> crate::serial::PacketReadSlice<'a> for u64 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for f32 {
impl<'a> PacketReadSlice<'a> for f32 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 4 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected f32"));
@@ -381,7 +383,7 @@ impl<'a> crate::serial::PacketReadSlice<'a> for f32 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for f64 {
impl<'a> PacketReadSlice<'a> for f64 {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 8 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected f64"));
@@ -395,13 +397,13 @@ impl<'a> crate::serial::PacketReadSlice<'a> for f64 {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for &'a str {
impl<'a> PacketReadSlice<'a> for &'a str {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
crate::serial::read_str_slice(buf)
read_str_slice(buf)
}
}
impl<'a, T: crate::serial::PacketReadSlice<'a>> crate::serial::PacketReadSlice<'a> for Option<T> {
impl<'a, T: PacketReadSlice<'a>> PacketReadSlice<'a> for Option<T> {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
bool::read_slice(buf)?
.then(|| T::read_slice(buf))
@@ -409,7 +411,7 @@ impl<'a, T: crate::serial::PacketReadSlice<'a>> crate::serial::PacketReadSlice<'
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for uuid::Uuid {
impl<'a> PacketReadSlice<'a> for uuid::Uuid {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
if buf.len() < 16 {
return Err(Error::new(ErrorKind::UnexpectedEof, "expected Uuid"));
@@ -423,20 +425,26 @@ impl<'a> crate::serial::PacketReadSlice<'a> for uuid::Uuid {
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for crate::codec::var_int::VarInt {
impl<'a> PacketReadSlice<'a> for crate::codec::var_int::VarInt {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
Self::read(buf)
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for crate::codec::var_uint::VarUInt {
impl<'a> PacketReadSlice<'a> for crate::codec::var_uint::VarUInt {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
Self::read(buf)
}
}
impl<'a> crate::serial::PacketReadSlice<'a> for crate::codec::var_ulong::VarULong {
impl<'a> PacketReadSlice<'a> for crate::codec::var_ulong::VarULong {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
Self::read(buf)
}
}
impl<'a> PacketReadSlice<'a> for Cow<'a, str> {
fn read_slice(buf: &mut &'a [u8]) -> Result<Self, Error> {
Ok(Self::Borrowed(read_str_slice(buf)?))
}
}

View File

@@ -1,6 +1,6 @@
pub mod deserializer;
pub mod serializer;
pub use pumpkin_macros::{PacketRead, PacketWrite};
pub use pumpkin_macros::{PacketRead, PacketReadSlice, PacketWrite};
use std::io::{Error, Read, Write};
pub trait PacketWrite {

View File

@@ -1,4 +1,5 @@
use std::{
borrow::Cow,
io::{Error, Write},
net::SocketAddr,
};
@@ -200,3 +201,9 @@ impl PacketWrite for GameMode {
.write(writer)
}
}
impl PacketWrite for Cow<'_, str> {
fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
self.as_ref().write(writer)
}
}

View File

@@ -588,7 +588,7 @@ fn collect_overloads_from_attached(
}
}
fn ensure_enum_value(enum_values: &mut Vec<String>, value: &str) -> usize {
fn ensure_enum_value(enum_values: &mut Vec<String>, value: &str) -> u32 {
enum_values
.iter()
.position(|v| v == value)
@@ -596,6 +596,8 @@ fn ensure_enum_value(enum_values: &mut Vec<String>, value: &str) -> usize {
enum_values.push(value.to_string());
enum_values.len() - 1
})
.try_into()
.unwrap()
}
fn ensure_command_enum(
@@ -608,7 +610,7 @@ fn ensure_command_enum(
return pos;
}
let value_indices: Vec<usize> = values
let value_indices: Vec<u32> = values
.iter()
.map(|val| ensure_enum_value(enum_values, val))
.collect();

View File

@@ -6,8 +6,8 @@ use pumpkin_data::tracked_data::{TrackedData, TrackedId};
use pumpkin_inventory::build_equipment_slots;
use pumpkin_inventory::player::player_inventory::PlayerInventory;
use pumpkin_inventory::screen_handler::InventoryPlayer;
use pumpkin_protocol::bedrock::client::actor_event::{ActorEventType, CActorEvent};
use pumpkin_protocol::bedrock::client::take_item_actor::CTakeItemActor;
use pumpkin_protocol::bedrock::server::actor_event::{ActorEventType, SActorEvent};
use pumpkin_protocol::codec::var_ulong::VarULong;
use pumpkin_util::GameMode;
use pumpkin_util::Hand;
@@ -2485,7 +2485,7 @@ impl EntityBase for LivingEntity {
(src.z - tgt.z).atan2(src.x - tgt.x).to_degrees() as f32
- self.entity.yaw.load()
});
let hurt_event = SActorEvent {
let hurt_event = CActorEvent {
entity_runtime_id: VarULong(entity_id as u64),
event_type: ActorEventType::Hurt,
event_data: VarInt(0),

View File

@@ -5,7 +5,7 @@ use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use crate::entity::{EntityBaseFuture, mob::Mob, player::Player};
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_util::math::vector3::Vector3;
pub trait Animal: Mob {

View File

@@ -11,7 +11,7 @@ use pumpkin_data::meta_data_type::MetaDataType;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_data::tracked_data::TrackedData;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;

View File

@@ -10,7 +10,7 @@ use pumpkin_data::meta_data_type::MetaDataType;
use pumpkin_data::tag::{self, Taggable};
use pumpkin_data::tracked_data::TrackedData;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_protocol::java::client::play::Metadata;
use rand::RngExt;

View File

@@ -18,7 +18,7 @@ use pumpkin_inventory::screen_handler::{
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::java::client::play::{CMerchantOffers, Metadata};
use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos, vector3::Vector3};

View File

@@ -64,8 +64,8 @@ use pumpkin_nbt::compound::NbtCompound;
use pumpkin_nbt::tag::NbtTag;
use pumpkin_protocol::IdOr;
use pumpkin_protocol::SoundEvent;
use pumpkin_protocol::bedrock::client::actor_event::{ActorEventType, CActorEvent};
use pumpkin_protocol::bedrock::client::container_open::CContainerOpen;
use pumpkin_protocol::bedrock::server::actor_event::{ActorEventType, SActorEvent};
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_protocol::codec::var_long::VarLong;
use pumpkin_protocol::codec::var_ulong::VarULong;
@@ -3440,7 +3440,7 @@ impl Player {
self.client
.send_packet_now_editioned(
&CCombatDeath::new(self.entity_id().into(), &death_msg),
&SActorEvent {
&CActorEvent {
entity_runtime_id: VarULong(self.entity_id() as u64),
event_type: ActorEventType::Death,
event_data: VarInt(0),

View File

@@ -14,7 +14,7 @@ use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::meta_data_type::MetaDataType;
use pumpkin_data::tracked_data::TrackedData;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer;
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;

View File

@@ -13,7 +13,7 @@ use pumpkin_data::damage::DamageType;
use pumpkin_data::entity::{EntityPose, EntityStatus};
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_util::math::vector3::Vector3;
const GRAVITY: f64 = 0.03;

View File

@@ -4,7 +4,7 @@ use crate::{
world::World,
};
use pumpkin_data::{entity::EntityStatus, meta_data_type::MetaDataType, tracked_data::TrackedData};
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_protocol::{codec::optional_int::OptionalInt, java::client::play::Metadata};
use pumpkin_util::{
math::vector3::Vector3,

View File

@@ -8,7 +8,7 @@ use crate::{
};
use pumpkin_data::entity::EntityStatus;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_protocol::java::client::play::CWorldEvent;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector2::{Vector2, to_chunk_pos};

View File

@@ -8,7 +8,7 @@ use crate::{
};
use pumpkin_data::damage::DamageType;
use pumpkin_data::entity::{EntityStatus, EntityType};
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_util::math::vector3::Vector3;
const GRAVITY: f64 = 0.03;

View File

@@ -5,7 +5,7 @@ use pumpkin_data::entity::EntityStatus;
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
use pumpkin_protocol::bedrock::client::actor_event::ActorEventType;
use pumpkin_util::math::vector3::Vector3;
use rand::RngExt;

View File

@@ -96,6 +96,7 @@ use pumpkin_protocol::{
BClientPacket, ClientPacket, IdOr, SoundEvent,
bedrock::{
client::{
actor_event::{ActorEventType, CActorEvent},
add_player::CAddPlayer,
block_event::CBlockEvent as CBedrockBlockEvent,
common::BuildPlatform,
@@ -107,10 +108,7 @@ use pumpkin_protocol::{
start_game::{Experiments, GamePublishSetting, LevelSettings},
update_attributes::{Attribute, CUpdateAttributes},
},
server::{
actor_event::{ActorEventType, SActorEvent},
text::SText,
},
server::text::SText,
},
codec::{var_int::VarInt, var_long::VarLong, var_uint::VarUInt, var_ulong::VarULong},
java::{
@@ -496,7 +494,7 @@ impl World {
let chunk_pos = entity.chunk_pos.load();
let je_packet = CEntityStatus::new(entity.entity_id, java_status as i8);
if let Some(be_event) = bedrock_status {
let be_packet = SActorEvent {
let be_packet = CActorEvent {
entity_runtime_id: VarULong(entity.entity_id as u64),
event_type: be_event,
event_data: VarInt(0),
@@ -2421,7 +2419,7 @@ impl World {
height: VarInt(height),
input,
output: vec![output_descriptor],
uuid: [0; 16],
uuid: Uuid::nil(),
block: "crafting_table".to_string(),
priority: VarInt(1),
assume_symmetry: true,
@@ -2459,7 +2457,7 @@ impl World {
recipe_id: format!("pumpkin:recipe_{network_id_counter}"),
input,
output: vec![output_descriptor],
uuid: [0; 16],
uuid: Uuid::nil(),
block: "crafting_table".to_string(),
priority: VarInt(1),
unlock_requirement: RecipeUnlockRequirement { context: 1 },