Skip to content

Commit

Permalink
Add more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Snowiiii committed Oct 29, 2024
1 parent 9f70b95 commit 14c8c7e
Show file tree
Hide file tree
Showing 7 changed files with 355 additions and 156 deletions.
236 changes: 118 additions & 118 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"docs:preview": "vitepress preview docs"
},
"devDependencies": {
"vitepress": "^1.4.1",
"vitepress": "^1.4.2",
"vue": "^3.5.12"
}
}
112 changes: 105 additions & 7 deletions pumpkin/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,32 @@ impl Client {
client_packets_queue.push_back(packet);
}

/// Sets the Packet encryption
/// Enables or disables packet encryption for the connection.
///
/// This function takes an optional shared secret as input. If the shared secret is provided,
/// the connection's encryption is enabled using the provided secret key. Otherwise, encryption is disabled.
///
/// # Arguments
///
/// * `shared_secret`: An optional **already decrypted** shared secret key used for encryption.
///
/// # Returns
///
/// A `Result` indicating whether the encryption was set successfully.
///
/// # Errors
///
/// Returns an `EncryptionError` if the shared secret has an incorrect length.
///
/// # Examples
/// ```
/// let shared_secret = server.decrypt(&encryption_response.shared_secret).unwrap();
///
/// if let Err(error) = self.set_encryption(Some(&shared_secret)).await {
/// self.kick(&error.to_string()).await;
/// return;
/// }
/// ```
pub async fn set_encryption(
&self,
shared_secret: Option<&[u8]>, // decrypted
Expand All @@ -176,13 +201,24 @@ impl Client {
Ok(())
}

/// Sets the Packet compression
/// Enables or disables packet compression for the connection.
///
/// This function takes an optional `CompressionInfo` struct as input. If the `CompressionInfo` is provided,
/// packet compression is enabled with the specified threshold. Otherwise, compression is disabled.
///
/// # Arguments
///
/// * `compression`: An optional `CompressionInfo` struct containing the compression threshold and compression level.
pub async fn set_compression(&self, compression: Option<CompressionInfo>) {
self.dec.lock().await.set_compression(compression.is_some());
self.enc.lock().await.set_compression(compression);
}

/// Send a Clientbound Packet to the Client
/// Sends a clientbound packet to the connected client.
///
/// # Arguments
///
/// * `packet`: A reference to a packet object implementing the `ClientPacket` trait.
pub async fn send_packet<P: ClientPacket>(&self, packet: &P) {
//log::debug!("Sending packet with id {} to {}", P::PACKET_ID, self.id);
// assert!(!self.closed);
Expand Down Expand Up @@ -216,6 +252,19 @@ impl Client {
*/
}

/// Sends a clientbound packet to the connected client.
///
/// # Arguments
///
/// * `packet`: A reference to a packet object implementing the `ClientPacket` trait.
///
/// # Returns
///
/// A `Result` indicating whether the Packet was Send successfully.
///
/// # Errors
///
/// Returns an `PacketError` if the could not be Send.
pub async fn try_send_packet<P: ClientPacket>(&self, packet: &P) -> Result<(), PacketError> {
// assert!(!self.closed);
/*
Expand Down Expand Up @@ -244,7 +293,19 @@ impl Client {
Ok(())
}

/// Processes all packets send by the client
/// Processes all packets received from the connected client in a loop.
///
/// This function continuously dequeues packets from the client's packet queue and processes them.
/// Processing involves calling the `handle_packet` function with the server instance and the packet itself.
///
/// The loop exits when:
///
/// - The connection is closed (checked before processing each packet).
/// - An error occurs while processing a packet (client is kicked with an error message).
///
/// # Arguments
///
/// * `server`: A reference to the `Arc<Server>` instance.
pub async fn process_packets(&self, server: &Arc<Server>) {
let mut packet_queue = self.client_packets_queue.lock().await;
while let Some(mut packet) = packet_queue.pop_front() {
Expand All @@ -264,7 +325,30 @@ impl Client {
}
}

/// Handles an incoming decoded not Play state Packet
/// Handles an incoming packet, routing it to the appropriate handler based on the current connection state.
///
/// This function takes a `RawPacket` and routes it to the corresponding handler based on the current connection state.
/// It supports the following connection states:
///
/// - **Handshake:** Handles handshake packets.
/// - **Status:** Handles status request and ping packets.
/// - **Login/Transfer:** Handles login and transfer packets.
/// - **Config:** Handles configuration packets.
///
/// For the `Play` state, an error is logged as it indicates an invalid state for packet processing.
///
/// # Arguments
///
/// * `server`: A reference to the `Arc<Server>` instance.
/// * `packet`: A mutable reference to the `RawPacket` to be processed.
///
/// # Returns
///
/// A `Result` indicating whether the packet was read and handled successfully.
///
/// # Errors
///
/// Returns a `DeserializerError` if an error occurs during packet deserialization.
pub async fn handle_packet(
&self,
server: &Arc<Server>,
Expand Down Expand Up @@ -463,7 +547,13 @@ impl Client {
}
}

/// Kicks the Client with a reason depending on the connection state
/// Disconnects a client from the server with a specified reason.
///
/// This function kicks a client identified by its ID from the server. The appropriate disconnect packet is sent based on the client's current connection state.
///
/// # Arguments
///
/// * `reason`: A string describing the reason for kicking the client.
pub async fn kick(&self, reason: &str) {
log::info!("Kicking Client id {} for {}", self.id, reason);
let result = match self.connection_state.load() {
Expand Down Expand Up @@ -491,7 +581,15 @@ impl Client {
self.close();
}

/// You should prefer to use `kick` when you can
/// Closes the connection to the client.
///
/// This function marks the connection as closed using an atomic flag. It's generally preferable
/// to use the `kick` function if you want to send a specific message to the client explaining the reason for the closure.
/// However, use `close` in scenarios where sending a message is not critical or might not be possible (e.g., sudden connection drop).
///
/// # Notes
///
/// This function does not attempt to send any disconnect packets to the client.
pub fn close(&self) {
self.closed
.store(true, std::sync::atomic::Ordering::Relaxed);
Expand Down
9 changes: 7 additions & 2 deletions pumpkin/src/entity/living.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ use pumpkin_protocol::client::play::{CEntityStatus, CSetEntityMetadata, Metadata

use super::Entity;

/// Represents a Living Entity (e.g. Player, Zombie, Enderman...)
/// Represents a living entity within the game world.
///
/// This struct encapsulates the core properties and behaviors of living entities, including players, mobs, and other creatures.
pub struct LivingEntity {
/// The underlying entity object, providing basic entity information and functionality.
pub entity: Entity,
/// Tracks the remaining time until the entity can regenerate health.
pub time_until_regen: AtomicI32,
/// Stores the amount of damage the entity last received.
pub last_damage_taken: AtomicCell<f32>,
/// The entity's current health level.
/// The current health level of the entity.
pub health: AtomicCell<f32>,
}

Expand Down
5 changes: 0 additions & 5 deletions pumpkin/src/entity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,22 @@ pub struct Entity {
/// The world in which the entity exists.
pub world: Arc<World>,
/// The entity's current health level.

/// The entity's current position in the world
pub pos: AtomicCell<Vector3<f64>>,
/// The entity's position rounded to the nearest block coordinates
pub block_pos: AtomicCell<WorldPosition>,
/// The chunk coordinates of the entity's current position
pub chunk_pos: AtomicCell<Vector2<i32>>,

/// Indicates whether the entity is sneaking
pub sneaking: AtomicBool,
/// Indicates whether the entity is sprinting
pub sprinting: AtomicBool,
/// Indicates whether the entity is flying due to a fall
pub fall_flying: AtomicBool,

/// The entity's current velocity vector, aka Knockback
pub velocity: AtomicCell<Vector3<f64>>,

/// Indicates whether the entity is on the ground (may not always be accurate).
pub on_ground: AtomicBool,

/// The entity's yaw rotation (horizontal rotation) ← →
pub yaw: AtomicCell<f32>,
/// The entity's head yaw rotation (horizontal rotation of the head)
Expand Down
83 changes: 73 additions & 10 deletions pumpkin/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,26 @@ pub mod ticker;

pub const CURRENT_MC_VERSION: &str = "1.21.3";

/// Represents a Minecraft server instance.
pub struct Server {
/// Handles cryptographic keys for secure communication.
key_store: KeyStore,
/// Manages server status information.
server_listing: Mutex<CachedStatus>,
/// Saves server branding information.
server_branding: CachedBranding,

/// Saves and Dispatches commands to appropriate handlers.
pub command_dispatcher: Arc<CommandDispatcher<'static>>,
/// Manages multiple worlds within the server.
pub worlds: Vec<Arc<World>>,

/// Cache the registry so we don't have to parse it every time a player joins
/// Caches game registries for efficient access.
pub cached_registry: Vec<Registry>,

pub open_containers: RwLock<HashMap<u64, OpenContainer>>,
/// Tracks open containers used for item interactions.
pub drag_handler: DragHandler,
/// Assigns unique IDs to entities.
entity_id: AtomicI32,

/// Used for Authentication, None is Online mode is disabled
/// Manages authentication with a authentication server, if enabled.
pub auth_client: Option<reqwest::Client>,
}

Expand Down Expand Up @@ -92,6 +96,31 @@ impl Server {
}
}

/// Adds a new player to the server.

/// This function takes an `Arc<Client>` representing the connected client and performs the following actions:
///
/// 1. Generates a new entity ID for the player.
/// 2. Determines the player's gamemode (defaulting to Survival if not specified in configuration).
/// 3. **(TODO: Select default from config)** Selects the world for the player (currently uses the first world).
/// 4. Creates a new `Player` instance using the provided information.
/// 5. Adds the player to the chosen world.
/// 6. **(TODO: Config if we want increase online)** Optionally updates server listing information based on player's configuration.
///
/// # Arguments
///
/// * `client`: An `Arc<Client>` representing the connected client.

/// # Returns
///
/// A tuple containing:
///
/// - `Arc<Player>`: A reference to the newly created player object.
/// - `Arc<World>`: A reference to the world the player was added to.
///
/// # Note
///
/// You still have to spawn the Player in the World to make then to let them Join and make them Visible
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 {
Expand Down Expand Up @@ -134,7 +163,13 @@ impl Server {
.cloned()
}

/// Sends a Packet to all Players in all worlds
/// Broadcasts a packet to all players in all worlds.
///
/// This function sends the specified packet to every connected player in every world managed by the server.
///
/// # Arguments
///
/// * `packet`: A reference to the packet to be broadcast. The packet must implement the `ClientPacket` trait.
pub async fn broadcast_packet_all<P>(&self, packet: &P)
where
P: ClientPacket,
Expand All @@ -144,7 +179,18 @@ impl Server {
}
}

/// Searches every world for a player by username
/// Searches for a player by their username across all worlds.
///
/// This function iterates through each world managed by the server and attempts to find a player with the specified username.
/// If a player is found in any world, it returns an `Arc<Player>` reference to that player. Otherwise, it returns `None`.
///
/// # Arguments
///
/// * `name`: The username of the player to search for.
///
/// # Returns
///
/// An `Option<Arc<Player>>` containing the player if found, or `None` if not found.
pub async fn get_player_by_name(&self, name: &str) -> Option<Arc<Player>> {
for world in &self.worlds {
if let Some(player) = world.get_player_by_name(name).await {
Expand All @@ -154,7 +200,18 @@ impl Server {
None
}

/// Searches every world for a player by UUID
/// Searches for a player by their UUID across all worlds.
///
/// This function iterates through each world managed by the server and attempts to find a player with the specified UUID.
/// If a player is found in any world, it returns an `Arc<Player>` reference to that player. Otherwise, it returns `None`.
///
/// # Arguments
///
/// * `id`: The UUID of the player to search for.
///
/// # Returns
///
/// An `Option<Arc<Player>>` containing the player if found, or `None` if not found.
pub async fn get_player_by_uuid(&self, id: uuid::Uuid) -> Option<Arc<Player>> {
for world in &self.worlds {
if let Some(player) = world.get_player_by_uuid(id).await {
Expand All @@ -164,7 +221,13 @@ impl Server {
None
}

/// Get the player count sum in all worlds
/// Counts the total number of players across all worlds.
///
/// This function iterates through each world and sums up the number of players currently connected to that world.
///
/// # Returns
///
/// The total number of players connected to the server.
pub async fn get_player_count(&self) -> usize {
let mut count = 0;
for world in &self.worlds {
Expand Down
Loading

0 comments on commit 14c8c7e

Please sign in to comment.