diff --git a/pumpkin-protocol/src/lib.rs b/pumpkin-protocol/src/lib.rs index 380a487e0..f0c1a6711 100644 --- a/pumpkin-protocol/src/lib.rs +++ b/pumpkin-protocol/src/lib.rs @@ -10,8 +10,8 @@ pub mod packet_decoder; pub mod packet_encoder; pub mod position; pub mod server; -pub mod uuid; pub mod slot; +pub mod uuid; pub const CURRENT_MC_PROTOCOL: u32 = 767; diff --git a/pumpkin-protocol/src/server/play/s_interact.rs b/pumpkin-protocol/src/server/play/s_interact.rs index 62e2b3475..c141358b9 100644 --- a/pumpkin-protocol/src/server/play/s_interact.rs +++ b/pumpkin-protocol/src/server/play/s_interact.rs @@ -1,3 +1,7 @@ +use std::char::MAX; + +use num_derive::FromPrimitive; +use num_traits::FromPrimitive; use pumpkin_macros::packet; use crate::{ServerPacket, VarInt}; @@ -6,19 +10,45 @@ use crate::{ServerPacket, VarInt}; pub struct SInteract { pub entity_id: VarInt, pub typ: VarInt, - pub target_x: Option, - // don't ask me why, adding more values does not work :c + pub target_position: Option<(f32, f32, f32)>, + pub hand: Option, + pub sneaking: bool, } -// TODO +// Great job Mojang ;D impl ServerPacket for SInteract { fn read( bytebuf: &mut crate::bytebuf::ByteBuffer, ) -> Result { + let entity_id = bytebuf.get_var_int(); + let typ = bytebuf.get_var_int(); + let action = ActionType::from_i32(typ.0 as i32).unwrap(); + let target_position: Option<(f32, f32, f32)> = match action { + ActionType::Interact => None, + ActionType::Attack => None, + ActionType::InteractAt => { + Some((bytebuf.get_f32(), bytebuf.get_f32(), bytebuf.get_f32())) + } + }; + let hand = match action { + ActionType::Interact => Some(bytebuf.get_var_int()), + ActionType::Attack => None, + ActionType::InteractAt => Some(bytebuf.get_var_int()), + }; + Ok(Self { - entity_id: bytebuf.get_var_int(), - typ: bytebuf.get_var_int(), - target_x: bytebuf.get_option(|v| v.get_f32()), + entity_id, + typ, + target_position, + hand, + sneaking: bytebuf.get_bool(), }) } } + +#[derive(FromPrimitive, PartialEq, Eq)] +pub enum ActionType { + Interact, + Attack, + InteractAt, +} diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index f97869514..b06432cf5 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -7,9 +7,9 @@ use pumpkin_protocol::{ }, position::WorldPosition, server::play::{ - Action, SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract, - SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation, SPlayerRotation, - SSetCreativeSlot, SSetHeldItem, SSwingArm, SUseItemOn, + Action, ActionType, SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, + SInteract, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation, + SPlayerRotation, SSetCreativeSlot, SSetHeldItem, SSwingArm, SUseItemOn, }, }; use pumpkin_text::TextComponent; @@ -268,50 +268,53 @@ impl Client { } pub fn handle_interact(&mut self, server: &mut Server, interact: SInteract) { - let attacker_player = self.player.as_ref().unwrap(); - let entity_id = interact.entity_id; - // TODO: do validation and stuff - let config = &server.advanced_config.pvp; - if config.enabled { - let attacked_client = server.get_by_entityid(self, entity_id.0 as EntityId); - if let Some(mut client) = attacked_client { - let token = client.token.clone(); - let player = client.player.as_mut().unwrap(); - let velo = player.velocity; - if config.protect_creative && player.gamemode == GameMode::Creative { - return; + let action = ActionType::from_i32(interact.typ.0).unwrap(); + if action == ActionType::Attack { + let attacker_player = self.player.as_ref().unwrap(); + let entity_id = interact.entity_id; + // TODO: do validation and stuff + let config = &server.advanced_config.pvp; + if config.enabled { + let attacked_client = server.get_by_entityid(self, entity_id.0 as EntityId); + if let Some(mut client) = attacked_client { + let token = client.token.clone(); + let player = client.player.as_mut().unwrap(); + let velo = player.velocity; + if config.protect_creative && player.gamemode == GameMode::Creative { + return; + } + if config.knockback { + let pitch = attacker_player.entity.pitch; + let strength = 1.0; + player.knockback( + strength * 0.5, + (pitch * 0.017453292).sin() as f64, + -(pitch * 0.017453292).cos() as f64, + ); + let packet = &CEntityVelocity::new( + &entity_id, + player.velocity.x as f32, + player.velocity.y as f32, + player.velocity.z as f32, + ); + player.velocity = velo; + client.send_packet(packet); + // attacker_player.velocity = attacker_player.velocity.multiply(0.6, 1.0, 0.6); + } + if config.hurt_animation { + // TODO + // thats how we prevent borrow errors :c + let packet = &CHurtAnimation::new(&entity_id, 10.0); + self.send_packet(packet); + client.send_packet(packet); + server.broadcast_packet_expect( + &[self.token.as_ref(), token.as_ref()], + &CHurtAnimation::new(&entity_id, 10.0), + ) + } + } else { + self.kick("Interacted with invalid entitiy id") } - if config.knockback { - let pitch = attacker_player.entity.pitch; - let strength = 1.0; - player.knockback( - strength * 0.5, - (pitch * 0.017453292).sin() as f64, - -(pitch * 0.017453292).cos() as f64, - ); - let packet = &CEntityVelocity::new( - &entity_id, - player.velocity.x as f32, - player.velocity.y as f32, - player.velocity.z as f32, - ); - player.velocity = velo; - client.send_packet(packet); - // attacker_player.velocity = attacker_player.velocity.multiply(0.6, 1.0, 0.6); - } - if config.hurt_animation { - // TODO - // thats how we prevent borrow errors :c - let packet = &CHurtAnimation::new(&entity_id, 10.0); - self.send_packet(packet); - client.send_packet(packet); - server.broadcast_packet_expect( - &[self.token.as_ref(), token.as_ref()], - &CHurtAnimation::new(&entity_id, 10.0), - ) - } - } else { - self.kick("Interacted with invalid entitiy id") } } }