1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 06:16:04 +00:00

port aabb

This commit is contained in:
mat 2022-06-26 00:34:45 -05:00
parent 8bc4e8bf3b
commit bf4fd29e7f
14 changed files with 520 additions and 40 deletions

View file

@ -1,6 +1,6 @@
use crate::{Account, Player};
use azalea_auth::game_profile::GameProfile;
use azalea_core::{ChunkPos, EntityPos, PositionDelta, PositionDeltaTrait, ResourceLocation};
use azalea_core::{ChunkPos, PositionDelta, PositionDeltaTrait, ResourceLocation, Vec3};
use azalea_entity::Entity;
use azalea_protocol::{
connect::{GameConnection, HandshakeConnection},
@ -277,7 +277,7 @@ impl Client {
*dimension_lock = Some(Dimension::new(16, height, min_y));
let entity =
Entity::new(p.player_id, client.game_profile.uuid, EntityPos::default());
Entity::new(p.player_id, client.game_profile.uuid, Vec3::default());
dimension_lock
.as_mut()
.expect(
@ -400,7 +400,7 @@ impl Client {
player_entity.set_rotation(y_rot, x_rot);
// TODO: minecraft sets "xo", "yo", and "zo" here but idk what that means
// so investigate that ig
let new_pos = EntityPos {
let new_pos = Vec3 {
x: new_pos_x,
y: new_pos_y,
z: new_pos_z,
@ -515,7 +515,7 @@ impl Client {
dimension.move_entity(
p.id,
EntityPos {
Vec3 {
x: p.x,
y: p.y,
z: p.z,
@ -528,13 +528,13 @@ impl Client {
GamePacket::ClientboundRotateHeadPacket(_p) => {
// println!("Got rotate head packet {:?}", p);
}
GamePacket::ClientboundMoveEntityPosPacket(p) => {
GamePacket::ClientboundMoveVec3Packet(p) => {
let mut dimension_lock = client.dimension.lock()?;
let dimension = dimension_lock.as_mut().unwrap();
dimension.move_entity_with_delta(p.entity_id, &p.delta)?;
}
GamePacket::ClientboundMoveEntityPosRotPacket(p) => {
GamePacket::ClientboundMoveVec3RotPacket(p) => {
let mut dimension_lock = client.dimension.lock()?;
let dimension = dimension_lock.as_mut().unwrap();

View file

@ -1,10 +1,10 @@
use crate::Client;
use azalea_core::EntityPos;
use azalea_core::Vec3;
use azalea_protocol::packets::game::serverbound_move_player_packet_pos_rot::ServerboundMovePlayerPacketPosRot;
impl Client {
/// Set the client's position to the given coordinates.
pub async fn move_to(&mut self, new_pos: EntityPos) -> Result<(), String> {
pub async fn move_to(&mut self, new_pos: Vec3) -> Result<(), String> {
{
let mut dimension_lock = self.dimension.lock().unwrap();
let dimension = dimension_lock.as_mut().unwrap();

View file

@ -1,4 +1,4 @@
use crate::EntityPos;
use crate::Vec3;
pub use azalea_buf::McBuf;
pub trait PositionDeltaTrait {
@ -57,9 +57,9 @@ impl PositionDeltaTrait for PositionDelta8 {
}
}
impl EntityPos {
pub fn with_delta(&self, delta: &dyn PositionDeltaTrait) -> EntityPos {
EntityPos {
impl Vec3 {
pub fn with_delta(&self, delta: &dyn PositionDeltaTrait) -> Vec3 {
Vec3 {
x: self.x + delta.x(),
y: self.y + delta.y(),
z: self.z + delta.z(),

View file

@ -9,6 +9,12 @@ pub trait PositionXYZ<T> {
fn add_x(&self, n: T) -> Self;
fn add_y(&self, n: T) -> Self;
fn add_z(&self, n: T) -> Self;
fn add(&self, x: T, y: T, z: T) -> Self
where
Self: Sized,
{
self.add_x(x).add_y(y).add_z(z)
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
@ -123,30 +129,31 @@ pub struct GlobalPos {
pub dimension: ResourceLocation,
}
/// An exact point in the world.
#[derive(Debug, Clone, Copy, Default)]
pub struct EntityPos {
pub struct Vec3 {
pub x: f64,
pub y: f64,
pub z: f64,
}
impl PositionXYZ<f64> for EntityPos {
impl PositionXYZ<f64> for Vec3 {
fn add_x(&self, n: f64) -> Self {
EntityPos {
Vec3 {
x: self.x + n,
y: self.y,
z: self.z,
}
}
fn add_y(&self, n: f64) -> Self {
EntityPos {
Vec3 {
x: self.x,
y: self.y + n,
z: self.z,
}
}
fn add_z(&self, n: f64) -> Self {
EntityPos {
Vec3 {
x: self.x,
y: self.y,
z: self.z + n,
@ -208,8 +215,8 @@ impl From<&ChunkBlockPos> for ChunkSectionBlockPos {
}
}
}
impl From<&EntityPos> for BlockPos {
fn from(pos: &EntityPos) -> Self {
impl From<&Vec3> for BlockPos {
fn from(pos: &Vec3) -> Self {
BlockPos {
x: pos.x.floor() as i32,
y: pos.y.floor() as i32,
@ -218,8 +225,8 @@ impl From<&EntityPos> for BlockPos {
}
}
impl From<&EntityPos> for ChunkPos {
fn from(pos: &EntityPos) -> Self {
impl From<&Vec3> for ChunkPos {
fn from(pos: &Vec3) -> Self {
ChunkPos::from(&BlockPos::from(pos))
}
}
@ -302,7 +309,7 @@ mod tests {
#[test]
fn test_from_entity_pos_to_block_pos() {
let entity_pos = EntityPos {
let entity_pos = Vec3 {
x: 31.5,
y: 80.0,
z: -16.1,
@ -313,7 +320,7 @@ mod tests {
#[test]
fn test_from_entity_pos_to_chunk_pos() {
let entity_pos = EntityPos {
let entity_pos = Vec3 {
x: 31.5,
y: 80.0,
z: -16.1,

View file

@ -1,7 +1,7 @@
mod data;
mod physics;
use azalea_core::{EntityPos, PositionDelta};
use azalea_core::{PositionDelta, Vec3};
pub use data::*;
use uuid::Uuid;
@ -11,9 +11,9 @@ pub struct Entity {
pub id: u32,
pub uuid: Uuid,
/// The position of the entity right now.
pos: EntityPos,
pos: Vec3,
/// The position of the entity last tick.
pub old_pos: EntityPos,
pub old_pos: Vec3,
pub delta: PositionDelta,
pub x_rot: f32,
@ -21,7 +21,7 @@ pub struct Entity {
}
impl Entity {
pub fn new(id: u32, uuid: Uuid, pos: EntityPos) -> Self {
pub fn new(id: u32, uuid: Uuid, pos: Vec3) -> Self {
Self {
id,
uuid,
@ -33,13 +33,13 @@ impl Entity {
}
}
pub fn pos(&self) -> &EntityPos {
pub fn pos(&self) -> &Vec3 {
&self.pos
}
/// Sets the position of the entity. This doesn't update the cache in
/// azalea-world, and should only be used within azalea-world!
pub fn unsafe_move(&mut self, new_pos: EntityPos) {
pub fn unsafe_move(&mut self, new_pos: Vec3) {
self.pos = new_pos;
}

View file

@ -0,0 +1,440 @@
use crate::physics::BlockHitResult;
use azalea_core::{BlockPos, Direction, PositionXYZ, Vec3};
pub const EPSILON: f64 = 1.0E-7;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct AABB {
pub min_x: f64,
pub min_y: f64,
pub min_z: f64,
pub max_x: f64,
pub max_y: f64,
pub max_z: f64,
}
impl AABB {
pub fn contract(&mut self, x: f64, y: f64, z: f64) -> AABB {
let mut min_x = self.min_x;
let mut min_y = self.min_y;
let mut min_z = self.min_z;
let mut max_x = self.max_x;
let mut max_y = self.max_y;
let mut max_z = self.max_z;
if x < 0.0 {
min_x -= x;
} else if x > 0.0 {
max_x -= x;
}
if y < 0.0 {
min_y -= y;
} else if y > 0.0 {
max_y -= y;
}
if z < 0.0 {
min_z -= z;
} else if z > 0.0 {
max_z -= z;
}
AABB {
min_x,
min_y,
min_z,
max_x,
max_y,
max_z,
}
}
pub fn expand_towards(&mut self, x: f64, y: f64, z: f64) -> AABB {
let mut min_x = self.min_x;
let mut min_y = self.min_y;
let mut min_z = self.min_z;
let mut max_x = self.max_x;
let mut max_y = self.max_y;
let mut max_z = self.max_z;
if x < 0.0 {
min_x += x;
} else if x > 0.0 {
max_x += x;
}
if y < 0.0 {
min_y += y;
} else if y > 0.0 {
max_y += y;
}
if z < 0.0 {
min_z += z;
} else if z > 0.0 {
max_z += z;
}
AABB {
min_x,
min_y,
min_z,
max_x,
max_y,
max_z,
}
}
pub fn inflate(&mut self, x: f64, y: f64, z: f64) -> AABB {
let min_x = self.min_x - x;
let min_y = self.min_y - y;
let min_z = self.min_z - z;
let max_x = self.max_x + x;
let max_y = self.max_y + y;
let max_z = self.max_z + z;
AABB {
min_x,
min_y,
min_z,
max_x,
max_y,
max_z,
}
}
pub fn intersect(&self, other: &AABB) -> AABB {
let min_x = self.min_x.max(other.min_x);
let min_y = self.min_y.max(other.min_y);
let min_z = self.min_z.max(other.min_z);
let max_x = self.max_x.min(other.max_x);
let max_y = self.max_y.min(other.max_y);
let max_z = self.max_z.min(other.max_z);
AABB {
min_x,
min_y,
min_z,
max_x,
max_y,
max_z,
}
}
pub fn minmax(&self, other: &AABB) -> AABB {
let min_x = self.min_x.min(other.min_x);
let min_y = self.min_y.min(other.min_y);
let min_z = self.min_z.min(other.min_z);
let max_x = self.max_x.max(other.max_x);
let max_y = self.max_y.max(other.max_y);
let max_z = self.max_z.max(other.max_z);
AABB {
min_x,
min_y,
min_z,
max_x,
max_y,
max_z,
}
}
pub fn move_relative(&self, x: f64, y: f64, z: f64) -> AABB {
AABB {
min_x: self.min_x + x,
min_y: self.min_y + y,
min_z: self.min_z + z,
max_x: self.max_x + x,
max_y: self.max_y + y,
max_z: self.max_z + z,
}
}
pub fn intersects_aabb(&self, other: &AABB) -> bool {
self.min_x < other.max_x
&& self.max_x > other.min_x
&& self.min_y < other.max_y
&& self.max_y > other.min_y
&& self.min_z < other.max_z
&& self.max_z > other.min_z
}
pub fn intersects_vec3(&self, other: &Vec3, other2: &Vec3) -> bool {
self.intersects_aabb(&AABB {
min_x: other.x.min(other2.x),
min_y: other.y.min(other2.y),
min_z: other.z.min(other2.z),
max_x: other.x.max(other2.x),
max_y: other.y.max(other2.y),
max_z: other.z.max(other2.z),
})
}
pub fn contains(&self, x: f64, y: f64, z: f64) -> bool {
x >= self.min_x
&& x < self.max_x
&& y >= self.min_y
&& y < self.max_y
&& z >= self.min_z
&& z < self.max_z
}
pub fn size(&self) -> f64 {
let x = self.get_xsize();
let y = self.get_ysize();
let z = self.get_zsize();
(x + y + z) / 3.0
}
pub fn get_xsize(&self) -> f64 {
self.max_x - self.min_x
}
pub fn get_ysize(&self) -> f64 {
self.max_y - self.min_y
}
pub fn get_zsize(&self) -> f64 {
self.max_z - self.min_z
}
pub fn deflate(&mut self, x: f64, y: f64, z: f64) -> AABB {
self.inflate(-x, -y, -z)
}
pub fn clip(&self, min: &Vec3, max: &Vec3) -> Option<Vec3> {
let mut t = [1.0];
let x = max.x - min.x;
let y = max.y - min.y;
let z = max.z - min.z;
let dir = self.get_direction(self, min, &mut t, None, x, y, z);
if dir.is_none() {
return None;
}
let t = t[0];
Some(min.add(t * x, t * y, t * z))
}
pub fn clip_iterable(
&self,
boxes: &Vec<AABB>,
from: &Vec3,
to: &Vec3,
pos: &BlockPos,
) -> Option<BlockHitResult> {
let mut t = [1.0];
let mut dir = None;
let x = to.x - from.x;
let y = to.y - from.y;
let z = to.z - from.z;
for aabb in boxes {
dir = self.get_direction(aabb, from, &mut t, dir, x, y, z);
}
if dir.is_none() {
return None;
}
let t = t[0];
Some(BlockHitResult {
location: from.add(t * x, t * y, t * z),
direction: dir.unwrap(),
block_pos: *pos,
inside: false,
miss: false,
})
}
fn get_direction(
&self,
aabb: &AABB,
from: &Vec3,
t: &mut [f64],
dir: Option<Direction>,
x: f64,
y: f64,
z: f64,
) -> Option<Direction> {
if x > EPSILON {
return self.clip_point(
t,
dir,
x,
y,
z,
aabb.min_x,
aabb.min_y,
aabb.max_y,
aabb.min_z,
aabb.max_z,
Direction::West,
from.x,
from.y,
from.z,
);
} else if x < -EPSILON {
return self.clip_point(
t,
dir,
x,
y,
z,
aabb.max_x,
aabb.min_y,
aabb.max_y,
aabb.min_z,
aabb.max_z,
Direction::East,
from.x,
from.y,
from.z,
);
}
if y > EPSILON {
return self.clip_point(
t,
dir,
y,
z,
x,
aabb.min_y,
aabb.min_z,
aabb.max_z,
aabb.min_x,
aabb.max_x,
Direction::Down,
from.y,
from.z,
from.x,
);
} else if y < -EPSILON {
return self.clip_point(
t,
dir,
y,
z,
x,
aabb.max_y,
aabb.min_z,
aabb.max_z,
aabb.min_x,
aabb.max_x,
Direction::Up,
from.y,
from.z,
from.x,
);
}
if z > EPSILON {
return self.clip_point(
t,
dir,
z,
x,
y,
aabb.min_z,
aabb.min_x,
aabb.max_x,
aabb.min_y,
aabb.max_y,
Direction::North,
from.z,
from.x,
from.y,
);
} else if z < -EPSILON {
return self.clip_point(
t,
dir,
z,
x,
y,
aabb.max_z,
aabb.min_x,
aabb.max_x,
aabb.min_y,
aabb.max_y,
Direction::South,
from.z,
from.x,
from.y,
);
}
dir
}
fn clip_point(
&self,
t: &mut [f64],
approach_dir: Option<Direction>,
delta_x: f64,
delta_y: f64,
delta_z: f64,
begin: f64,
min_x: f64,
max_x: f64,
min_z: f64,
max_z: f64,
result_dir: Direction,
start_x: f64,
start_y: f64,
start_z: f64,
) -> Option<Direction> {
let mut t_x = (begin - start_x) / delta_x;
let mut t_y = (begin - start_y) / delta_y;
let mut t_z = (begin - start_z) / delta_z;
if 0.0 < t_x
&& t_x < t[0]
&& min_x - EPSILON < t_y
&& t_y < max_x + EPSILON
&& max_x - EPSILON < t_z
&& t_z < max_z + EPSILON
{
t[0] = t_x;
Some(result_dir)
} else {
approach_dir
}
}
pub fn has_nan(&self) -> bool {
self.min_x.is_nan()
|| self.min_y.is_nan()
|| self.min_z.is_nan()
|| self.max_x.is_nan()
|| self.max_y.is_nan()
|| self.max_z.is_nan()
}
pub fn get_center(&self) -> Vec3 {
Vec3 {
x: (self.min_x + self.max_x) / 2.0,
y: (self.min_y + self.max_y) / 2.0,
z: (self.min_z + self.max_z) / 2.0,
}
}
pub fn of_size(center: Vec3, dx: f64, dy: f64, dz: f64) -> AABB {
AABB {
min_x: center.x - dx / 2.0,
min_y: center.y - dy / 2.0,
min_z: center.z - dz / 2.0,
max_x: center.x + dx / 2.0,
max_y: center.y + dy / 2.0,
max_z: center.z + dz / 2.0,
}
}
}

View file

@ -0,0 +1,9 @@
use azalea_core::{BlockPos, Direction, Vec3};
pub struct BlockHitResult {
pub location: Vec3,
pub direction: Direction,
pub block_pos: BlockPos,
pub miss: bool,
pub inside: bool,
}

View file

@ -1,5 +1,10 @@
mod aabb;
mod block_hit_result;
use crate::Entity;
pub use aabb::AABB;
use azalea_core::PositionDelta;
pub use block_hit_result::BlockHitResult;
pub enum MoverType {
Own,
@ -10,5 +15,24 @@ pub enum MoverType {
}
impl Entity {
pub fn move_entity(&mut self, mover_type: &MoverType, movement: &PositionDelta) {}
pub fn move_entity(&mut self, mover_type: &MoverType, movement: &PositionDelta) {
// if self.no_physics {
// return;
// };
// if (var1 == MoverType.PISTON) {
// var2 = this.limitPistonMovement(var2);
// if (var2.equals(Vec3.ZERO)) {
// return;
// }
// }
// if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7D) {
// var2 = var2.multiply(this.stuckSpeedMultiplier);
// this.stuckSpeedMultiplier = Vec3.ZERO;
// this.setDeltaMovement(Vec3.ZERO);
// }
// TODO
}
}

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_core::EntityPos;
use azalea_core::Vec3;
use azalea_entity::Entity;
use packet_macros::GamePacket;
use uuid::Uuid;
@ -31,7 +31,7 @@ impl From<&ClientboundAddEntityPacket> for Entity {
Self::new(
p.id,
p.uuid,
EntityPos {
Vec3 {
x: p.x,
y: p.y,
z: p.z,

View file

@ -1,5 +1,5 @@
use azalea_buf::McBuf;
use azalea_core::EntityPos;
use azalea_core::Vec3;
use azalea_entity::Entity;
use packet_macros::GamePacket;
use uuid::Uuid;
@ -22,7 +22,7 @@ impl From<&ClientboundAddPlayerPacket> for Entity {
Self::new(
p.id,
p.uuid,
EntityPos {
Vec3 {
x: p.x,
y: p.y,
z: p.z,

View file

@ -3,7 +3,7 @@ use azalea_core::PositionDelta8;
use packet_macros::GamePacket;
#[derive(Clone, Debug, McBuf, GamePacket)]
pub struct ClientboundMoveEntityPosPacket {
pub struct ClientboundMoveVec3Packet {
#[var]
pub entity_id: u32,
pub delta: PositionDelta8,

View file

@ -4,7 +4,7 @@ use packet_macros::GamePacket;
/// This packet is sent by the server when an entity moves less then 8 blocks.
#[derive(Clone, Debug, McBuf, GamePacket)]
pub struct ClientboundMoveEntityPosRotPacket {
pub struct ClientboundMoveVec3RotPacket {
#[var]
pub entity_id: u32,
pub delta: PositionDelta8,

View file

@ -96,8 +96,8 @@ declare_state_packets!(
0x21: clientbound_level_particles_packet::ClientboundLevelParticlesPacket,
0x22: clientbound_light_update_packet::ClientboundLightUpdatePacket,
0x23: clientbound_login_packet::ClientboundLoginPacket,
0x26: clientbound_move_entity_pos_packet::ClientboundMoveEntityPosPacket,
0x27: clientbound_move_entity_posrot_packet::ClientboundMoveEntityPosRotPacket,
0x26: clientbound_move_entity_pos_packet::ClientboundMoveVec3Packet,
0x27: clientbound_move_entity_posrot_packet::ClientboundMoveVec3RotPacket,
0x28: clientbound_move_entity_rot_packet::ClientboundMoveEntityRotPacket,
0x2f: clientbound_player_abilities_packet::ClientboundPlayerAbilitiesPacket,
0x30: clientbound_player_chat_packet::ClientboundPlayerChatPacket,

View file

@ -6,7 +6,7 @@ mod entity;
mod palette;
use azalea_block::BlockState;
use azalea_core::{BlockPos, ChunkPos, EntityPos, PositionDelta8};
use azalea_core::{BlockPos, ChunkPos, PositionDelta8, Vec3};
use azalea_entity::Entity;
pub use bit_storage::BitStorage;
pub use chunk::{Chunk, ChunkStorage};
@ -58,7 +58,7 @@ impl Dimension {
self.chunk_storage.get_block_state(pos, self.min_y())
}
pub fn move_entity(&mut self, entity_id: u32, new_pos: EntityPos) -> Result<(), String> {
pub fn move_entity(&mut self, entity_id: u32, new_pos: Vec3) -> Result<(), String> {
let entity = self
.entity_storage
.get_mut_by_id(entity_id)