Add nearby players collision check when trying to place blocks (#293)

* Try to update boundingbox when changin pos

* Remove unused imports

* Add nearby player check when placing blocks

* Add seach for nearby players when placing block

* Reformat

* Fix conflict

* fix: conflicts

and fix clippy

---------

Co-authored-by: Alexander Medvedev <lilalexmed@proton.me>
This commit is contained in:
Tiiita
2024-12-25 16:53:39 +01:00
committed by GitHub
parent 0e9b1af760
commit e8deff519e
2 changed files with 70 additions and 3 deletions

View File

@@ -764,9 +764,14 @@ impl Player {
}
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 position
if !bounding_box.intersects(&block_bounding_box) {
let mut intersects = false;
for player in world.get_nearby_players(entity.pos.load(), 20).await {
let bounding_box = player.1.living_entity.entity.bounding_box.load();
if bounding_box.intersects(&block_bounding_box) {
intersects = true;
}
}
if !intersects {
world
.set_block_state(world_pos, block.default_state_id)
.await;

View File

@@ -630,6 +630,68 @@ impl World {
return self.current_players.lock().await.get(&id).cloned();
}
/// Gets a list of players who's location equals the given position in the world.
///
/// It iterates through the players in the world and checks their location. If the player's location matches the
/// given position it will add this to a Vec which it later returns. If no
/// player was found in that position it will just return an empty Vec.
///
/// # Arguments
///
/// * `position`: The position the function will check.
pub async fn get_players_by_pos(
&self,
position: WorldPosition,
) -> HashMap<uuid::Uuid, Arc<Player>> {
self.current_players
.lock()
.await
.iter()
.filter_map(|(uuid, player)| {
let player_block_pos = player.living_entity.entity.block_pos.load().0;
(position.0.x == player_block_pos.x
&& position.0.y == player_block_pos.y
&& position.0.z == player_block_pos.z)
.then(|| (*uuid, Arc::clone(player)))
})
.collect::<HashMap<uuid::Uuid, Arc<Player>>>()
}
/// Gets the nearby players around a given world position
/// It "creates" a sphere and checks if whether players are inside
/// and returns a hashmap where the uuid is the key and the player
/// object the value.
///
/// # Arguments
/// * `pos`: The middlepoint of the sphere
/// * `radius`: The radius of the sphere. The higher the radius
/// the more area will be checked, in every direction.
pub async fn get_nearby_players(
&self,
pos: Vector3<f64>,
radius: u16,
) -> HashMap<uuid::Uuid, Arc<Player>> {
let radius_squared = (f64::from(radius)).powi(2);
let mut found_players = HashMap::new();
for player in self.current_players.lock().await.iter() {
let player_pos = player.1.living_entity.entity.pos.load();
let diff = Vector3::new(
player_pos.x - pos.x,
player_pos.y - pos.y,
player_pos.z - pos.z,
);
let distance_squared = diff.x.powi(2) + diff.y.powi(2) + diff.z.powi(2);
if distance_squared <= radius_squared {
found_players.insert(*player.0, player.1.clone());
}
}
found_players
}
/// Adds a player to the world and broadcasts a join message if enabled.
///
/// This function takes a player's UUID and an `Arc<Player>` reference.