pub mod character;
#[cfg(feature = "item_attrs")]
#[cfg_attr(docsrs, doc(cfg(feature = "item_attrs")))]
pub mod item_attrs;
use super::{PacketError, PacketType};
use crate::protocol::HelperReadWrite;
use half::f16;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Debug, Copy, Clone, PartialEq, HelperReadWrite)]
pub struct Position {
pub rot_x: f16,
pub rot_y: f16,
pub rot_z: f16,
pub rot_w: f16,
pub pos_x: f16,
pub pos_y: f16,
pub pos_z: f16,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct EulerPosition {
pub roll: f32,
pub pitch: f32,
pub yaw: f32,
pub x: f32,
pub y: f32,
pub z: f32,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct SGValue(pub f32);
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct FunValue(pub u32);
impl HelperReadWrite for EulerPosition {
fn read(
reader: &mut (impl std::io::Read + std::io::Seek),
packet_type: PacketType,
xor: u32,
sub: u32,
) -> Result<Self, PacketError> {
let pos = Position::read(reader, packet_type, xor, sub)?;
Ok(pos.into())
}
fn write(
&self,
writer: &mut impl std::io::Write,
packet_type: PacketType,
xor: u32,
sub: u32,
) -> Result<(), PacketError> {
let pos: Position = (*self).into();
pos.write(writer, packet_type, xor, sub)
}
}
impl HelperReadWrite for SGValue {
fn read(
reader: &mut (impl std::io::Read + std::io::Seek),
_: PacketType,
_: u32,
_: u32,
) -> Result<Self, PacketError> {
let mut buf = [0u8; 4];
reader
.read_exact(&mut buf[2..4])
.map_err(|e| PacketError::ValueError {
packet_name: "SGValue",
error: e,
})?;
reader
.read_exact(&mut buf[0..2])
.map_err(|e| PacketError::ValueError {
packet_name: "SGValue",
error: e,
})?;
let value = u32::from_le_bytes(buf);
let value = value as f32 / 5.0;
Ok(Self(value))
}
fn write(
&self,
writer: &mut impl std::io::Write,
_: PacketType,
_: u32,
_: u32,
) -> Result<(), PacketError> {
let value = (self.0 * 5.0) as u32;
let buf = value.to_le_bytes();
writer
.write_all(&buf[2..4])
.map_err(|e| PacketError::ValueError {
packet_name: "SGValue",
error: e,
})?;
writer
.write_all(&buf[0..2])
.map_err(|e| PacketError::ValueError {
packet_name: "SGValue",
error: e,
})?;
Ok(())
}
}
impl HelperReadWrite for FunValue {
fn read(
reader: &mut (impl std::io::Read + std::io::Seek),
_: PacketType,
_: u32,
_: u32,
) -> Result<Self, PacketError> {
let mut buf = [0u8; 4];
reader
.read_exact(&mut buf[2..4])
.map_err(|e| PacketError::ValueError {
packet_name: "FunValue",
error: e,
})?;
reader
.read_exact(&mut buf[0..2])
.map_err(|e| PacketError::ValueError {
packet_name: "FunValue",
error: e,
})?;
let value = u32::from_le_bytes(buf);
Ok(Self(value))
}
fn write(
&self,
writer: &mut impl std::io::Write,
_: PacketType,
_: u32,
_: u32,
) -> Result<(), PacketError> {
let buf = self.0.to_le_bytes();
writer
.write_all(&buf[2..4])
.map_err(|e| PacketError::ValueError {
packet_name: "FunValue",
error: e,
})?;
writer
.write_all(&buf[0..2])
.map_err(|e| PacketError::ValueError {
packet_name: "FunValue",
error: e,
})?;
Ok(())
}
}
impl From<Position> for EulerPosition {
fn from(value: Position) -> Self {
let x = value.pos_x.to_f32();
let y = value.pos_y.to_f32();
let z = value.pos_z.to_f32();
let qx = value.rot_x.to_f32();
let qy = value.rot_y.to_f32();
let qz = value.rot_z.to_f32();
let qw = value.rot_w.to_f32();
let (roll, pitch, yaw) = quat_to_euler(qx, qy, qz, qw);
Self {
roll,
pitch,
yaw,
x,
y,
z,
}
}
}
impl From<EulerPosition> for Position {
fn from(value: EulerPosition) -> Self {
let pos_x = f16::from_f32(value.x);
let pos_y = f16::from_f32(value.y);
let pos_z = f16::from_f32(value.z);
let (qx, qy, qz, qw) = euler_to_quat(value.roll, value.pitch, value.yaw);
let rot_x = f16::from_f32(qx);
let rot_y = f16::from_f32(qy);
let rot_z = f16::from_f32(qz);
let rot_w = f16::from_f32(qw);
Self {
rot_x,
rot_y,
rot_z,
rot_w,
pos_x,
pos_y,
pos_z,
}
}
}
fn quat_to_euler(qx: f32, qy: f32, qz: f32, qw: f32) -> (f32, f32, f32) {
let sqx = qx * qx;
let sqy = qy * qy;
let sqz = qz * qz;
let sqw = qw * qw;
let unit = sqx + sqy + sqz + sqw;
let test = qx * qy + qz * qw;
if test > 0.499 * unit {
let yaw = 2.0 * qx.atan2(qw);
let pitch = std::f32::consts::PI / 2.0;
let roll = 0.0;
return (roll, pitch, yaw);
}
if test < -0.499 * unit {
let yaw = -2.0 * qx.atan2(qw);
let pitch = -std::f32::consts::PI / 2.0;
let roll = 0.0;
return (roll, pitch, yaw);
}
let yaw_y = 2.0 * (qy * qw - qx * qz);
let yaw_x = sqx - sqy - sqz + sqw;
let yaw = yaw_y.atan2(yaw_x);
let pitch = (2.0 * test / unit).asin();
let roll_y = 2.0 * (qx * qw - qy * qz);
let roll_x = -sqx + sqy - sqz + sqw;
let roll = roll_y.atan2(roll_x);
(roll, pitch, yaw)
}
fn euler_to_quat(roll: f32, pitch: f32, yaw: f32) -> (f32, f32, f32, f32) {
let (sr, cr) = (roll * 0.5).sin_cos();
let (sp, cp) = (pitch * 0.5).sin_cos();
let (sy, cy) = (yaw * 0.5).sin_cos();
let qx = sr * cp * cy - cr * sp * sy;
let qy = cr * sp * cy + sr * cp * sy;
let qz = cr * cp * sy - sr * sp * cy;
let qw = cr * cp * cy + sr * sp * sy;
(qx, qy, qz, qw)
}
impl Position {
pub fn dist(&self, o: &Self) -> f64 {
let (x, y, z): (f64, f64, f64) = (self.pos_x.into(), self.pos_y.into(), self.pos_z.into());
let (ox, oy, oz): (f64, f64, f64) = (o.pos_x.into(), o.pos_y.into(), o.pos_z.into());
f64::sqrt((ox - x).powi(2) + (oy - y).powi(2) + (oz - z).powi(2))
}
pub fn dist_2d(&self, o: &Self) -> f64 {
let (x, z): (f64, f64) = (self.pos_x.into(), self.pos_z.into());
let (ox, oz): (f64, f64) = (o.pos_x.into(), o.pos_z.into());
f64::sqrt((ox - x).powi(2) + (oz - z).powi(2))
}
}
impl EulerPosition {
pub fn dist(&self, o: &Self) -> f64 {
let (x, y, z): (f64, f64, f64) = (self.x.into(), self.y.into(), self.z.into());
let (ox, oy, oz): (f64, f64, f64) = (o.x.into(), o.y.into(), o.z.into());
f64::sqrt((ox - x).powi(2) + (oy - y).powi(2) + (oz - z).powi(2))
}
pub fn dist_2d(&self, o: &Self) -> f64 {
let (x, z): (f64, f64) = (self.x.into(), self.z.into());
let (ox, oz): (f64, f64) = (o.x.into(), o.z.into());
f64::sqrt((ox - x).powi(2) + (oz - z).powi(2))
}
}
impl Default for Position {
fn default() -> Self {
Self {
rot_x: f16::from_f32(0.0),
rot_y: f16::from_f32(0.0),
rot_z: f16::from_f32(0.0),
rot_w: f16::from_f32(1.0),
pos_x: f16::from_f32(0.0),
pos_y: f16::from_f32(0.0),
pos_z: f16::from_f32(0.0),
}
}
}