deepslate 0.1.0

A high-performance Minecraft server proxy written in Rust.
Documentation
//! Concrete event types fired by the proxy.
//!
//! Each event is a plain struct. Events that can be cancelled or have their
//! outcome modified implement [`ResultedEvent`] with a domain-specific result
//! enum.
//!
//! Notification-only events (no result) are simple structs that handlers can
//! read but not influence.

use super::result::{EventResult, ResultedEvent};
use crate::event::PlayerInfo;

// ---------------------------------------------------------------------------
// LoginEvent
// ---------------------------------------------------------------------------

/// Fired after a player completes authentication but before they are connected
/// to a backend server.
///
/// Handlers can deny the login by setting the result to [`LoginResult::Deny`].
pub struct LoginEvent {
    /// Information about the connecting player.
    pub player: PlayerInfo,
    result: LoginResult,
}

impl LoginEvent {
    /// Create a new login event (defaults to allowed).
    #[must_use]
    pub const fn new(player: PlayerInfo) -> Self {
        Self {
            player,
            result: LoginResult::Allow,
        }
    }
}

/// Result for [`LoginEvent`].
#[derive(Debug, Clone)]
pub enum LoginResult {
    /// Allow the player to connect.
    Allow,
    /// Deny the connection with a reason (sent as a disconnect message).
    Deny(String),
}

impl EventResult for LoginResult {
    fn is_allowed(&self) -> bool {
        matches!(self, Self::Allow)
    }
}

impl ResultedEvent for LoginEvent {
    type Result = LoginResult;

    fn result(&self) -> &Self::Result {
        &self.result
    }

    fn set_result(&mut self, result: Self::Result) {
        self.result = result;
    }
}

// ---------------------------------------------------------------------------
// ChooseServerEvent
// ---------------------------------------------------------------------------

/// Fired to determine which backend server a player should initially connect to.
///
/// Handlers can override the default server selection by setting the result to
/// [`ChooseServerResult::Override`].
pub struct ChooseServerEvent {
    /// Information about the connecting player.
    pub player: PlayerInfo,
    result: ChooseServerResult,
}

impl ChooseServerEvent {
    /// Create a new event (defaults to using the configured try-order).
    #[must_use]
    pub const fn new(player: PlayerInfo) -> Self {
        Self {
            player,
            result: ChooseServerResult::Default,
        }
    }
}

/// Result for [`ChooseServerEvent`].
#[derive(Debug, Clone)]
pub enum ChooseServerResult {
    /// Use the configured try-order to select a server.
    Default,
    /// Connect to a specific server, overriding the try-order.
    Override(String),
}

impl EventResult for ChooseServerResult {
    fn is_allowed(&self) -> bool {
        true // always "allowed" — the question is which server, not whether to allow
    }
}

impl ResultedEvent for ChooseServerEvent {
    type Result = ChooseServerResult;

    fn result(&self) -> &Self::Result {
        &self.result
    }

    fn set_result(&mut self, result: Self::Result) {
        self.result = result;
    }
}

// ---------------------------------------------------------------------------
// ServerSwitchEvent
// ---------------------------------------------------------------------------

/// Fired when a player requests a server switch (e.g., via `/server <name>`).
///
/// Handlers can deny the switch by setting the result to
/// [`ServerSwitchResult::Deny`].
pub struct ServerSwitchEvent {
    /// Information about the player.
    pub player: PlayerInfo,
    /// The server the player is currently on.
    pub from: String,
    /// The server the player wants to switch to.
    pub to: String,
    result: ServerSwitchResult,
}

impl ServerSwitchEvent {
    /// Create a new event (defaults to allowed).
    #[must_use]
    pub const fn new(player: PlayerInfo, from: String, to: String) -> Self {
        Self {
            player,
            from,
            to,
            result: ServerSwitchResult::Allow,
        }
    }
}

/// Result for [`ServerSwitchEvent`].
#[derive(Debug, Clone)]
pub enum ServerSwitchResult {
    /// Allow the server switch.
    Allow,
    /// Deny the switch with a reason (sent as a chat message).
    Deny(String),
}

impl EventResult for ServerSwitchResult {
    fn is_allowed(&self) -> bool {
        matches!(self, Self::Allow)
    }
}

impl ResultedEvent for ServerSwitchEvent {
    type Result = ServerSwitchResult;

    fn result(&self) -> &Self::Result {
        &self.result
    }

    fn set_result(&mut self, result: Self::Result) {
        self.result = result;
    }
}

// ---------------------------------------------------------------------------
// ServerConnectedEvent
// ---------------------------------------------------------------------------

/// Fired after a player has successfully connected to a backend server.
///
/// This is a notification-only event — handlers cannot cancel it.
pub struct ServerConnectedEvent {
    /// Information about the player.
    pub player: PlayerInfo,
    /// The ID of the server the player connected to.
    pub server_id: String,
}

impl ServerConnectedEvent {
    /// Create a new event.
    #[must_use]
    pub const fn new(player: PlayerInfo, server_id: String) -> Self {
        Self { player, server_id }
    }
}

// ---------------------------------------------------------------------------
// DisconnectEvent
// ---------------------------------------------------------------------------

/// Fired when a player disconnects from the proxy.
///
/// This is a notification-only event — handlers cannot cancel it.
pub struct DisconnectEvent {
    /// Information about the disconnecting player.
    pub player: PlayerInfo,
}

impl DisconnectEvent {
    /// Create a new event.
    #[must_use]
    pub const fn new(player: PlayerInfo) -> Self {
        Self { player }
    }
}

// ---------------------------------------------------------------------------
// PingEvent
// ---------------------------------------------------------------------------

/// Fired when the proxy receives a server list ping.
///
/// Handlers can override the status response by setting the result to
/// [`PingResult::Override`].
pub struct PingEvent {
    /// The default status response JSON.
    pub default_response: serde_json::Value,
    /// The protocol version of the pinging client.
    pub client_protocol: i32,
    result: PingResult,
}

impl PingEvent {
    /// Create a new event (defaults to using the built-in response).
    #[must_use]
    pub const fn new(default_response: serde_json::Value, client_protocol: i32) -> Self {
        Self {
            default_response,
            client_protocol,
            result: PingResult::Default,
        }
    }
}

/// Result for [`PingEvent`].
#[derive(Debug, Clone)]
pub enum PingResult {
    /// Use the default status response.
    Default,
    /// Use a custom status response.
    Override(serde_json::Value),
}

impl EventResult for PingResult {
    fn is_allowed(&self) -> bool {
        true // always "allowed" — the question is which response, not whether to respond
    }
}

impl ResultedEvent for PingEvent {
    type Result = PingResult;

    fn result(&self) -> &Self::Result {
        &self.result
    }

    fn set_result(&mut self, result: Self::Result) {
        self.result = result;
    }
}