Move from ids to uuids

This commit is contained in:
Snowiiii 2024-10-23 16:38:30 +02:00
parent e396399e66
commit 14ff151d88
9 changed files with 65 additions and 88 deletions

View File

@ -18,7 +18,7 @@ use pumpkin_protocol::{
use uuid::Uuid;
use crate::{
client::authentication::{self, validate_textures, GameProfile},
client::authentication::{self, offline_uuid, validate_textures, GameProfile},
entity::player::{ChatMode, Hand},
proxy::{
bungeecord,
@ -39,11 +39,7 @@ impl Client {
.store(version, std::sync::atomic::Ordering::Relaxed);
*self.server_address.lock().await = handshake.server_address;
log::debug!(
"Handshake: id {} is now in state {:?}",
self.id,
&handshake.next_state
);
log::debug!("Handshake: next state {:?}", &handshake.next_state);
self.connection_state.store(handshake.next_state);
if self.connection_state.load() != ConnectionState::Status {
let protocol = version;
@ -60,13 +56,13 @@ impl Client {
}
pub async fn handle_status_request(&self, server: &Server, _status_request: SStatusRequest) {
log::debug!("Handling status request for id {}", self.id);
log::debug!("Handling status request for id");
let status = server.get_status();
self.send_packet(&status.lock().await.get_status()).await;
}
pub async fn handle_ping_request(&self, ping_request: SStatusPingRequest) {
log::debug!("Handling ping request for id {}", self.id);
log::debug!("Handling ping request for id");
self.send_packet(&CPingResponse::new(ping_request.payload))
.await;
self.close();
@ -80,11 +76,7 @@ impl Client {
}
pub async fn handle_login_start(&self, server: &Server, login_start: SLoginStart) {
log::debug!(
"login start for id {}, State {:?}",
self.id,
self.connection_state
);
log::debug!("login start");
if !Self::is_valid_player_name(&login_start.name) {
self.kick("Invalid characters in username").await;
@ -108,8 +100,14 @@ impl Client {
}
}
} else {
let id = if BASIC_CONFIG.online_mode {
login_start.uuid
} else {
offline_uuid(&login_start.name).expect("This is very not safe and bad")
};
let profile = GameProfile {
id: login_start.uuid,
id,
name: login_start.name,
properties: vec![],
profile_actions: None,
@ -137,7 +135,7 @@ impl Client {
server: &Server,
encryption_response: SEncryptionResponse,
) {
log::debug!("Handling encryption for id {}", self.id);
log::debug!("Handling encryption for id");
let shared_secret = server.decrypt(&encryption_response.shared_secret).unwrap();
if let Err(error) = self.set_encryption(Some(&shared_secret)).await {
@ -228,7 +226,7 @@ impl Client {
}
pub async fn handle_plugin_response(&self, plugin_response: SLoginPluginResponse) {
log::debug!("Handling plugin for id {}", self.id);
log::debug!("Handling plugin for id");
let velocity_config = &ADVANCED_CONFIG.proxy.velocity;
if velocity_config.enabled {
let mut address = self.address.lock().await;
@ -252,7 +250,7 @@ impl Client {
server: &Server,
_login_acknowledged: SLoginAcknowledged,
) {
log::debug!("Handling login acknowledged for id {}", self.id);
log::debug!("Handling login acknowledged for id");
self.connection_state.store(ConnectionState::Config);
self.send_packet(&server.get_branding()).await;
@ -289,7 +287,7 @@ impl Client {
&self,
client_information: SClientInformationConfig,
) {
log::debug!("Handling client settings for id {}", self.id);
log::debug!("Handling client settings for id");
if let (Some(main_hand), Some(chat_mode)) = (
Hand::from_i32(client_information.main_hand.into()),
ChatMode::from_i32(client_information.chat_mode.into()),
@ -310,7 +308,7 @@ impl Client {
}
pub async fn handle_plugin_message(&self, plugin_message: SPluginMessage) {
log::debug!("Handling plugin message for id {}", self.id);
log::debug!("Handling plugin message for id");
if plugin_message.channel.starts_with("minecraft:brand")
|| plugin_message.channel.starts_with("MC|Brand")
{
@ -323,7 +321,7 @@ impl Client {
}
pub async fn handle_known_packs(&self, server: &Server, _config_acknowledged: SKnownPacks) {
log::debug!("Handling known packs for id {}", self.id);
log::debug!("Handling known packs for id");
for registry in &server.cached_registry {
self.send_packet(&CRegistryData::new(
&registry.registry_id,
@ -338,7 +336,7 @@ impl Client {
}
pub fn handle_config_acknowledged(&self, _config_acknowledged: &SAcknowledgeFinishConfig) {
log::debug!("Handling config acknowledge for id {}", self.id);
log::debug!("Handling config acknowledge for id");
self.connection_state.store(ConnectionState::Play);
self.make_player
.store(true, std::sync::atomic::Ordering::Relaxed);

View File

@ -406,7 +406,7 @@ impl Player {
.filter(|player_id| *player_id != self.entity_id())
.collect_vec()
};
let player_token = self.client.id;
let player_token = self.gameprofile.id;
// TODO: Figure out better way to get only the players from player_ids
// Also refactor out a better method to get individual advanced state ids

View File

@ -107,8 +107,6 @@ pub struct Client {
pub encryption: AtomicBool,
/// Indicates if the client connection is closed.
pub closed: AtomicBool,
/// A unique id identifying the client.
pub id: usize,
/// The underlying TCP connection to the client.
pub connection_reader: Arc<Mutex<tokio::net::tcp::OwnedReadHalf>>,
pub connection_writer: Arc<Mutex<tokio::net::tcp::OwnedWriteHalf>>,
@ -126,7 +124,7 @@ pub struct Client {
impl Client {
#[must_use]
pub fn new(id: usize, connection: tokio::net::TcpStream, address: SocketAddr) -> Self {
pub fn new(connection: tokio::net::TcpStream, address: SocketAddr) -> Self {
let (connection_reader, connection_writer) = connection.into_split();
Self {
protocol_version: AtomicI32::new(0),
@ -134,7 +132,6 @@ impl Client {
config: Mutex::new(None),
brand: Mutex::new(None),
server_address: Mutex::new(String::new()),
id,
address: Mutex::new(address),
connection_state: AtomicCell::new(ConnectionState::HandShake),
connection_reader: Arc::new(Mutex::new(connection_reader)),
@ -198,11 +195,7 @@ impl Client {
{
self.kick(&error.to_string()).await;
} else if let Err(error) = writer.flush().await {
log::warn!(
"Failed to flush writer for id {}: {}",
self.id,
error.to_string()
);
log::warn!("Failed to flush writer for: {}", error.to_string());
}
}
@ -280,7 +273,7 @@ impl Client {
&self,
packet: &mut RawPacket,
) -> Result<(), DeserializerError> {
log::debug!("Handling handshake group for id {}", self.id);
log::debug!("Handling handshake group");
let bytebuf = &mut packet.bytebuf;
match packet.id.0 {
0 => {
@ -301,7 +294,7 @@ impl Client {
server: &Arc<Server>,
packet: &mut RawPacket,
) -> Result<(), DeserializerError> {
log::debug!("Handling status group for id {}", self.id);
log::debug!("Handling status group");
let bytebuf = &mut packet.bytebuf;
if let Some(packet) = ServerboundStatusPackets::from_i32(packet.id.0) {
match packet {
@ -329,7 +322,7 @@ impl Client {
server: &Arc<Server>,
packet: &mut RawPacket,
) -> Result<(), DeserializerError> {
log::debug!("Handling login group for id {}", self.id);
log::debug!("Handling login group for id");
let bytebuf = &mut packet.bytebuf;
if let Some(packet) = ServerboundLoginPackets::from_i32(packet.id.0) {
match packet {
@ -366,7 +359,7 @@ impl Client {
server: &Arc<Server>,
packet: &mut RawPacket,
) -> Result<(), DeserializerError> {
log::debug!("Handling config group for id {}", self.id);
log::debug!("Handling config group");
let bytebuf = &mut packet.bytebuf;
if let Some(packet) = ServerboundConfigPackets::from_i32(packet.id.0) {
#[expect(clippy::match_same_arms)]
@ -414,11 +407,7 @@ impl Client {
return true;
}
Ok(None) => (), //log::debug!("Waiting for more data to complete packet..."),
Err(err) => log::warn!(
"Failed to decode packet for id {}: {}",
self.id,
err.to_string()
),
Err(err) => log::warn!("Failed to decode packet for: {}", err.to_string()),
}
dec.reserve(4096);
@ -448,7 +437,7 @@ impl Client {
/// Kicks the Client with a reason depending on the connection state
pub async fn kick(&self, reason: &str) {
log::info!("Kicking Client id {} for {}", self.id, reason);
log::info!("Kicking Client for {}", reason);
match self.connection_state.load() {
ConnectionState::Login => {
self.try_send_packet(&CLoginDisconnect::new(

View File

@ -113,7 +113,7 @@ impl Player {
// send new position to all other players
world
.broadcast_packet_expect(
&[self.client.id],
&[self.gameprofile.id],
&CUpdateEntityPos::new(
entity_id.into(),
x.mul_add(4096.0, -(last_x * 4096.0)) as i16,
@ -186,7 +186,7 @@ impl Player {
world
.broadcast_packet_expect(
&[self.client.id],
&[self.gameprofile.id],
&CUpdateEntityPosRot::new(
entity_id.into(),
x.mul_add(4096.0, -(last_x * 4096.0)) as i16,
@ -200,7 +200,7 @@ impl Player {
.await;
world
.broadcast_packet_expect(
&[self.client.id],
&[self.gameprofile.id],
&CHeadRot::new(entity_id.into(), yaw as u8),
)
.await;
@ -230,11 +230,11 @@ impl Player {
let packet =
CUpdateEntityRot::new(entity_id.into(), yaw as u8, pitch as u8, rotation.ground);
world
.broadcast_packet_expect(&[self.client.id], &packet)
.broadcast_packet_expect(&[self.gameprofile.id], &packet)
.await;
let packet = CHeadRot::new(entity_id.into(), yaw as u8);
world
.broadcast_packet_expect(&[self.client.id], &packet)
.broadcast_packet_expect(&[self.gameprofile.id], &packet)
.await;
}
@ -325,7 +325,7 @@ impl Player {
let world = &self.living_entity.entity.world;
world
.broadcast_packet_expect(
&[self.client.id],
&[self.gameprofile.id],
&CEntityAnimation::new(id.into(), animation as u8),
)
.await;

View File

@ -157,7 +157,7 @@ impl Player {
log::debug!(
"Removing player id {}, unwatching {} chunks",
self.client.id,
self.gameprofile.name,
all_chunks.len()
);
self.living_entity
@ -168,7 +168,7 @@ impl Player {
log::debug!(
"Removed player id {} ({} chunks remain cached)",
self.client.id,
self.gameprofile.name,
self.living_entity.entity.world.get_cached_chunk_len().await
);
}

View File

@ -171,7 +171,6 @@ async fn main() -> io::Result<()> {
ticker.run(&server).await;
});
}
let mut player_count = 0;
loop {
// Asynchronously wait for an inbound socket.
let (connection, address) = listener.accept().await?;
@ -180,16 +179,12 @@ async fn main() -> io::Result<()> {
log::warn!("failed to set TCP_NODELAY {e}");
}
player_count += 1;
let id = player_count;
log::info!(
"Accepted connection from: {} (id: {})",
"Accepted connection from: {} ",
scrub_address(&format!("{address}")),
id
);
let client = Arc::new(Client::new(id, connection, addr));
let client = Arc::new(Client::new(connection, addr));
let server = server.clone();
tokio::spawn(async move {
@ -207,9 +202,7 @@ async fn main() -> io::Result<()> {
.make_player
.load(std::sync::atomic::Ordering::Relaxed)
{
let id = client.id;
log::debug!("Creating player for id {}", id);
let (player, world) = server.add_player(id, client).await;
let (player, world) = server.add_player(client).await;
world.spawn_player(&BASIC_CONFIG, player.clone()).await;
// poll Player
while !player
@ -226,6 +219,5 @@ async fn main() -> io::Result<()> {
server.remove_player().await;
}
});
player_count -= 1;
}
}

View File

@ -93,7 +93,7 @@ impl Server {
}
}
pub async fn add_player(&self, id: usize, client: Arc<Client>) -> (Arc<Player>, Arc<World>) {
pub async fn add_player(&self, client: Arc<Client>) -> (Arc<Player>, Arc<World>) {
let entity_id = self.new_entity_id();
let gamemode = match BASIC_CONFIG.default_gamemode {
GameMode::Undefined => GameMode::Survival,
@ -104,7 +104,9 @@ impl Server {
let world = &self.worlds[0];
let player = Arc::new(Player::new(client, world.clone(), entity_id, gamemode).await);
world.add_player(id, player.clone()).await;
world
.add_player(player.gameprofile.id, player.clone())
.await;
// TODO: Config if we want increase online
if let Some(config) = player.client.config.lock().await.as_ref() {
// TODO: Config so we can also just ignore this hehe

View File

@ -42,7 +42,7 @@ pub struct World {
/// The underlying level, responsible for chunk management and terrain generation.
pub level: Arc<Mutex<Level>>,
/// A map of active players within the world, keyed by their unique token.
pub current_players: Arc<Mutex<HashMap<usize, Arc<Player>>>>,
pub current_players: Arc<Mutex<HashMap<uuid::Uuid, Arc<Player>>>>,
pub scoreboard: Mutex<Scoreboard>,
// TODO: entities
}
@ -77,7 +77,7 @@ impl World {
/// Sends the specified packet to every player currently logged in to the server, excluding the players listed in the `except` parameter.
///
/// **Note:** This function acquires a lock on the `current_players` map, ensuring thread safety.
pub async fn broadcast_packet_expect<P>(&self, except: &[usize], packet: &P)
pub async fn broadcast_packet_expect<P>(&self, except: &[uuid::Uuid], packet: &P)
where
P: ClientPacket,
{
@ -100,11 +100,10 @@ impl World {
let gamemode = player.gamemode.load();
log::debug!(
"spawning player {}, entity id {}",
player.client.id,
player.gameprofile.name,
entity_id
);
log::debug!("Sending login packet to {}", player.client.id);
// login packet for our new player
player
.client
@ -134,7 +133,7 @@ impl World {
// player abilities
// TODO: this is for debug purpose, remove later
log::debug!("Sending player abilities to {}", player.client.id);
log::debug!("Sending player abilities to {}", player.gameprofile.name);
player
.client
.send_packet(&CPlayerAbilities::new(0x02, 0.4, 0.1))
@ -145,7 +144,7 @@ impl World {
let yaw = 10.0;
let pitch = 10.0;
log::debug!("Sending player teleport to {}", player.client.id);
log::debug!("Sending player teleport to {}", player.gameprofile.name);
player.teleport(position, yaw, pitch).await;
let pos = player.living_entity.entity.pos.load();
@ -154,7 +153,7 @@ impl World {
let gameprofile = &player.gameprofile;
// first send info update to our new player, So he can see his Skin
// also send his info to everyone else
log::debug!("Broadcasting player info for {}", player.client.id);
log::debug!("Broadcasting player info for {}", player.gameprofile.name);
self.broadcast_packet_all(&CPlayerInfoUpdate::new(
0x01 | 0x08,
&[pumpkin_protocol::client::play::Player {
@ -176,7 +175,7 @@ impl World {
let current_players = self.current_players.lock().await;
for (_, playerr) in current_players
.iter()
.filter(|(c, _)| **c != player.client.id)
.filter(|(c, _)| **c != player.gameprofile.id)
{
let gameprofile = &playerr.gameprofile;
entries.push(pumpkin_protocol::client::play::Player {
@ -190,7 +189,7 @@ impl World {
],
});
}
log::debug!("Sending player info to {}", player.client.id);
log::debug!("Sending player info to {}", player.gameprofile.name);
player
.client
.send_packet(&CPlayerInfoUpdate::new(0x01 | 0x08, &entries))
@ -199,10 +198,10 @@ impl World {
let gameprofile = &player.gameprofile;
log::debug!("Broadcasting player spawn for {}", player.client.id);
log::debug!("Broadcasting player spawn for {}", player.gameprofile.name);
// spawn player for every client
self.broadcast_packet_expect(
&[player.client.id],
&[player.gameprofile.id],
// TODO: add velo
&CSpawnEntity::new(
entity_id.into(),
@ -222,18 +221,18 @@ impl World {
)
.await;
// spawn players for our client
let token = player.client.id;
let id = player.gameprofile.id;
for (_, existing_player) in self
.current_players
.lock()
.await
.iter()
.filter(|c| c.0 != &token)
.filter(|c| c.0 != &id)
{
let entity = &existing_player.living_entity.entity;
let pos = entity.pos.load();
let gameprofile = &existing_player.gameprofile;
log::debug!("Sending player entities to {}", player.client.id);
log::debug!("Sending player entities to {}", player.gameprofile.name);
player
.client
.send_packet(&CSpawnEntity::new(
@ -260,12 +259,12 @@ impl World {
entity_id.into(),
Metadata::new(17, VarInt(0), config.skin_parts),
);
log::debug!("Broadcasting skin for {}", player.client.id);
log::debug!("Broadcasting skin for {}", player.gameprofile.name);
self.broadcast_packet_all(&packet).await;
}
// Start waiting for level chunks, Sets the "Loading Terrain" screen
log::debug!("Sending waiting chunks to {}", player.client.id);
log::debug!("Sending waiting chunks to {}", player.gameprofile.name);
player
.client
.send_packet(&CGameEvent::new(GameEvent::StartWaitingChunks, 0.0))
@ -292,10 +291,7 @@ impl World {
fn spawn_world_chunks(&self, client: Arc<Client>, chunks: Vec<Vector2<i32>>) {
if client.closed.load(std::sync::atomic::Ordering::Relaxed) {
log::info!(
"The connection with {} has closed before world chunks were spawned",
client.id
);
log::info!("The connection has closed before world chunks were spawned",);
return;
}
let inst = std::time::Instant::now();
@ -351,19 +347,19 @@ impl World {
None
}
pub async fn add_player(&self, id: usize, player: Arc<Player>) {
self.current_players.lock().await.insert(id, player);
pub async fn add_player(&self, uuid: uuid::Uuid, player: Arc<Player>) {
self.current_players.lock().await.insert(uuid, player);
}
pub async fn remove_player(&self, player: &Player) {
self.current_players
.lock()
.await
.remove(&player.client.id)
.remove(&player.gameprofile.id)
.unwrap();
let uuid = player.gameprofile.id;
self.broadcast_packet_expect(
&[player.client.id],
&[player.gameprofile.id],
&CRemovePlayerInfo::new(1.into(), &[uuid]),
)
.await;

View File

@ -28,7 +28,7 @@ pub async fn player_join(world: &World, player: Arc<Player>) {
assert_eq!(new_watched.x, chunk_pos.x);
assert_eq!(new_watched.z, chunk_pos.z);
log::debug!("Sending center chunk to {}", player.client.id);
log::debug!("Sending center chunk to {}", player.gameprofile.name);
player
.client
.send_packet(&CCenterChunk {
@ -40,7 +40,7 @@ pub async fn player_join(world: &World, player: Arc<Player>) {
log::debug!(
"Player {} ({}) joined with view distance: {}",
player.gameprofile.name,
player.client.id,
player.gameprofile.name,
view_distance
);