160 lines
5.8 KiB
Rust
160 lines
5.8 KiB
Rust
use pumpkin_protocol::{
|
|
client::play::{CHeadRot, CUpdateEntityPos, CUpdateEntityPosRot, CUpdateEntityRot},
|
|
server::play::{
|
|
SChatCommand, SConfirmTeleport, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation,
|
|
SPlayerRotation,
|
|
},
|
|
};
|
|
|
|
use crate::{
|
|
commands::{handle_command, CommandSender},
|
|
server::Server,
|
|
};
|
|
|
|
use super::Client;
|
|
|
|
/// Handles all Play Packets send by a real Player
|
|
impl Client {
|
|
pub fn handle_confirm_teleport(
|
|
&mut self,
|
|
_server: &mut Server,
|
|
confirm_teleport: SConfirmTeleport,
|
|
) {
|
|
let player = self.player.as_mut().unwrap();
|
|
if let Some(id) = player.awaiting_teleport.clone() {
|
|
if id == confirm_teleport.teleport_id {
|
|
} else {
|
|
log::warn!("Teleport id does not match, Weird but okay");
|
|
}
|
|
player.awaiting_teleport = None;
|
|
} else {
|
|
self.kick("Send Teleport confirm, but we did not teleport")
|
|
}
|
|
}
|
|
|
|
pub fn handle_position(&mut self, server: &mut Server, position: SPlayerPosition) {
|
|
if position.x.is_nan() || position.feet_y.is_nan() || position.z.is_nan() {
|
|
self.kick("Invalid movement");
|
|
}
|
|
let player = self.player.as_mut().unwrap();
|
|
let entity = &mut player.entity;
|
|
entity.lastx = entity.x;
|
|
entity.lasty = entity.y;
|
|
entity.lastz = entity.z;
|
|
entity.x = position.x;
|
|
entity.y = position.feet_y;
|
|
entity.z = position.z;
|
|
// todo: teleport when moving > 8 block
|
|
|
|
// send new position to all other players
|
|
let on_ground = player.on_ground;
|
|
let entity_id = entity.entity_id;
|
|
let (x, lastx) = (entity.x, entity.lastx);
|
|
let (y, lasty) = (entity.y, entity.lasty);
|
|
let (z, lastz) = (entity.z, entity.lastz);
|
|
|
|
server.broadcast_packet(
|
|
self,
|
|
CUpdateEntityPos::new(
|
|
entity_id.into(),
|
|
(x * 4096.0 - lastx * 4096.0) as i16,
|
|
(y * 4096.0 - lasty * 4096.0) as i16,
|
|
(z * 4096.0 - lastz * 4096.0) as i16,
|
|
on_ground,
|
|
),
|
|
);
|
|
}
|
|
|
|
pub fn handle_position_rotation(
|
|
&mut self,
|
|
server: &mut Server,
|
|
position_rotation: SPlayerPositionRotation,
|
|
) {
|
|
if position_rotation.x.is_nan()
|
|
|| position_rotation.feet_y.is_nan()
|
|
|| position_rotation.z.is_nan()
|
|
{
|
|
self.kick("Invalid movement");
|
|
}
|
|
if !position_rotation.yaw.is_finite() || !position_rotation.pitch.is_finite() {
|
|
self.kick("Invalid rotation");
|
|
}
|
|
let player = self.player.as_mut().unwrap();
|
|
let entity = &mut player.entity;
|
|
|
|
entity.x = position_rotation.x;
|
|
entity.y = position_rotation.feet_y;
|
|
entity.z = position_rotation.z;
|
|
entity.yaw = position_rotation.yaw % 360.0;
|
|
entity.pitch = position_rotation.pitch.clamp(-90.0, 90.0) % 360.0;
|
|
|
|
// send new position to all other players
|
|
let on_ground = player.on_ground;
|
|
let entity_id = entity.entity_id;
|
|
let (x, lastx) = (entity.x, entity.lastx);
|
|
let (y, lasty) = (entity.y, entity.lasty);
|
|
let (z, lastz) = (entity.z, entity.lastz);
|
|
let yaw = (entity.yaw * 256.0 / 360.0).floor();
|
|
let pitch = (entity.pitch * 256.0 / 360.0).floor();
|
|
let head_yaw = (entity.head_yaw * 256.0 / 360.0).floor();
|
|
|
|
server.broadcast_packet(
|
|
self,
|
|
CUpdateEntityPosRot::new(
|
|
entity_id.into(),
|
|
(x * 4096.0 - lastx * 4096.0) as i16,
|
|
(y * 4096.0 - lasty * 4096.0) as i16,
|
|
(z * 4096.0 - lastz * 4096.0) as i16,
|
|
yaw as u8,
|
|
pitch as u8,
|
|
on_ground,
|
|
),
|
|
);
|
|
server.broadcast_packet(self, CHeadRot::new(entity_id.into(), head_yaw as u8));
|
|
}
|
|
|
|
pub fn handle_rotation(&mut self, server: &mut Server, rotation: SPlayerRotation) {
|
|
if !rotation.yaw.is_finite() || !rotation.pitch.is_finite() {
|
|
self.kick("Invalid rotation");
|
|
}
|
|
let player = self.player.as_mut().unwrap();
|
|
let entity = &mut player.entity;
|
|
entity.yaw = rotation.yaw % 360.0;
|
|
entity.pitch = rotation.pitch.clamp(-90.0, 90.0) % 360.0;
|
|
// send new position to all other players
|
|
let on_ground = player.on_ground;
|
|
let entity_id = entity.entity_id;
|
|
let yaw = entity.yaw;
|
|
let pitch = entity.pitch;
|
|
|
|
server.broadcast_packet(
|
|
self,
|
|
CUpdateEntityRot::new(entity_id.into(), yaw as u8, pitch as u8, on_ground),
|
|
);
|
|
server.broadcast_packet(self, CHeadRot::new(entity_id.into(), yaw as u8));
|
|
}
|
|
|
|
pub fn handle_chat_command(&mut self, _server: &mut Server, command: SChatCommand) {
|
|
handle_command(&mut CommandSender::Player(self), command.command);
|
|
}
|
|
|
|
pub fn handle_player_command(&mut self, _server: &mut Server, command: SPlayerCommand) {
|
|
let player = self.player.as_mut().unwrap();
|
|
|
|
if command.entitiy_id != player.entity.entity_id.into() {
|
|
return;
|
|
}
|
|
|
|
match command.action {
|
|
pumpkin_protocol::server::play::Action::StartSneaking => player.sneaking = true,
|
|
pumpkin_protocol::server::play::Action::StopSneaking => player.sneaking = false,
|
|
pumpkin_protocol::server::play::Action::LeaveBed => todo!(),
|
|
pumpkin_protocol::server::play::Action::StartSprinting => player.sprinting = true,
|
|
pumpkin_protocol::server::play::Action::StopSprinting => player.sprinting = false,
|
|
pumpkin_protocol::server::play::Action::StartHourseJump => todo!(),
|
|
pumpkin_protocol::server::play::Action::OpenVehicleInventory => todo!(),
|
|
pumpkin_protocol::server::play::Action::StartFlyingElytra => todo!(),
|
|
}
|
|
}
|
|
}
|