mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-31 08:22:33 +00:00
feat(connection_cache): implement player samples in server status
- Add `Sample` import from pumpkin_protocol for player sample representation - Add `Uuid` import for player identification - Add `MAX_SAMPLE_PLAYERS` constant set to 12 to limit sample size - Add `player_samples` field to `CachedStatus` struct to track online players - Implement player sample collection in `add_player` method with deduplication - Implement player sample removal in `remove_player` method - Update status response JSON with player samples on each change - Replace TODO comments with functional implementation for player tracking - Ensures server status response includes up to 12 player samples for clients
This commit is contained in:
@@ -4,7 +4,7 @@ use core::error;
|
||||
use pumpkin_config::BasicConfiguration;
|
||||
use pumpkin_data::packet::CURRENT_MC_PROTOCOL;
|
||||
use pumpkin_protocol::{
|
||||
Players, StatusResponse, Version,
|
||||
Players, Sample, StatusResponse, Version,
|
||||
codec::var_int::VarInt,
|
||||
java::client::{config::CPluginMessage, status::CStatusResponse},
|
||||
};
|
||||
@@ -13,8 +13,10 @@ use std::{
|
||||
fs::{self},
|
||||
path::Path,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
const DEFAULT_ICON: &[u8] = include_bytes!("../../../assets/default_icon.png");
|
||||
const MAX_SAMPLE_PLAYERS: usize = 12;
|
||||
|
||||
fn load_icon_from_file<P: AsRef<Path>>(path: P) -> Result<String, Box<dyn error::Error>> {
|
||||
let buf = fs::read(path)?;
|
||||
@@ -41,6 +43,7 @@ pub struct CachedStatus {
|
||||
// We cache the json response here so we don't parse it every time someone makes a status request.
|
||||
// Keep in mind that we must parse this again when the StatusResponse changes, which usually happen when a player joins or leaves.
|
||||
status_response_json: String,
|
||||
player_samples: Vec<(Uuid, String)>,
|
||||
}
|
||||
|
||||
pub struct CachedBranding {
|
||||
@@ -79,6 +82,7 @@ impl CachedStatus {
|
||||
Self {
|
||||
status_response,
|
||||
status_response_json,
|
||||
player_samples: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,37 +90,48 @@ impl CachedStatus {
|
||||
CStatusResponse::new(self.status_response_json.clone())
|
||||
}
|
||||
|
||||
// TODO: Player samples
|
||||
pub fn add_player(&mut self, _player: &Player) {
|
||||
pub fn add_player(&mut self, player: &Player) {
|
||||
let status_response = &mut self.status_response;
|
||||
if let Some(players) = &mut status_response.players {
|
||||
// TODO
|
||||
// if player
|
||||
// .client
|
||||
// .added_to_server_listing
|
||||
// .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
|
||||
// .is_ok()
|
||||
// {
|
||||
players.online = players.online.saturating_add(1);
|
||||
// }
|
||||
|
||||
let player_id = player.gameprofile.id;
|
||||
let player_name = player.gameprofile.name.clone();
|
||||
|
||||
if !self.player_samples.iter().any(|(id, _)| *id == player_id) {
|
||||
self.player_samples.push((player_id, player_name.clone()));
|
||||
|
||||
players.sample = self.player_samples
|
||||
.iter()
|
||||
.take(MAX_SAMPLE_PLAYERS)
|
||||
.map(|(id, name)| Sample {
|
||||
name: name.clone(),
|
||||
id: id.to_string(),
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
self.status_response_json = serde_json::to_string(&status_response)
|
||||
.expect("Failed to parse status response into JSON");
|
||||
}
|
||||
|
||||
pub fn remove_player(&mut self, _player: &Player) {
|
||||
pub fn remove_player(&mut self, player: &Player) {
|
||||
let status_response = &mut self.status_response;
|
||||
if let Some(players) = &mut status_response.players {
|
||||
// TODO
|
||||
// if player
|
||||
// .client
|
||||
// .added_to_server_listing
|
||||
// .compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed)
|
||||
// .is_ok()
|
||||
// {
|
||||
players.online = players.online.saturating_sub(1);
|
||||
// }
|
||||
|
||||
let player_id = player.gameprofile.id;
|
||||
self.player_samples.retain(|(id, _)| *id != player_id);
|
||||
|
||||
players.sample = self.player_samples
|
||||
.iter()
|
||||
.take(MAX_SAMPLE_PLAYERS)
|
||||
.map(|(id, name)| Sample {
|
||||
name: name.clone(),
|
||||
id: id.to_string(),
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
self.status_response_json = serde_json::to_string(&status_response)
|
||||
|
||||
Reference in New Issue
Block a user