Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions crates/arcane-core/src/cluster_simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,13 @@ pub struct GameAction {
/// remove it and include the id in the next delta's `removed` list. Deleting from `entities` alone
/// would omit the entity from `updated` without a removal record.
pub struct ClusterTickContext<'a> {
/// Unique identifier for this cluster.
pub cluster_id: Uuid,
/// Monotonic tick index that will be assigned to the upcoming replication delta's `tick` field.
pub tick: u64,
/// Simulation time step (seconds) since the last tick.
pub dt_seconds: f64,
/// Mutable reference to the cluster's entity storage.
pub entities: &'a mut HashMap<Uuid, EntityStateEntry>,
/// Processed after `on_tick` returns so the next delta lists these ids under `removed`.
pub pending_removals: &'a mut Vec<Uuid>,
Expand All @@ -59,5 +62,7 @@ pub struct ClusterTickContext<'a> {

/// Custom simulation step for entities owned by this cluster.
pub trait ClusterSimulation: Send + Sync {
/// Advance simulation state by one tick. Called once per tick after client updates and injected
/// entities are applied, and before the replication delta is built.
fn on_tick(&self, ctx: &mut ClusterTickContext<'_>);
}
25 changes: 25 additions & 0 deletions crates/arcane-core/src/server_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,54 @@ use uuid::Uuid;
/// Handle to an allocated cluster server.
#[derive(Clone, Debug)]
pub struct ServerHandle {
/// Unique identifier for this server instance.
pub server_id: Uuid,
/// Hostname or IP address of the server.
pub host: String,
/// WebSocket port for client connections.
pub ws_port: u16,
/// RPC port for inter-cluster communication.
pub rpc_port: u16,
/// Metrics / observability port.
pub metrics_port: u16,
/// Monotonic timestamp (seconds since epoch) when the server was allocated.
pub allocated_at: f64,
}

/// Error from pool operations.
#[derive(Clone, Debug)]
pub struct PoolError {
/// Machine-readable error code.
pub code: PoolErrorCode,
/// Human-readable error detail for logging and debugging.
pub detail: String,
}

/// Reasons a pool operation can fail.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PoolErrorCode {
/// All servers are allocated; no capacity remaining.
PoolExhausted,
/// An allocation request exceeded the timeout.
AllocationTimeout,
/// The target server is in an unhealthy state.
ServerUnhealthy,
}

/// Current pool capacity and health.
#[derive(Clone, Debug)]
pub struct PoolStatus {
/// Total number of server slots in the pool.
pub total_capacity: u32,
/// Number of servers currently free for allocation.
pub available: u32,
/// Number of servers currently allocated to clusters.
pub allocated: u32,
/// Number of servers in a failed state.
pub failed: u32,
/// Minimum desired free capacity; below this triggers scaling.
pub min_available: u32,
/// P99 allocation latency in milliseconds.
pub allocation_p99_ms: f32,
}

Expand All @@ -56,15 +74,22 @@ pub trait IServerPool: Send + Sync {
fn get_status(&self) -> PoolStatus;
}

/// Category of server failure reported to the pool.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FailureType {
/// Server is not reachable over the network.
Unreachable,
/// Server process crashed (e.g. segfault, OOM).
SimulationCrashed,
/// Server is reachable but operating outside acceptable performance bounds.
PerformanceDegraded,
}

/// Result of a failure report: an optional replacement server and expected wait time.
#[derive(Clone, Debug)]
pub struct ReplacementHandle {
/// Replacement server handle, if one was immediately available.
pub handle: Option<ServerHandle>,
/// Estimated time (ms) until a replacement is ready, if not immediate.
pub eta_ms: Option<u32>,
}
11 changes: 11 additions & 0 deletions crates/arcane-core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ pub use uuid::Uuid as EntityId;
/// 2D vector (e.g. centroid in 2D plane, or x/z).
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec2 {
/// X-axis component.
pub x: f64,
/// Y-axis component.
pub y: f64,
}

impl Vec2 {
/// Create a new 2D vector from its x and y components.
pub fn new(x: f64, y: f64) -> Self {
Self { x, y }
}
Expand All @@ -24,12 +27,16 @@ impl Vec2 {
/// 3D position (world position, centroid with height).
#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Vec3 {
/// X-axis coordinate.
pub x: f64,
/// Y-axis coordinate.
pub y: f64,
/// Z-axis coordinate.
pub z: f64,
}

impl Vec3 {
/// Create a new 3D vector from its x, y, and z components.
pub fn new(x: f64, y: f64, z: f64) -> Self {
Self { x, y, z }
}
Expand All @@ -46,9 +53,13 @@ impl Vec3 {
/// Per-cluster geometry from SpatialIndex (IN-03). Used for neighbor lists and WorldStateView.
#[derive(Clone, Debug, PartialEq)]
pub struct ClusterGeometry {
/// Unique identifier for this cluster.
pub cluster_id: Uuid,
/// Spatial centroid of the cluster.
pub centroid: Vec3,
/// Maximum distance of any entity from the centroid.
pub spread_radius: f64,
/// Number of entities assigned to this cluster.
pub entity_count: u32,
}

Expand Down
14 changes: 14 additions & 0 deletions crates/arcane-core/src/world_simulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,43 @@ use uuid::Uuid;
/// Last known state of an entity when it was last observed.
#[derive(Clone, Debug)]
pub struct LastKnownState {
/// Unique identifier for this entity.
pub entity_id: Uuid,
/// Timestamp (seconds since epoch) when the entity was last observed.
pub last_observed: f64,
/// Last observed world-space position.
pub position: Vec3,
/// Last observed velocity vector (units per second).
pub velocity: Vec3,
/// Current health value.
pub health: i32,
/// Maximum health value.
pub health_max: i32,
/// Game-defined behavior state (e.g. `"idle"`, `"patrolling"`).
pub behavior_state: String,
/// Spawn or anchor position the entity returns to.
pub home_position: Vec3,
/// Distance from home_position the entity may wander before returning.
pub territory_radius: f64,
}

/// Context at simulation time (optional, for FastForward/ML).
#[derive(Clone, Debug)]
pub struct WorldContext {
/// Current simulation timestamp (seconds since epoch).
pub current_time: f64,
}

/// Plausible state after simulating forward from last_known.
#[derive(Clone, Debug)]
pub struct SimulatedState {
/// Unique identifier for this entity.
pub entity_id: Uuid,
/// Simulated world-space position.
pub position: Vec3,
/// Simulated velocity vector (units per second).
pub velocity: Vec3,
/// Simulated health value.
pub health: i32,
}

Expand Down
Loading