diff --git a/pumpkin-protocol/src/client/play/c_entity_animation.rs b/pumpkin-protocol/src/client/play/c_entity_animation.rs index f6a08e407..1c2e6da8b 100644 --- a/pumpkin-protocol/src/client/play/c_entity_animation.rs +++ b/pumpkin-protocol/src/client/play/c_entity_animation.rs @@ -20,10 +20,11 @@ impl CEntityAnimation { } } +#[derive(Debug)] #[repr(u8)] pub enum Animation { SwingMainArm, - LeaveBed, + LeaveBed = 2, SwingOffhand, CriticalEffect, MagicCriticaleffect, diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index 1d9dcd8e0..c1816bc02 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -76,7 +76,7 @@ impl Default for PlayerConfig { chat_mode: ChatMode::Enabled, chat_colors: true, skin_parts: 0, - main_hand: Hand::Main, + main_hand: Hand::Right, text_filtering: false, server_listing: false, } diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index 054d23f39..8679823ff 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -359,25 +359,32 @@ impl Player { } pub async fn handle_swing_arm(&self, swing_arm: SSwingArm) { - match Hand::from_i32(swing_arm.hand.0) { - Some(hand) => { - let animation = match hand { - Hand::Main => Animation::SwingMainArm, - Hand::Off => Animation::SwingOffhand, - }; - let id = self.entity_id(); - let world = self.world(); - world - .broadcast_packet_except( - &[self.gameprofile.id], - &CEntityAnimation::new(id.into(), animation as u8), - ) - .await; - } - None => { + let animation = match swing_arm.hand.0 { + 0 => Animation::SwingMainArm, + 1 => Animation::SwingOffhand, + _ => { self.kick(TextComponent::text("Invalid hand")).await; + return; } }; + // Invert hand if player is left handed + let animation = match self.config.lock().await.main_hand { + Hand::Left => match animation { + Animation::SwingMainArm => Animation::SwingOffhand, + Animation::SwingOffhand => Animation::SwingMainArm, + _ => unreachable!(), + }, + Hand::Right => animation, + }; + + let id = self.entity_id(); + let world = self.world(); + world + .broadcast_packet_except( + &[self.gameprofile.id], + &CEntityAnimation::new(id.into(), animation as u8), + ) + .await; } pub async fn handle_chat_message(&self, chat_message: SChatMessage) { @@ -442,6 +449,7 @@ impl Player { text_filtering: client_information.text_filtering, server_listing: client_information.server_listing, }; + self.update_client_information().await; } else { self.kick(TextComponent::text("Invalid hand or chat type")) .await; diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 101deb24f..d89d0f87f 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -24,7 +24,6 @@ use pumpkin_core::{ use pumpkin_entity::{entity_type::EntityType, EntityId}; use pumpkin_inventory::player::PlayerInventory; use pumpkin_macros::sound; -use pumpkin_protocol::server::play::{SClickContainer, SKeepAlive}; use pumpkin_protocol::server::play::{SCookieResponse as SPCookieResponse, SPlayPingRequest}; use pumpkin_protocol::{ bytebuf::packet_id::Packet, @@ -41,6 +40,10 @@ use pumpkin_protocol::{ }, RawPacket, ServerPacket, SoundCategory, VarInt, }; +use pumpkin_protocol::{ + client::play::{CSetEntityMetadata, Metadata}, + server::play::{SClickContainer, SKeepAlive}, +}; use pumpkin_world::{cylindrical_chunk_iterator::Cylindrical, item::ItemStack}; use tokio::sync::{Mutex, Notify}; use tokio::task::JoinHandle; @@ -656,6 +659,24 @@ impl Player { .await; } + /// Send skin layers and used hand to all players + pub async fn update_client_information(&self) { + let config = self.config.lock().await; + let world = self.world(); + world + .broadcast_packet_all(&CSetEntityMetadata::new( + self.entity_id().into(), + Metadata::new(17, 0.into(), config.skin_parts), + )) + .await; + world + .broadcast_packet_all(&CSetEntityMetadata::new( + self.entity_id().into(), + Metadata::new(18, 0.into(), config.main_hand as u8), + )) + .await; + } + pub async fn send_system_message<'a>(&self, text: &TextComponent<'a>) { self.client .send_packet(&CSystemChatMessage::new(text, false)) @@ -845,16 +866,17 @@ impl Default for Abilities { } /// Represents the player's dominant hand. -#[derive(FromPrimitive, Clone)] +#[derive(Debug, FromPrimitive, Clone, Copy)] +#[repr(u8)] pub enum Hand { - /// The player's primary hand (usually the right hand). - Main, - /// The player's off-hand (usually the left hand). - Off, + /// Usually the player's off-hand. + Left, + /// Usually the player's primary hand. + Right, } /// Represents the player's chat mode settings. -#[derive(FromPrimitive, Clone)] +#[derive(Debug, FromPrimitive, Clone)] pub enum ChatMode { /// Chat is enabled for the player. Enabled, @@ -865,7 +887,7 @@ pub enum ChatMode { } /// the player's permission level -#[derive(FromPrimitive, ToPrimitive, Clone, Copy)] +#[derive(Debug, FromPrimitive, ToPrimitive, Clone, Copy)] #[repr(i8)] pub enum PermissionLvl { Zero = 0, diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index cde04a910..022a350f9 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -292,6 +292,7 @@ impl World { }], )) .await; + player.update_client_information().await; // here we send all the infos of already joined players let mut entries = Vec::new();