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:
2026-02-11 16:54:40 +01:00
co-authored by Claude Opus 4.6
parent 84925b334a
commit f67caf1986
18 changed files with 2036 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
// Simulation tier system
// Implements D-026: Active/Background/State-saved/Ungenerated tiers
// Timestamp-based LRU eviction for simulation space management
use bevy_ecs::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Component, Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum SimulationTier {
Active,
Background,
StateSaved,
Ungenerated,
}
#[derive(Component, Debug, Clone)]
pub struct LastInteraction {
pub tick: u64,
}
#[derive(Component, Debug, Clone)]
pub struct ScopeTag {
pub tags: Vec<ScopeKind>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ScopeKind {
Neighborhood,
ActiveQuest,
Colleague,
KnownContact,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tier_can_be_added_and_queried() {
let mut world = bevy_ecs::world::World::new();
let entity = world.spawn(SimulationTier::Active).id();
assert_eq!(
*world.get::<SimulationTier>(entity).unwrap(),
SimulationTier::Active
);
}
#[test]
fn tier_can_transition() {
let mut world = bevy_ecs::world::World::new();
let entity = world.spawn(SimulationTier::Active).id();
world.entity_mut(entity).insert(SimulationTier::Background);
assert_eq!(
*world.get::<SimulationTier>(entity).unwrap(),
SimulationTier::Background
);
}
}