Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions pumpkin/src/client/player_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ impl Player {
world_pos
};

//TODO: Maybe put that in config?
//check max world build height
if world_pos.0.y > 319 {
self.client
Expand All @@ -661,17 +662,22 @@ 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 posistion
if !bounding_box.intersects(&block_bounding_box) {

//Search in 20 block radius
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;
}
}
self.client
.send_packet(&CAcknowledgeBlockChange::new(use_item_on.sequence))
.await;
}

Ok(())
Expand Down
66 changes: 66 additions & 0 deletions pumpkin/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,72 @@ 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;
if position.0.x == player_block_pos.x
&& position.0.y == player_block_pos.y
&& position.0.z == player_block_pos.z
{
Some((*uuid, Arc::clone(player)))
} else {
None
}
})
.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.
Expand Down
Loading