Security & infrastructure: - Remove unused services/ (auth, spacetimedb) and auth.db - Add .env.example template, expand .gitignore for env/db files - Add GitHub Actions CI + commitlint config and workflows - Add manual vendor chunking and source maps to docs/site vite configs Shared UI & docs app: - Add ARIA props and focus-visible rings to Button/Panel - Add ButtonAsLink primitive; use shared Button in NotFound - Wire @void-nav/ui into docs app; refresh content pages - Replace Todo page with Kanban board Gameplay (Bevy): - Add ai module (behavior, faction, navigation, perception, spawning, states) - Add narrative module (events, history, synthesis, ui) - Refine galaxy contents and in-system flight/scene systems
5.3 KiB
5.3 KiB
VOID::NAV - AI Agent Guidelines
Project Overview
VOID::NAV is a single-player narrative-driven space exploration game built with:
- Rust + Bevy 0.16 for the game client (
apps/game/) - TypeScript + React for docs and site (
apps/docs/,apps/site/) - pnpm workspace monorepo structure
Key Technical Patterns
Bevy ECS Architecture
- The game uses Bevy's Entity Component System with state-based gameplay
- States: MainMenu, Galaxy, CharacterCreation, StartingBaseSelection, InGame, Options
- Systems use
run_if(in_state(AppState::InGame))for state-gated execution - Components are organized by feature module (ai, movement, galaxy, narrative, etc.)
Time API (Bevy 0.16)
- Use
time.delta_secs()NOTtime.delta_seconds()for delta time - Time is accessed as
Res<Time>and auto-derefs for method calls - Example:
time.delta_secs().min(0.1)for clamped delta time
Component Organization
- Components are in
components.rssubmodules (e.g.,movement::components::MoveTarget) - Always use full import paths:
use crate::gameplay::movement::components::MoveTarget; - Movement components:
Player,Velocity,MaxSpeed,TurnRate,MoveTarget
Plugin Pattern
- Each feature has a Plugin struct that implements
Plugin::build() - Plugins are added to the app in
main.rs - Example plugin structure:
pub struct FeaturePlugin; impl Plugin for FeaturePlugin { fn build(&self, app: &mut App) { app.init_resource::<FeatureConfig>() .add_event::<FeatureEvent>() .add_systems(Update, feature_system.run_if(in_state(AppState::InGame))); } }
Resource and Event Patterns
- Resources: Use
init_resource::<T>()for app-wide state (config, history) - Events: Use
add_event::<T>()for event-driven communication - Event readers in systems:
EventReader<T>for consuming events - Event writers:
EventWriter<T>for sending events
ActiveSystem Pattern
ActiveSystemresource tracks the current gameplay system- Contains:
system_id,system_name,star_entity - Note: Does NOT contain full system data (security, faction) - use defaults or look up
Module Organization
Game Structure
apps/game/src/
├── main.rs # App entry point, plugin registration
├── camera.rs # Camera system with orbit/follow modes
├── state.rs # AppState enum
├── ui.rs # UI systems
└── gameplay/
├── mod.rs # Re-exports all gameplay modules
├── ai/ # NPC AI with state machines
├── movement/ # Movement components and systems
├── galaxy/ # Galaxy generation and viewing
├── in_system/ # In-system gameplay
├── narrative/ # Event logging and campaign history
├── character_creation/
├── starting_base/
└── campaign.rs # Campaign persistence
Adding New Features
- Create feature module under
gameplay/ - Create Plugin struct in
mod.rs - Add to
gameplay/mod.rspub exports - Register in
main.rsapp builder - Use
run_if(in_state(...))for state-gated systems
Common Issues
Borrow Checker in Loops
- Cannot have both mutable and immutable borrows of same Query in loop
- Solution: Restructure logic, avoid nested queries of same data
- Use intermediate values or separate systems for complex queries
Move Semantics with Clones
- String values moved into structs can't be reused
- Solution: Clone before use or restructure order
- Example:
name: npc_name.clone()preserves original
Import Paths
- Always use full crate paths for imports
- Components often in
components.rssubmodules - Check existing code for correct import patterns
Development Workflow
Testing Compilation
cd apps/game && cargo check
# or from root with proper path
cargo check
Running the Game
pnpm dev # Start docs and site
cargo run # Run game client (from apps/game directory)
Project-Specific Patterns
AI System
- State machine with: Idle, Patrol, Combat, Flee, Mining, Trading
- NPC spawning based on system security level
- Faction-based behavior profiles (Concord, Amarr, Minmatar, etc.)
- Perception system for detecting player and other entities
Narrative System
- Event logging captures all player actions
- Campaign history maintains timeline with chapters
- Chapter detection based on event count and theme analysis
- LLM synthesis planned for future (placeholder exists)
Galaxy Generation
- Procedural spiral galaxy with core, disks, and beams
- Each system has faction, security, and POI contents
- Nearest-neighbor connections for stargate routes
- POI types: planets, stations, asteroid belts, anomalies, gas clouds
Current State
Recently Implemented
- Multiplayer Removed: SpacetimeDB and auth services deleted
- AI Foundation: Complete state machine AI with 6 behavior states
- Narrative Foundation: Event logging and campaign history tracking
- Kanban Updated: Narrative items moved to TODO with sub-items
Next Priorities (from Kanban)
- Complete in-system gameplay (docking, mining operations)
- Add flight HUD/in-game UI
- Implement narrative synthesis engine (LLM integration)
- Add story log UI for campaign viewing