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

Implement max player limit #194

Merged
merged 5 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
11 changes: 9 additions & 2 deletions pumpkin/src/client/client_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ impl Client {
pub async fn handle_login_start(&self, server: &Server, login_start: SLoginStart) {
log::debug!("login start");

// Don't allow new logons when server is full.
// TODO: If client is an operator or otherwise suitable elevated permissions, allow client to bypass this requirement.
if server.get_player_count().await >= BASIC_CONFIG.max_players {
self.kick("The server is currently full, please try again later")
.await;
}

if !Self::is_valid_player_name(&login_start.name) {
self.kick("Invalid characters in username").await;
return;
Expand Down Expand Up @@ -166,14 +173,14 @@ impl Client {

// Don't allow duplicate UUIDs
if let Some(online_player) = &server.get_player_by_uuid(profile.id).await {
log::debug!("Player (IP '{}', username '{}') tried to log in with the same UUID ('{}') as an online player (IP '{}', username '{}')", &self.address.lock().await.to_string(), &profile.name, &profile.id.to_string(), &online_player.client.address.lock().await.to_string(), &online_player.gameprofile.name);
log::debug!("Player (IP '{}', username '{}') tried to log in with the same UUID ('{}') as an online player (IP '{}', username '{}')", &self.address.lock().await, &profile.name, &profile.id, &online_player.client.address.lock().await, &online_player.gameprofile.name);
self.kick("You are already connected to this server").await;
return;
}

// Don't allow a duplicate username
if let Some(online_player) = &server.get_player_by_name(&profile.name).await {
log::debug!("A player (IP '{}', attempted username '{}') tried to log in with the same username as an online player (UUID '{}', IP '{}', username '{}')", &self.address.lock().await.to_string(), &profile.name, &profile.id.to_string(), &online_player.client.address.lock().await.to_string(), &online_player.gameprofile.name);
log::debug!("A player (IP '{}', attempted username '{}') tried to log in with the same username as an online player (UUID '{}', IP '{}', username '{}')", &self.address.lock().await, &profile.name, &profile.id, &online_player.client.address.lock().await, &online_player.gameprofile.name);
self.kick("A player with this username is already connected")
.await;
return;
Expand Down
16 changes: 16 additions & 0 deletions pumpkin/src/server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use connection_cache::{CachedBranding, CachedStatus};
use key_store::KeyStore;
use num_traits::ToPrimitive;
use pumpkin_config::BASIC_CONFIG;
use pumpkin_core::GameMode;
use pumpkin_entity::EntityId;
Expand Down Expand Up @@ -163,6 +164,21 @@ impl Server {
None
}

/// Get the player count sum in all worlds
pub async fn get_player_count(&self) -> u32 {
let mut count = 0;
for world in &self.worlds {
count += world
.current_players
.lock()
.await
.len()
.to_u32()
.expect("Unable to convert to u32");
}
count
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need to convert it to u32, just use usize

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BASIC_CONFIG.max_players is u32 which is why I used the conversion, also usize is platform dependent , please let me know what you think

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So generally we want to use usize for such things like a player count. I also want to give the option to disable a player limit, maybe by setting it to -1 ?. the config value can stay u32 because this will be more than enough if someone wants to set a limit

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR return usize. If you compare it with the config value, cast it

Copy link
Contributor Author

@lokka30 lokka30 Oct 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cheers - should be resolved in 8aba1ff. I've also added logic that setting the max players to zero will disable the limit. (since it's unsigned, we can't / shouldn't use -1)


/// Generates a new entity id
/// This should be global
pub fn new_entity_id(&self) -> EntityId {
Expand Down