Add Deserialize and Serialize for Vector3
This commit is contained in:
parent
b2f627d517
commit
e02f05825f
@ -6,6 +6,7 @@ edition.workspace = true
|
||||
[dependencies]
|
||||
pumpkin-nbt = { path = "../pumpkin-nbt" }
|
||||
serde.workspace = true
|
||||
bytes.workspace = true
|
||||
uuid.workspace = true
|
||||
num-traits.workspace = true
|
||||
num-derive.workspace = true
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use bytes::BufMut;
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
use num_traits::Float;
|
||||
@ -117,8 +118,114 @@ pub trait Math:
|
||||
+ Sized
|
||||
{
|
||||
}
|
||||
impl Math for i16 {}
|
||||
impl Math for f64 {}
|
||||
impl Math for f32 {}
|
||||
impl Math for i32 {}
|
||||
impl Math for i64 {}
|
||||
impl Math for u8 {}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for Vector3<f32> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
struct Vector3Visitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for Vector3Visitor {
|
||||
type Value = Vector3<f32>;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid Vector<32>")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: serde::de::SeqAccess<'de>,
|
||||
{
|
||||
if let Some(x) = seq.next_element::<f32>()? {
|
||||
if let Some(y) = seq.next_element::<f32>()? {
|
||||
if let Some(z) = seq.next_element::<f32>()? {
|
||||
return Ok(Vector3::new(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(serde::de::Error::custom("Failed to read Vector<f32>"))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(Vector3Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for Vector3<f64> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
struct Vector3Visitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for Vector3Visitor {
|
||||
type Value = Vector3<f64>;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid Vector<f64>")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: serde::de::SeqAccess<'de>,
|
||||
{
|
||||
if let Some(x) = seq.next_element::<f64>()? {
|
||||
if let Some(y) = seq.next_element::<f64>()? {
|
||||
if let Some(z) = seq.next_element::<f64>()? {
|
||||
return Ok(Vector3::new(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(serde::de::Error::custom("Failed to read Vector<f64>"))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(Vector3Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::Serialize for Vector3<f32> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
buf.put_f32(self.x);
|
||||
buf.put_f32(self.y);
|
||||
buf.put_f32(self.z);
|
||||
serializer.serialize_bytes(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::Serialize for Vector3<f64> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
buf.put_f64(self.x);
|
||||
buf.put_f64(self.y);
|
||||
buf.put_f64(self.z);
|
||||
serializer.serialize_bytes(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::Serialize for Vector3<i16> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
buf.put_i16(self.x);
|
||||
buf.put_i16(self.y);
|
||||
buf.put_i16(self.z);
|
||||
serializer.serialize_bytes(&buf)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use pumpkin_core::math::vector3::Vector3;
|
||||
use pumpkin_macros::client_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
@ -10,7 +11,7 @@ pub struct CDamageEvent {
|
||||
source_type_id: VarInt,
|
||||
source_cause_id: VarInt,
|
||||
source_direct_id: VarInt,
|
||||
source_position: Option<(f64, f64, f64)>,
|
||||
source_position: Option<Vector3<f64>>,
|
||||
}
|
||||
|
||||
impl CDamageEvent {
|
||||
@ -19,7 +20,7 @@ impl CDamageEvent {
|
||||
source_type_id: VarInt,
|
||||
source_cause_id: Option<VarInt>,
|
||||
source_direct_id: Option<VarInt>,
|
||||
source_position: Option<(f64, f64, f64)>,
|
||||
source_position: Option<Vector3<f64>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
|
||||
@ -13,7 +13,7 @@ pub struct CEntityVelocity<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CEntityVelocity<'a> {
|
||||
pub fn new(entity_id: &'a VarInt, velocity_x: f32, velocity_y: f32, velocity_z: f32) -> Self {
|
||||
pub fn new(entity_id: &'a VarInt, velocity_x: f64, velocity_y: f64, velocity_z: f64) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
velocity_x: (velocity_x.clamp(-3.9, 3.9) * 8000.0) as i16,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use pumpkin_core::math::vector3::Vector3;
|
||||
use pumpkin_macros::client_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
@ -8,12 +9,8 @@ use crate::VarInt;
|
||||
pub struct CParticle<'a> {
|
||||
/// If true, particle distance increases from 256 to 65536.
|
||||
long_distance: bool,
|
||||
x: f64,
|
||||
y: f64,
|
||||
z: f64,
|
||||
offset_x: f32,
|
||||
offset_y: f32,
|
||||
offset_z: f32,
|
||||
position: Vector3<f64>,
|
||||
offset: Vector3<f64>,
|
||||
max_speed: f32,
|
||||
particle_count: i32,
|
||||
pariticle_id: VarInt,
|
||||
@ -21,15 +18,10 @@ pub struct CParticle<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CParticle<'a> {
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
long_distance: bool,
|
||||
x: f64,
|
||||
y: f64,
|
||||
z: f64,
|
||||
offset_x: f32,
|
||||
offset_y: f32,
|
||||
offset_z: f32,
|
||||
position: Vector3<f64>,
|
||||
offset: Vector3<f64>,
|
||||
max_speed: f32,
|
||||
particle_count: i32,
|
||||
pariticle_id: VarInt,
|
||||
@ -37,12 +29,8 @@ impl<'a> CParticle<'a> {
|
||||
) -> Self {
|
||||
Self {
|
||||
long_distance,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
offset_x,
|
||||
offset_y,
|
||||
offset_z,
|
||||
position,
|
||||
offset,
|
||||
max_speed,
|
||||
particle_count,
|
||||
pariticle_id,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use pumpkin_core::math::vector3::Vector3;
|
||||
use pumpkin_macros::client_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
@ -7,25 +8,15 @@ use crate::VarInt;
|
||||
#[client_packet("play:move_entity_pos")]
|
||||
pub struct CUpdateEntityPos {
|
||||
entity_id: VarInt,
|
||||
delta_x: i16,
|
||||
delta_y: i16,
|
||||
delta_z: i16,
|
||||
delta: Vector3<i16>,
|
||||
on_ground: bool,
|
||||
}
|
||||
|
||||
impl CUpdateEntityPos {
|
||||
pub fn new(
|
||||
entity_id: VarInt,
|
||||
delta_x: i16,
|
||||
delta_y: i16,
|
||||
delta_z: i16,
|
||||
on_ground: bool,
|
||||
) -> Self {
|
||||
pub fn new(entity_id: VarInt, delta: Vector3<i16>, on_ground: bool) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
delta_x,
|
||||
delta_y,
|
||||
delta_z,
|
||||
delta,
|
||||
on_ground,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use pumpkin_core::math::vector3::Vector3;
|
||||
use pumpkin_macros::client_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
@ -7,9 +8,7 @@ use crate::VarInt;
|
||||
#[client_packet("play:move_entity_pos_rot")]
|
||||
pub struct CUpdateEntityPosRot {
|
||||
entity_id: VarInt,
|
||||
delta_x: i16,
|
||||
delta_y: i16,
|
||||
delta_z: i16,
|
||||
delta: Vector3<i16>,
|
||||
yaw: u8,
|
||||
pitch: u8,
|
||||
on_ground: bool,
|
||||
@ -18,18 +17,14 @@ pub struct CUpdateEntityPosRot {
|
||||
impl CUpdateEntityPosRot {
|
||||
pub fn new(
|
||||
entity_id: VarInt,
|
||||
delta_x: i16,
|
||||
delta_y: i16,
|
||||
delta_z: i16,
|
||||
delta: Vector3<i16>,
|
||||
yaw: u8,
|
||||
pitch: u8,
|
||||
on_ground: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
delta_x,
|
||||
delta_y,
|
||||
delta_z,
|
||||
delta,
|
||||
yaw,
|
||||
pitch,
|
||||
on_ground,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use pumpkin_core::math::vector3::Vector3;
|
||||
use pumpkin_macros::server_packet;
|
||||
|
||||
use crate::{bytebuf::DeserializerError, ServerPacket, VarInt};
|
||||
@ -8,7 +9,7 @@ use crate::{bytebuf::DeserializerError, ServerPacket, VarInt};
|
||||
pub struct SInteract {
|
||||
pub entity_id: VarInt,
|
||||
pub typ: VarInt,
|
||||
pub target_position: Option<(f32, f32, f32)>,
|
||||
pub target_position: Option<Vector3<f32>>,
|
||||
pub hand: Option<VarInt>,
|
||||
pub sneaking: bool,
|
||||
}
|
||||
@ -23,12 +24,14 @@ impl ServerPacket for SInteract {
|
||||
let action = ActionType::from_i32(typ.0).ok_or(DeserializerError::Message(
|
||||
"invalid action type".to_string(),
|
||||
))?;
|
||||
let target_position: Option<(f32, f32, f32)> = match action {
|
||||
let target_position: Option<Vector3<f32>> = match action {
|
||||
ActionType::Interact => None,
|
||||
ActionType::Attack => None,
|
||||
ActionType::InteractAt => {
|
||||
Some((bytebuf.get_f32()?, bytebuf.get_f32()?, bytebuf.get_f32()?))
|
||||
}
|
||||
ActionType::InteractAt => Some(Vector3::new(
|
||||
bytebuf.get_f32()?,
|
||||
bytebuf.get_f32()?,
|
||||
bytebuf.get_f32()?,
|
||||
)),
|
||||
};
|
||||
let hand = match action {
|
||||
ActionType::Interact => Some(bytebuf.get_var_int()?),
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
use pumpkin_core::math::vector3::Vector3;
|
||||
use pumpkin_macros::server_packet;
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
#[server_packet("play:move_player_pos")]
|
||||
pub struct SPlayerPosition {
|
||||
pub x: f64,
|
||||
pub feet_y: f64,
|
||||
pub z: f64,
|
||||
pub position: Vector3<f64>,
|
||||
pub ground: bool,
|
||||
}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
use pumpkin_core::math::vector3::Vector3;
|
||||
use pumpkin_macros::server_packet;
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
#[server_packet("play:move_player_pos_rot")]
|
||||
pub struct SPlayerPositionRotation {
|
||||
pub x: f64,
|
||||
pub feet_y: f64,
|
||||
pub z: f64,
|
||||
pub position: Vector3<f64>,
|
||||
pub yaw: f32,
|
||||
pub pitch: f32,
|
||||
pub ground: bool,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use pumpkin_core::math::position::WorldPosition;
|
||||
use pumpkin_core::math::{position::WorldPosition, vector3::Vector3};
|
||||
use pumpkin_macros::server_packet;
|
||||
use serde::Deserialize;
|
||||
|
||||
@ -10,9 +10,7 @@ pub struct SUseItemOn {
|
||||
pub hand: VarInt,
|
||||
pub location: WorldPosition,
|
||||
pub face: VarInt,
|
||||
pub cursor_pos_x: f32,
|
||||
pub cursor_pos_y: f32,
|
||||
pub cursor_pos_z: f32,
|
||||
pub cursor_pos: Vector3<f32>,
|
||||
pub inside_block: bool,
|
||||
pub is_against_world_border: bool,
|
||||
pub sequence: VarInt,
|
||||
|
||||
@ -80,9 +80,9 @@ pub async fn handle_knockback(
|
||||
|
||||
let packet = &CEntityVelocity::new(
|
||||
&entity_id,
|
||||
victim_velocity.x as f32,
|
||||
victim_velocity.y as f32,
|
||||
victim_velocity.z as f32,
|
||||
victim_velocity.x,
|
||||
victim_velocity.y,
|
||||
victim_velocity.z,
|
||||
);
|
||||
let velocity = attacker_entity.velocity.load();
|
||||
attacker_entity
|
||||
@ -105,12 +105,8 @@ pub async fn spawn_sweep_particle(attacker_entity: &Entity, world: &World, pos:
|
||||
world
|
||||
.broadcast_packet_all(&CParticle::new(
|
||||
false,
|
||||
pos.x + d,
|
||||
body_y,
|
||||
pos.z + e,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
Vector3::new(pos.x + d, body_y, pos.z + e),
|
||||
Vector3::new(0.0, 0.0, 0.0),
|
||||
0.0,
|
||||
0,
|
||||
VarInt(i32::from(particle!("sweep_attack"))), // sweep
|
||||
|
||||
@ -114,18 +114,17 @@ impl Player {
|
||||
pos.clamp(-2.0E7, 2.0E7)
|
||||
}
|
||||
|
||||
pub async fn handle_position(self: &Arc<Self>, position_packet: SPlayerPosition) {
|
||||
if position_packet.x.is_nan()
|
||||
|| position_packet.feet_y.is_nan()
|
||||
|| position_packet.z.is_nan()
|
||||
{
|
||||
pub async fn handle_position(self: &Arc<Self>, packet: SPlayerPosition) {
|
||||
// y = feet Y
|
||||
let position = packet.position;
|
||||
if position.x.is_nan() || position.y.is_nan() || position.z.is_nan() {
|
||||
self.kick(TextComponent::text("Invalid movement")).await;
|
||||
return;
|
||||
}
|
||||
let position = Vector3::new(
|
||||
Self::clamp_horizontal(position_packet.x),
|
||||
Self::clamp_vertical(position_packet.feet_y),
|
||||
Self::clamp_horizontal(position_packet.z),
|
||||
Self::clamp_horizontal(position.x),
|
||||
Self::clamp_vertical(position.y),
|
||||
Self::clamp_horizontal(position.z),
|
||||
);
|
||||
let entity = &self.living_entity.entity;
|
||||
self.living_entity.set_pos(position);
|
||||
@ -135,11 +134,10 @@ impl Player {
|
||||
|
||||
entity
|
||||
.on_ground
|
||||
.store(position_packet.ground, std::sync::atomic::Ordering::Relaxed);
|
||||
.store(packet.ground, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
let entity_id = entity.entity_id;
|
||||
let Vector3 { x, y, z } = pos;
|
||||
let (last_x, last_y, last_z) = (last_pos.x, last_pos.y, last_pos.z);
|
||||
let world = &entity.world;
|
||||
|
||||
// let delta = Vector3::new(x - lastx, y - lasty, z - lastz);
|
||||
@ -160,36 +158,34 @@ impl Player {
|
||||
&[self.gameprofile.id],
|
||||
&CUpdateEntityPos::new(
|
||||
entity_id.into(),
|
||||
x.mul_add(4096.0, -(last_x * 4096.0)) as i16,
|
||||
y.mul_add(4096.0, -(last_y * 4096.0)) as i16,
|
||||
z.mul_add(4096.0, -(last_z * 4096.0)) as i16,
|
||||
position_packet.ground,
|
||||
Vector3::new(
|
||||
x.mul_add(4096.0, -(last_pos.x * 4096.0)) as i16,
|
||||
y.mul_add(4096.0, -(last_pos.y * 4096.0)) as i16,
|
||||
z.mul_add(4096.0, -(last_pos.z * 4096.0)) as i16,
|
||||
),
|
||||
packet.ground,
|
||||
),
|
||||
)
|
||||
.await;
|
||||
player_chunker::update_position(self).await;
|
||||
}
|
||||
|
||||
pub async fn handle_position_rotation(
|
||||
self: &Arc<Self>,
|
||||
position_rotation: SPlayerPositionRotation,
|
||||
) {
|
||||
if position_rotation.x.is_nan()
|
||||
|| position_rotation.feet_y.is_nan()
|
||||
|| position_rotation.z.is_nan()
|
||||
{
|
||||
pub async fn handle_position_rotation(self: &Arc<Self>, packet: SPlayerPositionRotation) {
|
||||
// y = feet Y
|
||||
let position = packet.position;
|
||||
if position.x.is_nan() || position.y.is_nan() || position.z.is_nan() {
|
||||
self.kick(TextComponent::text("Invalid movement")).await;
|
||||
return;
|
||||
}
|
||||
|
||||
if position_rotation.yaw.is_infinite() || position_rotation.pitch.is_infinite() {
|
||||
if packet.yaw.is_infinite() || packet.pitch.is_infinite() {
|
||||
self.kick(TextComponent::text("Invalid rotation")).await;
|
||||
return;
|
||||
}
|
||||
let position = Vector3::new(
|
||||
Self::clamp_horizontal(position_rotation.x),
|
||||
Self::clamp_vertical(position_rotation.feet_y),
|
||||
Self::clamp_horizontal(position_rotation.z),
|
||||
Self::clamp_horizontal(position.x),
|
||||
Self::clamp_vertical(position.y),
|
||||
Self::clamp_horizontal(position.z),
|
||||
);
|
||||
let entity = &self.living_entity.entity;
|
||||
self.living_entity.set_pos(position);
|
||||
@ -197,19 +193,17 @@ impl Player {
|
||||
let pos = entity.pos.load();
|
||||
let last_pos = self.living_entity.last_pos.load();
|
||||
|
||||
entity.on_ground.store(
|
||||
position_rotation.ground,
|
||||
std::sync::atomic::Ordering::Relaxed,
|
||||
);
|
||||
entity
|
||||
.on_ground
|
||||
.store(packet.ground, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
entity.set_rotation(
|
||||
wrap_degrees(position_rotation.yaw) % 360.0,
|
||||
wrap_degrees(position_rotation.pitch).clamp(-90.0, 90.0) % 360.0,
|
||||
wrap_degrees(packet.yaw) % 360.0,
|
||||
wrap_degrees(packet.pitch).clamp(-90.0, 90.0) % 360.0,
|
||||
);
|
||||
|
||||
let entity_id = entity.entity_id;
|
||||
let Vector3 { x, y, z } = pos;
|
||||
let (last_x, last_y, last_z) = (last_pos.x, last_pos.y, last_pos.z);
|
||||
|
||||
let yaw = modulus(entity.yaw.load() * 256.0 / 360.0, 256.0);
|
||||
let pitch = modulus(entity.pitch.load() * 256.0 / 360.0, 256.0);
|
||||
@ -235,12 +229,14 @@ impl Player {
|
||||
&[self.gameprofile.id],
|
||||
&CUpdateEntityPosRot::new(
|
||||
entity_id.into(),
|
||||
x.mul_add(4096.0, -(last_x * 4096.0)) as i16,
|
||||
y.mul_add(4096.0, -(last_y * 4096.0)) as i16,
|
||||
z.mul_add(4096.0, -(last_z * 4096.0)) as i16,
|
||||
Vector3::new(
|
||||
x.mul_add(4096.0, -(last_pos.x * 4096.0)) as i16,
|
||||
y.mul_add(4096.0, -(last_pos.y * 4096.0)) as i16,
|
||||
z.mul_add(4096.0, -(last_pos.z * 4096.0)) as i16,
|
||||
),
|
||||
yaw as u8,
|
||||
pitch as u8,
|
||||
position_rotation.ground,
|
||||
packet.ground,
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user