feat(server): initialize Rust/bevy_ecs simulation server
Server boilerplate epic (276) complete. Establishes the Rust simulation server foundation per D-020 (subprocess/IPC architecture). Structure: - bevy_ecs 0.18 + bevy_app 0.18, MessagePack serialization (rmp-serde) - SimulationPlugin with deterministic resources: SimulationTime (D-031), SimRng (D-030), InputQueue (D-010) - Core IPC types: ObserverSnapshot, PlayerInput, SimBridge trait (D-020) - CauseChain production component for provenance tracking (D-030) - SimulationTier types with LRU eviction support (D-026) - NPC 10-axis model components (D-024) - 15 tests: inline unit tests + integration smoke/serialization tests - make ci-server passes (clippy, fmt, build, test) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
// Bridge module - Client-server communication
|
||||
// Implements D-020 subprocess/IPC architecture
|
||||
// MessagePack serialization for Rust<->Godot communication
|
||||
|
||||
use bevy_app::prelude::*;
|
||||
|
||||
pub mod types;
|
||||
pub use types::*;
|
||||
|
||||
/// Error type for bridge operations
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum BridgeError {
|
||||
#[error("serialization error: {0}")]
|
||||
Serialization(#[from] rmp_serde::encode::Error),
|
||||
#[error("deserialization error: {0}")]
|
||||
Deserialization(#[from] rmp_serde::decode::Error),
|
||||
#[error("transport error: {0}")]
|
||||
Transport(String),
|
||||
}
|
||||
|
||||
/// Abstracts transport layer (D-020)
|
||||
/// Implemented by LocalBridge (stdio) and future NetworkBridge
|
||||
pub trait SimBridge: Send + Sync {
|
||||
/// Send an observer snapshot to the client
|
||||
fn send_snapshot(&self, snapshot: &ObserverSnapshot) -> Result<(), BridgeError>;
|
||||
|
||||
/// Receive player inputs from the client
|
||||
fn receive_inputs(&self) -> Result<Vec<PlayerInput>, BridgeError>;
|
||||
}
|
||||
|
||||
/// Bridge plugin for client-server communication
|
||||
/// Abstracts transport layer (LocalBridge/NetworkBridge)
|
||||
pub struct BridgePlugin;
|
||||
|
||||
impl Plugin for BridgePlugin {
|
||||
fn build(&self, _app: &mut App) {
|
||||
// Stub implementation - will be populated in phase 2
|
||||
tracing::debug!("BridgePlugin initialized");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Bridge type definitions
|
||||
// ObserverSnapshot: data crossing the client-server boundary
|
||||
// PlayerInput: semantic actions from client
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The ONLY data structure crossing the client-server boundary (D-020)
|
||||
/// Contains all information visible to the observer at a given tick
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ObserverSnapshot {
|
||||
/// Simulation tick when this snapshot was produced
|
||||
pub tick: u64,
|
||||
/// All entities visible to the observer
|
||||
pub entities: Vec<VisibleEntity>,
|
||||
}
|
||||
|
||||
/// A visible entity in the simulation
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VisibleEntity {
|
||||
pub entity_id: u64,
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: i32,
|
||||
pub kind: EntityKind,
|
||||
}
|
||||
|
||||
/// Category of visible entity
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum EntityKind {
|
||||
Npc,
|
||||
Object,
|
||||
Terrain,
|
||||
}
|
||||
|
||||
/// Semantic player actions, not raw key events (D-020)
|
||||
/// Timestamped for deterministic processing
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PlayerInput {
|
||||
/// Tick when this input was issued
|
||||
pub tick: u64,
|
||||
/// The action to perform
|
||||
pub action: PlayerAction,
|
||||
}
|
||||
|
||||
/// Player action variants
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum PlayerAction {
|
||||
MoveNorth,
|
||||
MoveSouth,
|
||||
MoveEast,
|
||||
MoveWest,
|
||||
Interact,
|
||||
UsePerceptionMode(String),
|
||||
Pause,
|
||||
Unpause,
|
||||
}
|
||||
Reference in New Issue
Block a user