mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 22:41:30 +11:00
Replace nalgebra-glm with vek
Vek has been pleasant to use in practice. nalgebra is slow to compile and its documentation is difficult to traverse. Vek also comes with its own AABB impl, so we use that instead.
This commit is contained in:
parent
adc8a4faae
commit
620c0bf287
|
@ -24,7 +24,6 @@ flume = "0.10"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
hematite-nbt = "0.5"
|
hematite-nbt = "0.5"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
nalgebra-glm = "0.17"
|
|
||||||
num = "0.4"
|
num = "0.4"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
paste = "1"
|
paste = "1"
|
||||||
|
@ -39,6 +38,7 @@ sha2 = "0.10"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
uuid = "1"
|
uuid = "1"
|
||||||
|
vek = "0.15"
|
||||||
|
|
||||||
[dependencies.reqwest]
|
[dependencies.reqwest]
|
||||||
version = "0.11"
|
version = "0.11"
|
||||||
|
|
|
@ -7,8 +7,8 @@ use valence::client::GameMode;
|
||||||
use valence::config::{Config, ServerListPing};
|
use valence::config::{Config, ServerListPing};
|
||||||
use valence::text::Color;
|
use valence::text::Color;
|
||||||
use valence::{
|
use valence::{
|
||||||
async_trait, ChunkPos, ClientMut, DimensionId, Server, ShutdownResult, Text,
|
async_trait, ChunkPos, ClientMut, DimensionId, Server, ShutdownResult, Text, TextFormat,
|
||||||
TextFormat, WorldId, WorldsMut,
|
WorldId, WorldsMut,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() -> ShutdownResult {
|
pub fn main() -> ShutdownResult {
|
||||||
|
|
176
src/aabb.rs
176
src/aabb.rs
|
@ -1,176 +0,0 @@
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
|
|
||||||
use num::cast::AsPrimitive;
|
|
||||||
|
|
||||||
use crate::glm::{self, Number, RealNumber, TVec, TVec3};
|
|
||||||
|
|
||||||
/// An Axis-aligned bounding box in an arbitrary dimension, defined by its
|
|
||||||
/// minimum and maximum corners.
|
|
||||||
///
|
|
||||||
/// This type maintains the invariant that `min <= max` componentwise.
|
|
||||||
///
|
|
||||||
/// The generic type `T` can be an integer, which is useful for AABBs on grids.
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub struct Aabb<T, const D: usize> {
|
|
||||||
min: TVec<T, D>,
|
|
||||||
max: TVec<T, D>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Number, const D: usize> Aabb<T, D> {
|
|
||||||
pub fn new(p0: impl Into<TVec<T, D>>, p1: impl Into<TVec<T, D>>) -> Self {
|
|
||||||
let p0 = p0.into();
|
|
||||||
let p1 = p1.into();
|
|
||||||
Self {
|
|
||||||
min: glm::min2(&p0, &p1),
|
|
||||||
max: glm::max2(&p0, &p1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn point(pos: impl Into<TVec<T, D>>) -> Self {
|
|
||||||
let pos = pos.into();
|
|
||||||
Self { min: pos, max: pos }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn min(&self) -> TVec<T, D> {
|
|
||||||
self.min
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max(&self) -> TVec<T, D> {
|
|
||||||
self.max
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dimensions(&self) -> TVec<T, D> {
|
|
||||||
self.max - self.min
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Moves this AABB by some vector.
|
|
||||||
pub fn translate(&self, v: impl Into<TVec<T, D>>) -> Self {
|
|
||||||
let v = v.into();
|
|
||||||
Self {
|
|
||||||
min: self.min + v,
|
|
||||||
max: self.max + v,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculates the AABB union, which is the smallest AABB completely
|
|
||||||
/// encompassing both AABBs.
|
|
||||||
pub fn union(&self, other: Self) -> Self {
|
|
||||||
Self {
|
|
||||||
min: glm::min2(&self.min, &other.min),
|
|
||||||
max: glm::max2(&self.max, &other.max),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn collides_with_aabb(&self, other: &Self) -> bool {
|
|
||||||
let l = glm::less_than_equal(&self.min, &other.max);
|
|
||||||
let r = glm::greater_than_equal(&self.max, &other.min);
|
|
||||||
glm::all(&l.zip_map(&r, |l, r| l && r))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Number, const D: usize> Aabb<T, D>
|
|
||||||
where
|
|
||||||
i32: AsPrimitive<T>,
|
|
||||||
{
|
|
||||||
/// Returns the center (centroid) of this AABB.
|
|
||||||
pub fn center(&self) -> TVec<T, D> {
|
|
||||||
(self.min + self.max).map(|c| c / 2.as_())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: RealNumber, const D: usize> Aabb<T, D> {
|
|
||||||
/// Construct an AABB from a center (centroid) and the dimensions of the box
|
|
||||||
/// along each axis.
|
|
||||||
pub fn from_center_and_dimensions(
|
|
||||||
center: impl Into<TVec<T, D>>,
|
|
||||||
dims: impl Into<TVec<T, D>>,
|
|
||||||
) -> Self {
|
|
||||||
let half = dims.into() * T::from_subset(&0.5);
|
|
||||||
let center = center.into();
|
|
||||||
Self {
|
|
||||||
min: center - half,
|
|
||||||
max: center + half,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn collides_with_sphere(
|
|
||||||
&self,
|
|
||||||
center: impl Into<TVec<T, D>>,
|
|
||||||
radius: impl Into<T>,
|
|
||||||
) -> bool {
|
|
||||||
self.distance_to_point(center.into()) <= radius.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn distance_to_point(&self, p: impl Into<TVec<T, D>>) -> T {
|
|
||||||
let p = p.into();
|
|
||||||
glm::distance(&p, &glm::clamp_vec(&p, &self.min, &self.max))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Number> Aabb<T, 3>
|
|
||||||
where
|
|
||||||
i32: AsPrimitive<T>,
|
|
||||||
{
|
|
||||||
pub fn surface_area(&self) -> T {
|
|
||||||
let d = self.dimensions();
|
|
||||||
(d.x * d.y + d.y * d.z + d.z * d.x) * 2.as_()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: RealNumber> Aabb<T, 3> {
|
|
||||||
/// Constructs an AABB from a position and the dimensions of the box along
|
|
||||||
/// each axis. The position is the center of the bottom face of the AABB.
|
|
||||||
pub fn from_bottom_and_dimensions(
|
|
||||||
bottom: impl Into<TVec3<T>>,
|
|
||||||
dims: impl Into<TVec3<T>>,
|
|
||||||
) -> Self {
|
|
||||||
let dims = dims.into();
|
|
||||||
Self::from_center_and_dimensions(bottom, dims).translate([
|
|
||||||
T::from_subset(&0.0),
|
|
||||||
dims.y * T::from_subset(&0.5),
|
|
||||||
T::from_subset(&0.0),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Number + Default, const D: usize> Default for Aabb<T, D> {
|
|
||||||
fn default() -> Self {
|
|
||||||
let d = T::default();
|
|
||||||
Self::new([d; D], [d; D])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Number, const D: usize> PartialEq for Aabb<T, D> {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.min == other.min && self.max == other.max
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Number + Eq, const D: usize> Eq for Aabb<T, D> {}
|
|
||||||
|
|
||||||
impl<T: Number, const D: usize> PartialOrd for Aabb<T, D> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
match self.min.partial_cmp(&other.min) {
|
|
||||||
Some(Ordering::Equal) => self.max.partial_cmp(&other.max),
|
|
||||||
ord => return ord,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Number + Hash, const D: usize> Hash for Aabb<T, D> {
|
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
||||||
self.min.hash(state);
|
|
||||||
self.max.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: impl Ord for Aabb
|
|
||||||
//impl<T: Number + Ord, const D: usize> Ord for Aabb<T, D> {
|
|
||||||
// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
||||||
// match self.min.cmp(&other.min) {
|
|
||||||
// Ordering::Equal => self.max.cmp(&other.max),
|
|
||||||
// ord => ord,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
12
src/chunk.rs
12
src/chunk.rs
|
@ -5,13 +5,12 @@ use std::io::Write;
|
||||||
use std::iter::FusedIterator;
|
use std::iter::FusedIterator;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use bitvec::bitvec;
|
|
||||||
use bitvec::vec::BitVec;
|
use bitvec::vec::BitVec;
|
||||||
use num::Integer;
|
use num::Integer;
|
||||||
use rayon::iter::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator};
|
||||||
|
use vek::Vec2;
|
||||||
|
|
||||||
use crate::block::BlockState;
|
use crate::block::BlockState;
|
||||||
use crate::glm::DVec2;
|
|
||||||
use crate::packets::play::{
|
use crate::packets::play::{
|
||||||
BlockChange, ChunkDataAndUpdateLight, ChunkDataHeightmaps, ClientPlayPacket, MultiBlockChange,
|
BlockChange, ChunkDataAndUpdateLight, ChunkDataHeightmaps, ClientPlayPacket, MultiBlockChange,
|
||||||
};
|
};
|
||||||
|
@ -292,15 +291,6 @@ impl ChunkPos {
|
||||||
pub const fn new(x: i32, z: i32) -> Self {
|
pub const fn new(x: i32, z: i32) -> Self {
|
||||||
Self { x, z }
|
Self { x, z }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the chunk position of the chunk that the given coordinates are
|
|
||||||
/// contained within.
|
|
||||||
pub fn from_xz(xz: DVec2) -> Self {
|
|
||||||
Self {
|
|
||||||
x: (xz.x / 16.0) as i32,
|
|
||||||
z: (xz.y / 16.0) as i32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(i32, i32)> for ChunkPos {
|
impl From<(i32, i32)> for ChunkPos {
|
||||||
|
|
|
@ -3,9 +3,9 @@ use std::iter::FusedIterator;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use flume::{Receiver, Sender, TrySendError};
|
use flume::{Receiver, Sender, TrySendError};
|
||||||
use glm::DVec3;
|
|
||||||
use rayon::iter::ParallelIterator;
|
use rayon::iter::ParallelIterator;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use vek::Vec3;
|
||||||
|
|
||||||
use crate::block_pos::BlockPos;
|
use crate::block_pos::BlockPos;
|
||||||
use crate::config::{
|
use crate::config::{
|
||||||
|
@ -26,9 +26,7 @@ use crate::server::ServerPacketChannels;
|
||||||
use crate::slotmap::{Key, SlotMap};
|
use crate::slotmap::{Key, SlotMap};
|
||||||
use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
|
use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
|
||||||
use crate::var_int::VarInt;
|
use crate::var_int::VarInt;
|
||||||
use crate::{
|
use crate::{ident, ChunkPos, Chunks, Entities, EntityId, Server, Text, Ticks, LIBRARY_NAMESPACE};
|
||||||
glm, ident, ChunkPos, Chunks, Entities, EntityId, Server, Text, Ticks, LIBRARY_NAMESPACE,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Clients {
|
pub struct Clients {
|
||||||
sm: SlotMap<Client>,
|
sm: SlotMap<Client>,
|
||||||
|
@ -117,8 +115,8 @@ pub struct Client {
|
||||||
username: String,
|
username: String,
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
on_ground: bool,
|
on_ground: bool,
|
||||||
new_position: DVec3,
|
new_position: Vec3<f64>,
|
||||||
old_position: DVec3,
|
old_position: Vec3<f64>,
|
||||||
/// Measured in degrees
|
/// Measured in degrees
|
||||||
yaw: f32,
|
yaw: f32,
|
||||||
/// Measured in degrees
|
/// Measured in degrees
|
||||||
|
@ -181,8 +179,8 @@ impl Client {
|
||||||
username,
|
username,
|
||||||
uuid,
|
uuid,
|
||||||
on_ground: false,
|
on_ground: false,
|
||||||
new_position: DVec3::default(),
|
new_position: Vec3::default(),
|
||||||
old_position: DVec3::default(),
|
old_position: Vec3::default(),
|
||||||
yaw: 0.0,
|
yaw: 0.0,
|
||||||
pitch: 0.0,
|
pitch: 0.0,
|
||||||
teleported_this_tick: false,
|
teleported_this_tick: false,
|
||||||
|
@ -216,7 +214,7 @@ impl Client {
|
||||||
self.uuid
|
self.uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn position(&self) -> DVec3 {
|
pub fn position(&self) -> Vec3<f64> {
|
||||||
self.new_position
|
self.new_position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +260,7 @@ impl<'a> ClientMut<'a> {
|
||||||
ClientMut(self.0)
|
ClientMut(self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn teleport(&mut self, pos: impl Into<DVec3>, yaw: f32, pitch: f32) {
|
pub fn teleport(&mut self, pos: impl Into<Vec3<f64>>, yaw: f32, pitch: f32) {
|
||||||
self.0.new_position = pos.into();
|
self.0.new_position = pos.into();
|
||||||
self.0.yaw = yaw;
|
self.0.yaw = yaw;
|
||||||
self.0.pitch = pitch;
|
self.0.pitch = pitch;
|
||||||
|
@ -425,7 +423,10 @@ impl<'a> ClientMut<'a> {
|
||||||
.map_or(2, |s| s.view_distance)
|
.map_or(2, |s| s.view_distance)
|
||||||
.min(self.new_max_view_distance);
|
.min(self.new_max_view_distance);
|
||||||
|
|
||||||
let center = ChunkPos::from_xz(self.0.new_position.xz());
|
let center = ChunkPos::new(
|
||||||
|
(self.new_position.x / 16.0) as i32,
|
||||||
|
(self.new_position.z / 16.0) as i32,
|
||||||
|
);
|
||||||
|
|
||||||
// Send the update view position packet if the client changes the chunk section
|
// Send the update view position packet if the client changes the chunk section
|
||||||
// they're in.
|
// they're in.
|
||||||
|
@ -484,19 +485,18 @@ impl<'a> ClientMut<'a> {
|
||||||
// This is done after the chunks are loaded so that the "downloading terrain"
|
// This is done after the chunks are loaded so that the "downloading terrain"
|
||||||
// screen is closed at the appropriate time.
|
// screen is closed at the appropriate time.
|
||||||
|
|
||||||
// TODO: temporarily broken
|
if self.0.teleported_this_tick {
|
||||||
// if self.0.teleported_this_tick {
|
self.0.teleported_this_tick = false;
|
||||||
// self.0.teleported_this_tick = false;
|
|
||||||
|
|
||||||
// self.send_packet(dbg!(PlayerPositionAndLook {
|
self.send_packet(PlayerPositionAndLook {
|
||||||
// position: self.new_position,
|
position: self.new_position,
|
||||||
// yaw: self.yaw,
|
yaw: self.yaw,
|
||||||
// pitch: self.pitch,
|
pitch: self.pitch,
|
||||||
// flags: PlayerPositionAndLookFlags::new(false, false, false, false, false),
|
flags: PlayerPositionAndLookFlags::new(false, false, false, false, false),
|
||||||
// teleport_id: VarInt((self.teleport_id_counter - 1) as i32),
|
teleport_id: VarInt((self.teleport_id_counter - 1) as i32),
|
||||||
// dismount_vehicle: false,
|
dismount_vehicle: false,
|
||||||
// }));
|
});
|
||||||
// }
|
}
|
||||||
|
|
||||||
let mut entities_to_unload = Vec::new();
|
let mut entities_to_unload = Vec::new();
|
||||||
|
|
||||||
|
@ -504,9 +504,7 @@ impl<'a> ClientMut<'a> {
|
||||||
// longer visible.
|
// longer visible.
|
||||||
self.0.loaded_entities.retain(|&id| {
|
self.0.loaded_entities.retain(|&id| {
|
||||||
if let Some(entity) = entities.get(id) {
|
if let Some(entity) = entities.get(id) {
|
||||||
if glm::distance(&self.0.new_position, &entity.position())
|
if self.0.new_position.distance(entity.position()) <= view_dist as f64 * 16.0 {
|
||||||
<= view_dist as f64 * 16.0
|
|
||||||
{
|
|
||||||
todo!("update entity");
|
todo!("update entity");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -524,7 +522,7 @@ impl<'a> ClientMut<'a> {
|
||||||
|
|
||||||
// Spawn new entities within the view distance.
|
// Spawn new entities within the view distance.
|
||||||
for (id, entity) in entities.iter() {
|
for (id, entity) in entities.iter() {
|
||||||
if glm::distance(&self.position(), &entity.position()) <= view_dist as f64 * 16.0
|
if self.position().distance(entity.position()) <= view_dist as f64 * 16.0
|
||||||
&& entity.typ() != EntityType::Marker
|
&& entity.typ() != EntityType::Marker
|
||||||
&& self.0.loaded_entities.insert(id)
|
&& self.0.loaded_entities.insert(id)
|
||||||
{
|
{
|
||||||
|
@ -548,7 +546,7 @@ impl<'a> ClientMut<'a> {
|
||||||
|
|
||||||
fn handle_movement_packet(
|
fn handle_movement_packet(
|
||||||
client: &mut Client,
|
client: &mut Client,
|
||||||
new_position: DVec3,
|
new_position: Vec3<f64>,
|
||||||
new_yaw: f32,
|
new_yaw: f32,
|
||||||
new_pitch: f32,
|
new_pitch: f32,
|
||||||
new_on_ground: bool,
|
new_on_ground: bool,
|
||||||
|
@ -556,8 +554,8 @@ impl<'a> ClientMut<'a> {
|
||||||
if client.pending_teleports == 0 {
|
if client.pending_teleports == 0 {
|
||||||
let event = Event::Movement {
|
let event = Event::Movement {
|
||||||
position: client.new_position,
|
position: client.new_position,
|
||||||
yaw_degrees: client.yaw,
|
yaw: client.yaw,
|
||||||
pitch_degrees: client.pitch,
|
pitch: client.pitch,
|
||||||
on_ground: client.on_ground,
|
on_ground: client.on_ground,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -693,9 +691,9 @@ pub enum Event {
|
||||||
/// The client has moved. The values in this variant are the previous
|
/// The client has moved. The values in this variant are the previous
|
||||||
/// position and look.
|
/// position and look.
|
||||||
Movement {
|
Movement {
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
yaw_degrees: f32,
|
yaw: f32,
|
||||||
pitch_degrees: f32,
|
pitch: f32,
|
||||||
on_ground: bool,
|
on_ground: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,18 +9,17 @@ use std::ops::Deref;
|
||||||
use bitfield_struct::bitfield;
|
use bitfield_struct::bitfield;
|
||||||
use rayon::iter::ParallelIterator;
|
use rayon::iter::ParallelIterator;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use vek::{Aabb, Vec3};
|
||||||
|
|
||||||
use crate::byte_angle::ByteAngle;
|
use crate::byte_angle::ByteAngle;
|
||||||
use crate::chunk::ChunkPos;
|
|
||||||
use crate::glm::{DVec3, I16Vec3, Vec3};
|
|
||||||
use crate::packets::play::{
|
use crate::packets::play::{
|
||||||
ClientPlayPacket, EntityMetadata, SpawnEntity, SpawnExperienceOrb, SpawnLivingEntity,
|
ClientPlayPacket, EntityMetadata, SpawnEntity, SpawnExperienceOrb, SpawnLivingEntity,
|
||||||
SpawnPainting, SpawnPlayer,
|
SpawnPainting, SpawnPlayer,
|
||||||
};
|
};
|
||||||
use crate::protocol::ReadToEnd;
|
use crate::protocol::ReadToEnd;
|
||||||
use crate::slotmap::{Key, SlotMap};
|
use crate::slotmap::{Key, SlotMap};
|
||||||
|
use crate::util::aabb_from_bottom_and_size;
|
||||||
use crate::var_int::VarInt;
|
use crate::var_int::VarInt;
|
||||||
use crate::{Aabb, WorldId};
|
|
||||||
|
|
||||||
pub struct Entities {
|
pub struct Entities {
|
||||||
sm: SlotMap<Entity>,
|
sm: SlotMap<Entity>,
|
||||||
|
@ -103,8 +102,8 @@ impl<'a> EntitiesMut<'a> {
|
||||||
let entity = EntityId(self.0.sm.insert(Entity {
|
let entity = EntityId(self.0.sm.insert(Entity {
|
||||||
flags: EntityFlags(0),
|
flags: EntityFlags(0),
|
||||||
meta: EntityMeta::new(EntityType::Marker),
|
meta: EntityMeta::new(EntityType::Marker),
|
||||||
new_position: DVec3::default(),
|
new_position: Vec3::default(),
|
||||||
old_position: DVec3::default(),
|
old_position: Vec3::default(),
|
||||||
yaw: 0.0,
|
yaw: 0.0,
|
||||||
pitch: 0.0,
|
pitch: 0.0,
|
||||||
head_yaw: 0.0,
|
head_yaw: 0.0,
|
||||||
|
@ -181,13 +180,13 @@ impl EntityId {
|
||||||
pub struct Entity {
|
pub struct Entity {
|
||||||
flags: EntityFlags,
|
flags: EntityFlags,
|
||||||
meta: EntityMeta,
|
meta: EntityMeta,
|
||||||
new_position: DVec3,
|
new_position: Vec3<f64>,
|
||||||
old_position: DVec3,
|
old_position: Vec3<f64>,
|
||||||
yaw: f32,
|
yaw: f32,
|
||||||
pitch: f32,
|
pitch: f32,
|
||||||
head_yaw: f32,
|
head_yaw: f32,
|
||||||
head_pitch: f32,
|
head_pitch: f32,
|
||||||
velocity: Vec3,
|
velocity: Vec3<f32>,
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,13 +229,13 @@ impl Entity {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the position of this entity in the world it inhabits.
|
/// Returns the position of this entity in the world it inhabits.
|
||||||
pub fn position(&self) -> DVec3 {
|
pub fn position(&self) -> Vec3<f64> {
|
||||||
self.new_position
|
self.new_position
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the position of this entity as it existed at the end of the
|
/// Returns the position of this entity as it existed at the end of the
|
||||||
/// previous tick.
|
/// previous tick.
|
||||||
pub fn old_position(&self) -> DVec3 {
|
pub fn old_position(&self) -> Vec3<f64> {
|
||||||
self.old_position
|
self.old_position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +260,7 @@ impl Entity {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the velocity of this entity in meters per second.
|
/// Gets the velocity of this entity in meters per second.
|
||||||
pub fn velocity(&self) -> Vec3 {
|
pub fn velocity(&self) -> Vec3<f32> {
|
||||||
self.velocity
|
self.velocity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +368,7 @@ impl Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hitbox(&self) -> Aabb<f64, 3> {
|
pub fn hitbox(&self) -> Aabb<f64> {
|
||||||
let dims = match &self.meta {
|
let dims = match &self.meta {
|
||||||
EntityMeta::AreaEffectCloud(e) => [
|
EntityMeta::AreaEffectCloud(e) => [
|
||||||
e.get_radius() as f64 * 2.0,
|
e.get_radius() as f64 * 2.0,
|
||||||
|
@ -504,13 +503,13 @@ impl Entity {
|
||||||
EntityMeta::FishingBobber(_) => [0.25, 0.25, 0.25],
|
EntityMeta::FishingBobber(_) => [0.25, 0.25, 0.25],
|
||||||
};
|
};
|
||||||
|
|
||||||
Aabb::from_bottom_and_dimensions(self.new_position, dims)
|
aabb_from_bottom_and_size(self.new_position, dims.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn velocity_to_packet_units(vel: Vec3) -> I16Vec3 {
|
fn velocity_to_packet_units(vel: Vec3<f32>) -> Vec3<i16> {
|
||||||
// The saturating cast to i16 is desirable.
|
// The saturating cast to i16 is desirable.
|
||||||
vel.map(|v| (v * 400.0) as i16)
|
(vel * 400.0).as_()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EntityMut<'a> {
|
impl<'a> EntityMut<'a> {
|
||||||
|
@ -534,7 +533,7 @@ impl<'a> EntityMut<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the position of this entity in the world it inhabits.
|
/// Sets the position of this entity in the world it inhabits.
|
||||||
pub fn set_position(&mut self, pos: impl Into<DVec3>) {
|
pub fn set_position(&mut self, pos: impl Into<Vec3<f64>>) {
|
||||||
self.0.new_position = pos.into();
|
self.0.new_position = pos.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,9 +569,10 @@ impl<'a> EntityMut<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_velocity(&mut self, velocity: Vec3) {
|
pub fn set_velocity(&mut self, velocity: impl Into<Vec3<f32>>) {
|
||||||
self.0.velocity = velocity;
|
let new_vel = velocity.into();
|
||||||
if velocity_to_packet_units(self.velocity) != velocity_to_packet_units(velocity) {
|
self.0.velocity = new_vel;
|
||||||
|
if velocity_to_packet_units(self.velocity) != velocity_to_packet_units(new_vel) {
|
||||||
self.0.flags.set_velocity_modified(true);
|
self.0.flags.set_velocity_modified(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
// missing_docs
|
// missing_docs
|
||||||
)]
|
)]
|
||||||
|
|
||||||
mod aabb;
|
|
||||||
pub mod block;
|
pub mod block;
|
||||||
mod block_pos;
|
mod block_pos;
|
||||||
mod byte_angle;
|
mod byte_angle;
|
||||||
|
@ -27,7 +26,6 @@ mod var_int;
|
||||||
mod var_long;
|
mod var_long;
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
|
||||||
pub use aabb::Aabb;
|
|
||||||
pub use async_trait::async_trait;
|
pub use async_trait::async_trait;
|
||||||
pub use block_pos::BlockPos;
|
pub use block_pos::BlockPos;
|
||||||
pub use chunk::{Chunk, ChunkPos, Chunks, ChunksMut};
|
pub use chunk::{Chunk, ChunkPos, Chunks, ChunksMut};
|
||||||
|
@ -39,7 +37,7 @@ pub use server::{start_server, NewClientData, Server, ShutdownResult};
|
||||||
pub use text::{Text, TextFormat};
|
pub use text::{Text, TextFormat};
|
||||||
pub use uuid::Uuid;
|
pub use uuid::Uuid;
|
||||||
pub use world::{WorldId, WorldMut, WorldRef, Worlds, WorldsMut};
|
pub use world::{WorldId, WorldMut, WorldRef, Worlds, WorldsMut};
|
||||||
pub use {nalgebra_glm as glm, nbt, uuid};
|
pub use {nbt, uuid, vek};
|
||||||
|
|
||||||
/// The Minecraft protocol version that this library targets.
|
/// The Minecraft protocol version that this library targets.
|
||||||
pub const PROTOCOL_VERSION: i32 = 758;
|
pub const PROTOCOL_VERSION: i32 = 758;
|
||||||
|
|
|
@ -13,10 +13,10 @@ use num::{One, Zero};
|
||||||
use paste::paste;
|
use paste::paste;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use vek::{Vec2, Vec3};
|
||||||
|
|
||||||
use crate::block_pos::BlockPos;
|
use crate::block_pos::BlockPos;
|
||||||
use crate::byte_angle::ByteAngle;
|
use crate::byte_angle::ByteAngle;
|
||||||
use crate::glm::{DVec3, I16Vec3, Vec3};
|
|
||||||
use crate::identifier::Identifier;
|
use crate::identifier::Identifier;
|
||||||
use crate::protocol::{BoundedArray, BoundedInt, BoundedString, Decode, Encode, Nbt, ReadToEnd};
|
use crate::protocol::{BoundedArray, BoundedInt, BoundedString, Decode, Encode, Nbt, ReadToEnd};
|
||||||
use crate::var_int::VarInt;
|
use crate::var_int::VarInt;
|
||||||
|
@ -445,18 +445,18 @@ pub mod play {
|
||||||
entity_id: VarInt,
|
entity_id: VarInt,
|
||||||
object_uuid: Uuid,
|
object_uuid: Uuid,
|
||||||
typ: VarInt,
|
typ: VarInt,
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
pitch: ByteAngle,
|
pitch: ByteAngle,
|
||||||
yaw: ByteAngle,
|
yaw: ByteAngle,
|
||||||
data: i32,
|
data: i32,
|
||||||
velocity: I16Vec3,
|
velocity: Vec3<i16>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def_struct! {
|
def_struct! {
|
||||||
SpawnExperienceOrb 0x01 {
|
SpawnExperienceOrb 0x01 {
|
||||||
entity_id: VarInt,
|
entity_id: VarInt,
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
count: i16,
|
count: i16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -466,11 +466,11 @@ pub mod play {
|
||||||
entity_id: VarInt,
|
entity_id: VarInt,
|
||||||
entity_uuid: Uuid,
|
entity_uuid: Uuid,
|
||||||
typ: VarInt,
|
typ: VarInt,
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
yaw: ByteAngle,
|
yaw: ByteAngle,
|
||||||
pitch: ByteAngle,
|
pitch: ByteAngle,
|
||||||
head_pitch: ByteAngle,
|
head_pitch: ByteAngle,
|
||||||
velocity: I16Vec3,
|
velocity: Vec3<i16>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +497,7 @@ pub mod play {
|
||||||
SpawnPlayer 0x04 {
|
SpawnPlayer 0x04 {
|
||||||
entity_id: VarInt,
|
entity_id: VarInt,
|
||||||
player_uuid: Uuid,
|
player_uuid: Uuid,
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
yaw: ByteAngle,
|
yaw: ByteAngle,
|
||||||
pitch: ByteAngle,
|
pitch: ByteAngle,
|
||||||
}
|
}
|
||||||
|
@ -966,7 +966,7 @@ pub mod play {
|
||||||
|
|
||||||
def_struct! {
|
def_struct! {
|
||||||
PlayerPositionAndLook 0x38 {
|
PlayerPositionAndLook 0x38 {
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
yaw: f32,
|
yaw: f32,
|
||||||
pitch: f32,
|
pitch: f32,
|
||||||
flags: PlayerPositionAndLookFlags,
|
flags: PlayerPositionAndLookFlags,
|
||||||
|
@ -1290,7 +1290,7 @@ pub mod play {
|
||||||
|
|
||||||
def_struct! {
|
def_struct! {
|
||||||
InteractAtData {
|
InteractAtData {
|
||||||
target: Vec3,
|
target: Vec3<f64>,
|
||||||
hand: Hand,
|
hand: Hand,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1317,7 +1317,7 @@ pub mod play {
|
||||||
|
|
||||||
def_struct! {
|
def_struct! {
|
||||||
PlayerPosition 0x11 {
|
PlayerPosition 0x11 {
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
on_ground: bool,
|
on_ground: bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1325,7 +1325,7 @@ pub mod play {
|
||||||
def_struct! {
|
def_struct! {
|
||||||
PlayerPositionAndRotation 0x12 {
|
PlayerPositionAndRotation 0x12 {
|
||||||
// Absolute position
|
// Absolute position
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
/// Absolute rotation on X axis in degrees.
|
/// Absolute rotation on X axis in degrees.
|
||||||
yaw: f32,
|
yaw: f32,
|
||||||
/// Absolute rotation on Y axis in degrees.
|
/// Absolute rotation on Y axis in degrees.
|
||||||
|
@ -1353,7 +1353,7 @@ pub mod play {
|
||||||
def_struct! {
|
def_struct! {
|
||||||
VehicleMoveServerbound 0x15 {
|
VehicleMoveServerbound 0x15 {
|
||||||
/// Absolute position
|
/// Absolute position
|
||||||
position: DVec3,
|
position: Vec3<f64>,
|
||||||
/// Degrees
|
/// Degrees
|
||||||
yaw: f32,
|
yaw: f32,
|
||||||
/// Degrees
|
/// Degrees
|
||||||
|
@ -1669,7 +1669,7 @@ pub mod play {
|
||||||
hand: Hand,
|
hand: Hand,
|
||||||
location: BlockPos,
|
location: BlockPos,
|
||||||
face: BlockFace,
|
face: BlockFace,
|
||||||
cursor_pos: Vec3,
|
cursor_pos: Vec3<f64>,
|
||||||
head_inside_block: bool,
|
head_inside_block: bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ use anyhow::{anyhow, ensure, Context};
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use bitvec::prelude::*;
|
use bitvec::prelude::*;
|
||||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use nalgebra_glm::{Number, TVec};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use vek::{Vec2, Vec3, Vec4};
|
||||||
|
|
||||||
use crate::var_int::VarInt;
|
use crate::var_int::VarInt;
|
||||||
use crate::EntityId;
|
use crate::EntityId;
|
||||||
|
@ -372,15 +372,50 @@ impl<T: Decode, const N: usize> Decode for [T; N] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Encode, const N: usize> Encode for TVec<T, N> {
|
impl<T: Encode> Encode for Vec2<T> {
|
||||||
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||||
encode_array_bounded(self.as_slice(), N, N, w)
|
self.x.encode(w)?;
|
||||||
|
self.y.encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Decode + Number, const N: usize> Decode for TVec<T, N> {
|
impl<T: Encode> Encode for Vec3<T> {
|
||||||
|
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||||
|
self.x.encode(w)?;
|
||||||
|
self.y.encode(w)?;
|
||||||
|
self.z.encode(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Encode> Encode for Vec4<T> {
|
||||||
|
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
|
||||||
|
self.x.encode(w)?;
|
||||||
|
self.y.encode(w)?;
|
||||||
|
self.z.encode(w)?;
|
||||||
|
self.w.encode(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Decode> Decode for Vec2<T> {
|
||||||
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||||
Ok(<[T; N]>::decode(r)?.into())
|
Ok(Vec2::new(T::decode(r)?, T::decode(r)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Decode> Decode for Vec3<T> {
|
||||||
|
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||||
|
Ok(Vec3::new(T::decode(r)?, T::decode(r)?, T::decode(r)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Decode> Decode for Vec4<T> {
|
||||||
|
fn decode(r: &mut impl Read) -> anyhow::Result<Self> {
|
||||||
|
Ok(Vec4::new(
|
||||||
|
T::decode(r)?,
|
||||||
|
T::decode(r)?,
|
||||||
|
T::decode(r)?,
|
||||||
|
T::decode(r)?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
src/util.rs
27
src/util.rs
|
@ -1,5 +1,9 @@
|
||||||
use std::iter::FusedIterator;
|
use std::iter::FusedIterator;
|
||||||
|
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
use num::Float;
|
||||||
|
use vek::{Aabb, Extent3, Vec3};
|
||||||
|
|
||||||
use crate::ChunkPos;
|
use crate::ChunkPos;
|
||||||
|
|
||||||
/// Returns true if the given string meets the criteria for a valid Minecraft
|
/// Returns true if the given string meets the criteria for a valid Minecraft
|
||||||
|
@ -26,3 +30,26 @@ pub fn is_chunk_in_view_distance(center: ChunkPos, other: ChunkPos, distance: u8
|
||||||
(center.x as f64 - other.x as f64).powi(2) + (center.z as f64 - other.z as f64).powi(2)
|
(center.x as f64 - other.x as f64).powi(2) + (center.z as f64 - other.z as f64).powi(2)
|
||||||
<= (distance as f64 + EXTRA_RADIUS as f64).powi(2)
|
<= (distance as f64 + EXTRA_RADIUS as f64).powi(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn aabb_from_bottom_and_size<T>(bottom: Vec3<T>, size: Vec3<T>) -> Aabb<T>
|
||||||
|
where
|
||||||
|
T: Float + 'static,
|
||||||
|
f64: AsPrimitive<T>,
|
||||||
|
{
|
||||||
|
let aabb = Aabb {
|
||||||
|
min: Vec3::new(
|
||||||
|
bottom.x - size.x / 2.0.as_(),
|
||||||
|
bottom.y,
|
||||||
|
bottom.z - size.z / 2.0.as_(),
|
||||||
|
),
|
||||||
|
max: Vec3::new(
|
||||||
|
bottom.x + size.x / 2.0.as_(),
|
||||||
|
bottom.y,
|
||||||
|
bottom.z + size.z / 2.0.as_(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
debug_assert!(aabb.is_valid());
|
||||||
|
|
||||||
|
aabb
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue