This commit is contained in:
2026-06-13 02:57:22 +02:00
parent 802f2bd34b
commit 2dd338c890
9 changed files with 188 additions and 150 deletions
+68
View File
@@ -0,0 +1,68 @@
//! Owner des dispatch-relevanten Spielzustands und der Borrow-View, durch
//! die Signal-Actions und Ink-Story-Steps darauf zugreifen.
//!
//! `Game` hält die Slots, die Actions lesen oder mutieren dürfen.
//! `ActionCtx` ist der schmale `&mut`-View; er wird über `Game::action_ctx()`
//! konstruiert und durch die Dispatch-Pipeline gereicht.
//!
//! Verben, deren Ziel-Subsystem (Szene, Audio, Renderer) noch nicht
//! existiert oder den Kern nichts angeht, produzieren [`Action`]-Werte
//! statt direkt zu wirken. Frontends konsumieren die Queue: die CLI druckt
//! sie, die Engine führt sie später aus. So bleibt der Kern headless
//! testbar und kennt keines der Subsysteme.
use std::collections::HashMap;
use crate::engine::ink;
use crate::engine::kv::Store;
/// Signal-Table aus `assets/signals.toml`: Signal-Name → Action-Strings.
/// Geladen/geparst von [`crate::engine::signals`]; definiert ist der Typ
/// hier beim Zustand, damit `game` ← `signals` eine Einbahnstraße bleibt.
pub type Signals = HashMap<String, Vec<String>>;
/// Action, die der Kern nicht selbst ausführt, sondern ans Frontend
/// weiterreicht. Die Queue in `Game::actions` gehört nach jedem Dispatch
/// geleert (konsumiert).
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Action {
/// Instance unsichtbar + kollisionslos + nicht mehr interagierbar machen.
HideObject(String),
/// WAV unter `assets/audio/<name>` als SFX abspielen.
PlaySound(String),
}
pub struct Game {
pub kv: Store,
pub signals: Signals,
pub story: Option<ink::Story>,
pub actions: Vec<Action>,
}
pub struct ActionCtx<'a> {
pub kv: &'a mut Store,
pub signals: &'a Signals,
pub story: &'a mut Option<ink::Story>,
pub actions: &'a mut Vec<Action>,
/// Auslöser-Identifier: bei Objekt-Interaktion der volle Instance-Name
/// (mit Blender-Suffix, z.B. `Mushroom.005`). `$self` in Action-Args
/// wird damit substituiert. `None` bei Signalen ohne Quell-Instance
/// (z.B. `init`, Story-Tags).
pub instance_name: Option<String>,
}
impl Game {
pub fn new(signals: Signals) -> Self {
Self { kv: Store::new(), signals, story: None, actions: Vec::new() }
}
pub fn action_ctx(&mut self, instance_name: Option<String>) -> ActionCtx<'_> {
ActionCtx {
kv: &mut self.kv,
signals: &self.signals,
story: &mut self.story,
actions: &mut self.actions,
instance_name,
}
}
}