Skip to content

Commit

Permalink
world: change player list to rwlock (#550)
Browse files Browse the repository at this point in the history
  • Loading branch information
vyPal authored Feb 14, 2025
1 parent 95e04c7 commit 9c32499
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 28 deletions.
2 changes: 1 addition & 1 deletion pumpkin/src/entity/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ impl Player {
let uuid = self.gameprofile.id;
current_world.remove_player(self.clone(), false).await;
*self.living_entity.entity.world.write().await = new_world.clone();
new_world.players.lock().await.insert(uuid, self.clone());
new_world.players.write().await.insert(uuid, self.clone());
self.unload_watched_chunks(&current_world).await;
let last_pos = self.living_entity.last_pos.load();
let death_dimension = self.world().await.dimension_type.name();
Expand Down
2 changes: 1 addition & 1 deletion pumpkin/src/net/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ impl Player {
.read()
.await
.players
.lock()
.read()
.await
.iter()
.filter_map(|(token, player)| {
Expand Down
2 changes: 1 addition & 1 deletion pumpkin/src/net/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ async fn handle_packet(
for world in server.worlds.read().await.iter() {
let mut world_players = world
.players
.lock()
.read()
.await
// Although there is no documented limit, we will limit to 4 players
.values()
Expand Down
4 changes: 2 additions & 2 deletions pumpkin/src/plugin/api/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl Context {
};

for world in self.server.worlds.read().await.iter() {
for player in world.players.lock().await.values() {
for player in world.players.read().await.values() {
client_suggestions::send_c_commands_packet(player, &self.server.command_dispatcher)
.await;
}
Expand All @@ -105,7 +105,7 @@ impl Context {
};

for world in self.server.worlds.read().await.iter() {
for player in world.players.lock().await.values() {
for player in world.players.read().await.values() {
client_suggestions::send_c_commands_packet(player, &self.server.command_dispatcher)
.await;
}
Expand Down
8 changes: 4 additions & 4 deletions pumpkin/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ impl Server {
let mut players = Vec::<Arc<Player>>::new();

for world in self.worlds.read().await.iter() {
for (_, player) in world.players.lock().await.iter() {
for (_, player) in world.players.read().await.iter() {
if player.client.address.lock().await.ip() == ip {
players.push(player.clone());
}
Expand All @@ -372,7 +372,7 @@ impl Server {
let mut players = Vec::<Arc<Player>>::new();

for world in self.worlds.read().await.iter() {
for (_, player) in world.players.lock().await.iter() {
for (_, player) in world.players.read().await.iter() {
players.push(player.clone());
}
}
Expand Down Expand Up @@ -418,7 +418,7 @@ impl Server {
pub async fn get_player_count(&self) -> usize {
let mut count = 0;
for world in self.worlds.read().await.iter() {
count += world.players.lock().await.len();
count += world.players.read().await.len();
}
count
}
Expand All @@ -427,7 +427,7 @@ impl Server {
pub async fn has_n_players(&self, n: usize) -> bool {
let mut count = 0;
for world in self.worlds.read().await.iter() {
count += world.players.lock().await.len();
count += world.players.read().await.len();
if count >= n {
return true;
}
Expand Down
38 changes: 19 additions & 19 deletions pumpkin/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub struct World {
/// The underlying level, responsible for chunk management and terrain generation.
pub level: Arc<Level>,
/// A map of active players within the world, keyed by their unique UUID.
pub players: Arc<Mutex<HashMap<uuid::Uuid, Arc<Player>>>>,
pub players: Arc<RwLock<HashMap<uuid::Uuid, Arc<Player>>>>,
/// A map of active entities within the world, keyed by their unique UUID.
/// This does not include Players
pub entities: Arc<RwLock<HashMap<uuid::Uuid, Arc<dyn EntityBase>>>>,
Expand All @@ -128,7 +128,7 @@ impl World {
pub fn load(level: Level, dimension_type: DimensionType) -> Self {
Self {
level: Arc::new(level),
players: Arc::new(Mutex::new(HashMap::new())),
players: Arc::new(RwLock::new(HashMap::new())),
entities: Arc::new(RwLock::new(HashMap::new())),
scoreboard: Mutex::new(Scoreboard::new()),
worldborder: Mutex::new(Worldborder::new(0.0, 0.0, 29_999_984.0, 0, 0, 0)),
Expand All @@ -151,7 +151,7 @@ impl World {
where
P: ClientPacket,
{
let current_players = self.players.lock().await;
let current_players = self.players.read().await;
for player in current_players.values() {
player.client.send_packet(packet).await;
}
Expand Down Expand Up @@ -182,7 +182,7 @@ impl World {
where
P: ClientPacket,
{
let current_players = self.players.lock().await;
let current_players = self.players.read().await;
for (_, player) in current_players.iter().filter(|c| !except.contains(c.0)) {
player.client.send_packet(packet).await;
}
Expand All @@ -196,7 +196,7 @@ impl World {
particle_count: i32,
pariticle: Particle,
) {
let players = self.players.lock().await;
let players = self.players.read().await;
for (_, player) in players.iter() {
player
.spawn_particle(position, offset, max_speed, particle_count, pariticle)
Expand All @@ -218,7 +218,7 @@ impl World {
pitch: f32,
) {
let seed = thread_rng().gen::<f64>();
let players = self.players.lock().await;
let players = self.players.read().await;
for (_, player) in players.iter() {
player
.play_sound(sound_id, category, position, volume, pitch, seed)
Expand Down Expand Up @@ -276,7 +276,7 @@ impl World {
};

// player ticks
for player in self.players.lock().await.values() {
for player in self.players.read().await.values() {
player.tick().await;
}

Expand All @@ -287,7 +287,7 @@ impl World {
entity.tick().await;
// this boolean thing prevents deadlocks, since we lock players we can't broadcast packets
let mut collied_player = None;
for player in self.players.lock().await.values() {
for player in self.players.read().await.values() {
if player
.living_entity
.entity
Expand Down Expand Up @@ -407,7 +407,7 @@ impl World {
// here we send all the infos of already joined players
let mut entries = Vec::new();
{
let current_players = self.players.lock().await;
let current_players = self.players.read().await;
for (_, playerr) in current_players
.iter()
.filter(|(c, _)| **c != player.gameprofile.id)
Expand Down Expand Up @@ -453,7 +453,7 @@ impl World {
.await;
// spawn players for our client
let id = player.gameprofile.id;
for (_, existing_player) in self.players.lock().await.iter().filter(|c| c.0 != &id) {
for (_, existing_player) in self.players.read().await.iter().filter(|c| c.0 != &id) {
let entity = &existing_player.living_entity.entity;
let pos = entity.pos.load();
let gameprofile = &existing_player.gameprofile;
Expand Down Expand Up @@ -744,7 +744,7 @@ impl World {

/// Gets a Player by entity id
pub async fn get_player_by_id(&self, id: EntityId) -> Option<Arc<Player>> {
for player in self.players.lock().await.values() {
for player in self.players.read().await.values() {
if player.entity_id() == id {
return Some(player.clone());
}
Expand All @@ -764,7 +764,7 @@ impl World {

/// Gets a Player by username
pub async fn get_player_by_name(&self, name: &str) -> Option<Arc<Player>> {
for player in self.players.lock().await.values() {
for player in self.players.read().await.values() {
if player.gameprofile.name.to_lowercase() == name.to_lowercase() {
return Some(player.clone());
}
Expand All @@ -785,7 +785,7 @@ impl World {
///
/// An `Option<Arc<Player>>` containing the player if found, or `None` if not.
pub async fn get_player_by_uuid(&self, id: uuid::Uuid) -> Option<Arc<Player>> {
return self.players.lock().await.get(&id).cloned();
return self.players.read().await.get(&id).cloned();
}

/// Gets a list of players who's location equals the given position in the world.
Expand All @@ -799,7 +799,7 @@ impl World {
/// * `position`: The position the function will check.
pub async fn get_players_by_pos(&self, position: BlockPos) -> HashMap<uuid::Uuid, Arc<Player>> {
self.players
.lock()
.read()
.await
.iter()
.filter_map(|(uuid, player)| {
Expand Down Expand Up @@ -829,7 +829,7 @@ impl World {
let radius_squared = radius.powi(2);

self.players
.lock()
.read()
.await
.iter()
.filter_map(|(id, player)| {
Expand Down Expand Up @@ -874,7 +874,7 @@ impl World {
/// * `player`: An `Arc<Player>` reference to the player object.
pub async fn add_player(&self, uuid: uuid::Uuid, player: Arc<Player>) {
{
let mut current_players = self.players.lock().await;
let mut current_players = self.players.write().await;
current_players.insert(uuid, player.clone())
};

Expand All @@ -895,7 +895,7 @@ impl World {

if !event.cancelled {
let current_players = current_players.clone();
let players = current_players.lock().await;
let players = current_players.read().await;
for player in players.values() {
player.send_system_message(&event.join_message).await;
}
Expand Down Expand Up @@ -925,7 +925,7 @@ impl World {
/// - The disconnect message sending is currently optional. Consider making it a configurable option.
pub async fn remove_player(&self, player: Arc<Player>, fire_event: bool) {
self.players
.lock()
.write()
.await
.remove(&player.gameprofile.id)
.unwrap();
Expand Down Expand Up @@ -953,7 +953,7 @@ impl World {
.await;

if !event.cancelled {
let players = self.players.lock().await;
let players = self.players.read().await;
for player in players.values() {
player.send_system_message(&event.leave_message).await;
}
Expand Down

0 comments on commit 9c32499

Please sign in to comment.