Check collision before block place (#251)

* Add bounding box to entities)

* Try to update boundingbox when changin pos

* Remove unused imports

* Update / recalc boundingbox when changing pos

* Add collision when placing check

* Add todo: Check collision with every entity in pos

* Change BoundingBox::new() args

* Seperate bounding box width and height

* Change intersect fn name

* Clean up code
This commit is contained in:
Tiiita
2024-11-10 23:28:14 +01:00
committed by GitHub
parent 2d24098e91
commit 4067f65ff9
4 changed files with 80 additions and 16 deletions

View File

@@ -1,5 +1,6 @@
use super::{position::WorldPosition, vector3::Vector3};
#[derive(Clone, Copy)]
pub struct BoundingBox {
pub min_x: f64,
pub min_y: f64,
@@ -10,14 +11,30 @@ pub struct BoundingBox {
}
impl BoundingBox {
pub fn new(min_x: f64, min_y: f64, min_z: f64, max_x: f64, max_y: f64, max_z: f64) -> Self {
pub fn new_default(size: &BoundingBoxSize) -> Self {
Self::new_from_pos(0., 0., 0., size)
}
pub fn new_from_pos(x: f64, y: f64, z: f64, size: &BoundingBoxSize) -> Self {
let f = size.width / 2.;
Self {
min_x,
min_y,
min_z,
max_x,
max_y,
max_z,
min_x: x - f,
min_y: y,
min_z: z - f,
max_x: x + f,
max_y: y + size.height,
max_z: z + f,
}
}
pub fn new(min: Vector3<f64>, max: Vector3<f64>) -> Self {
Self {
min_x: min.x,
min_y: min.y,
min_z: min.z,
max_x: max.x,
max_y: max.y,
max_z: max.z,
}
}
@@ -33,6 +50,15 @@ impl BoundingBox {
}
}
pub fn intersects(&self, other: &BoundingBox) -> 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 squared_magnitude(&self, pos: Vector3<f64>) -> f64 {
let d = f64::max(f64::max(self.min_x - pos.x, pos.x - self.max_x), 0.0);
let e = f64::max(f64::max(self.min_y - pos.y, pos.y - self.max_y), 0.0);
@@ -40,3 +66,9 @@ impl BoundingBox {
super::squared_magnitude(d, e, f)
}
}
#[derive(Clone, Copy)]
pub struct BoundingBoxSize {
pub width: f64,
pub height: f64,
}

View File

@@ -8,7 +8,7 @@ use crate::{
};
use num_traits::FromPrimitive;
use pumpkin_config::ADVANCED_CONFIG;
use pumpkin_core::math::position::WorldPosition;
use pumpkin_core::math::{boundingbox::BoundingBox, position::WorldPosition};
use pumpkin_core::{
math::{vector3::Vector3, wrap_degrees},
text::TextComponent,
@@ -577,12 +577,13 @@ impl Player {
}
}
world
.set_block(
WorldPosition(location.0 + face.to_offset()),
block.default_state_id,
)
.await;
let world_pos = WorldPosition(location.0 + face.to_offset());
let block_bounding_box = BoundingBox::from_block(&world_pos);
let bounding_box = entity.bounding_box.load();
//TODO: Make this check for every entity in that posistion
if !bounding_box.intersects(&block_bounding_box) {
world.set_block(world_pos, block.default_state_id).await;
}
}
self.client
.send_packet(&CAcknowledgeBlockChange::new(use_item_on.sequence))

View File

@@ -3,7 +3,11 @@ use std::sync::{atomic::AtomicBool, Arc};
use crossbeam::atomic::AtomicCell;
use num_derive::FromPrimitive;
use pumpkin_core::math::{
get_section_cord, position::WorldPosition, vector2::Vector2, vector3::Vector3,
boundingbox::{BoundingBox, BoundingBoxSize},
get_section_cord,
position::WorldPosition,
vector2::Vector2,
vector3::Vector3,
};
use pumpkin_entity::{entity_type::EntityType, pose::EntityPose, EntityId};
use pumpkin_protocol::{
@@ -50,6 +54,10 @@ pub struct Entity {
pub standing_eye_height: f32,
/// The entity's current pose (e.g., standing, sitting, swimming).
pub pose: AtomicCell<EntityPose>,
/// The bounding box of an entity (hitbox)
pub bounding_box: AtomicCell<BoundingBox>,
///The size (width and height) of the bounding box
pub bounding_box_size: AtomicCell<BoundingBoxSize>,
}
impl Entity {
@@ -58,6 +66,8 @@ impl Entity {
world: Arc<World>,
entity_type: EntityType,
standing_eye_height: f32,
bounding_box: AtomicCell<BoundingBox>,
bounding_box_size: AtomicCell<BoundingBoxSize>,
) -> Self {
Self {
entity_id,
@@ -77,6 +87,8 @@ impl Entity {
velocity: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)),
standing_eye_height,
pose: AtomicCell::new(EntityPose::Standing),
bounding_box,
bounding_box_size,
}
}
@@ -89,6 +101,13 @@ impl Entity {
if pos.x != x || pos.y != y || pos.z != z {
self.pos.store(Vector3::new(x, y, z));
self.bounding_box.store(BoundingBox::new_from_pos(
pos.x,
pos.y,
pos.z,
&self.bounding_box_size.load(),
));
let floor_x = x.floor() as i32;
let floor_y = y.floor() as i32;
let floor_z = z.floor() as i32;

View File

@@ -13,7 +13,12 @@ use itertools::Itertools;
use num_derive::FromPrimitive;
use pumpkin_config::ADVANCED_CONFIG;
use pumpkin_core::{
math::{boundingbox::BoundingBox, position::WorldPosition, vector2::Vector2, vector3::Vector3},
math::{
boundingbox::{BoundingBox, BoundingBoxSize},
position::WorldPosition,
vector2::Vector2,
vector3::Vector3,
},
text::TextComponent,
GameMode,
};
@@ -177,12 +182,19 @@ impl Player {
|profile| profile,
);
let config = client.config.lock().await.clone().unwrap_or_default();
let bounding_box_size = BoundingBoxSize {
width: 0.6,
height: 1.8,
};
Self {
living_entity: LivingEntity::new(Entity::new(
entity_id,
world,
EntityType::Player,
1.62,
AtomicCell::new(BoundingBox::new_default(&bounding_box_size)),
AtomicCell::new(bounding_box_size),
)),
config: Mutex::new(config),
gameprofile,