From f181bf4de900d028121f16f03973fb02bfd14993 Mon Sep 17 00:00:00 2001 From: irrlicht Date: Wed, 1 Jul 2026 00:31:34 +0200 Subject: [PATCH] Renamed Play State --- src/cli.rs | 2 +- src/render/mod.rs | 2 +- src/render/ui.rs | 2 +- src/session.rs | 58 ++++++++++------------------------------------- 4 files changed, 15 insertions(+), 49 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index af322dd..36bcdc5 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -29,7 +29,7 @@ fn prompt_for(mode: &Mode) -> &'static str { Mode::Dialog(d) if !d.choices.is_empty() => " wahl> ", Mode::Dialog(_) => " [Enter] ", Mode::Menu => "menü> ", - Mode::Play => "spiel> ", + Mode::FirstPerson => "spiel> ", Mode::Free => "> ", } } diff --git a/src/render/mod.rs b/src/render/mod.rs index e82bf99..a831cc1 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -339,7 +339,7 @@ impl App { // die Maus (relativer Blick); Menü/Dialog geben sie frei fürs UI. So // gibt es keine parallele Lock-Logik. let fly = matches!(self.session.mode, Mode::Free); - let play = matches!(self.session.mode, Mode::Play); + let play = matches!(self.session.mode, Mode::FirstPerson); let grab = fly || play; if grab != self.input.grabbed { self.set_grab(grab); } diff --git a/src/render/ui.rs b/src/render/ui.rs index e9f7c52..13aa015 100644 --- a/src/render/ui.rs +++ b/src/render/ui.rs @@ -228,7 +228,7 @@ pub(crate) fn layout(internal: [f32; 2], fonts: &Fonts, session: &Session, cur: match &session.mode { // Spiel und Flycam: nur HUD/Cursor, kein Panel (beide laufen // ohnehin gefangen — dieser Zweig greift nur im Übergang). - Mode::Play | Mode::Free => {} + Mode::FirstPerson | Mode::Free => {} Mode::Menu => menu(&mut ui, f, internal, cur.pos, &mut hover), Mode::Dialog(d) => dialog(&mut ui, f, internal, d, cur.pos, &mut hover), } diff --git a/src/session.rs b/src/session.rs index 6c0ff49..6f70d91 100644 --- a/src/session.rs +++ b/src/session.rs @@ -1,22 +1,3 @@ -//! Session: der geteilte Anwendungszustand über allen Frontends. -//! -//! Es existiert genau eine `Session` pro Lauf. CLI und Fenster steuern -//! dieselbe — das Fenster besitzt sie, die Terminal-Eingabe schickt nur -//! Befehlszeilen hinein. Dadurch kann es keinen Mismatch geben: ein -//! `Game`-Zustand, ein `Mode`, beide Frontends stellen ihn nur dar. -//! -//! Schicht: `engine ← session ← { cli, render }`. Die Session kennt kein -//! Frontend — `exec` nimmt eine Befehlszeile und *gibt* Ausgabezeilen -//! zurück (statt zu drucken), damit jedes Frontend sie frei darstellt -//! (Terminal jetzt, In-Fenster-Konsole später). -//! -//! Die Session ist auch der alleinige Besitzer der **Lauf-Simulation**: -//! `Player` und `CollisionWorld`. Sie hat zwei Eingabe-Tore — `exec` für -//! diskrete Befehle/Dialog und `tick` für die kontinuierliche Physik pro -//! Frame. Die Frontends sammeln nur Eingaben und stellen den Zustand dar; -//! die Flycam dagegen ist reine Frontend-Sicht (kein Sim-Zustand) und bleibt -//! im `render`-Modul. - use crate::engine::collision::CollisionWorld; use crate::engine::game::{Action, Game, ModeTarget}; use crate::engine::ink::StoryState; @@ -27,28 +8,13 @@ use crate::engine::{kv, signals, story_ctrl}; /// Maus-Empfindlichkeit der Spieler-Sicht (Radiant/Pixel). const LOOK_SENS: f32 = 0.0025; -/// Was die Frontends gerade darstellen sollen. Geteilt, damit CLI und GUI -/// nie uneins sind, ob ein Dialog läuft. pub enum Mode { - /// First-Person-Spiel — der Player bewegt sich mit Physik durch die Welt - /// (siehe engine::player). Der Renderer leitet seine View aus dem Player - /// ab. Das ist der eigentliche Spielmodus. - Play, - /// Noclip-Debug-Flycam — frei schwebende Kamera ohne Physik. Per - /// `noclip`-Befehl gegen `Play` getauscht. + FirstPerson, Free, - /// Menü offen — wie der Dialog pausiert das Fenster die Welt und gibt die - /// Maus frei; Eingaben sind weiter Engine-Befehle (das Menü ist nur eine - /// andere Darstellung). Per `menu`-Befehl getoggelt; „Fortsetzen" führt - /// ins Spiel (`Play`). Menu, - /// Ein Dialog läuft — das Fenster pausiert die Welt und zeigt Panels; - /// Eingaben treiben den Dialog statt Befehle. Dialog(Dialog), } -/// Aktueller Dialogschritt, frontend-neutral. `choices` leer = reiner Text, -/// der auf „weiter" (Leerzeile/Enter) wartet. pub struct Dialog { // Wird vom Panel-Renderer der UI-Phase gelesen; bis dahin läuft der // Dialogtext über die Konsolen-Ausgabe (siehe `step`). @@ -115,7 +81,7 @@ impl Session { /// `exec`. Nur im Spielmodus bewegt sich der Spieler; Menü/Dialog/Flycam /// pausieren die Sim (die Flycam ist reine Frontend-Sicht). pub fn tick(&mut self, input: &FrameInput, dt: f32) { - if matches!(self.mode, Mode::Play) { + if matches!(self.mode, Mode::FirstPerson) { self.player.look(input.look_dx, input.look_dy, LOOK_SENS); self.player.step(&self.collision, input.fwd, input.right, input.jump, dt); } @@ -135,7 +101,7 @@ impl Session { pub fn exec(&mut self, line: &str) -> ExecResult { match self.mode { Mode::Dialog(_) => self.dialog_input(line), - Mode::Play | Mode::Free | Mode::Menu => self.command(line), + Mode::FirstPerson | Mode::Free | Mode::Menu => self.command(line), } } @@ -159,7 +125,7 @@ impl Session { // Debug: zwischen First-Person (Play) und freier Flycam (Free) // umschalten. let t = match self.mode { - Mode::Play => ModeTarget::Free, + Mode::FirstPerson => ModeTarget::Free, _ => ModeTarget::Play, }; self.set_mode(t); @@ -219,7 +185,7 @@ impl Session { // geladen haben, während die alte auf End lief (mode → Play). Falls // das passiert ist, sofort den ersten Schritt der neuen Story ziehen // statt den Spieler im Play-Modus hängen zu lassen. - if self.game.story.is_some() && matches!(self.mode, Mode::Play) { + if self.game.story.is_some() && matches!(self.mode, Mode::FirstPerson) { out.extend(self.step(None)); } ExecResult::lines(out) @@ -252,7 +218,7 @@ impl Session { let mut out = self.drain_actions(); match state { None | Some(StoryState::End) => { - self.mode = Mode::Play; + self.mode = Mode::FirstPerson; } Some(StoryState::Text(text)) => { out.push(text.clone()); @@ -293,7 +259,7 @@ impl Session { /// entsteht ausschließlich in `step` aus dem Story-Ablauf.) fn set_mode(&mut self, t: ModeTarget) { self.mode = match t { - ModeTarget::Play => Mode::Play, + ModeTarget::Play => Mode::FirstPerson, ModeTarget::Free => Mode::Free, ModeTarget::Menu => Mode::Menu, }; @@ -376,7 +342,7 @@ mod tests { s.exec("menu"); assert!(matches!(s.mode, Mode::Menu)); s.exec("menu"); // „Fortsetzen" → ins Spiel - assert!(matches!(s.mode, Mode::Play)); + assert!(matches!(s.mode, Mode::FirstPerson)); s.exec("menu"); // aus dem Spiel wieder ins Menü assert!(matches!(s.mode, Mode::Menu)); // Im Menü laufen Engine-Befehle weiter (gleiche Route wie Play/Free). @@ -388,7 +354,7 @@ mod tests { fn mode_command_sets_mode_directly() { let mut s = empty_session(); s.exec("mode play"); - assert!(matches!(s.mode, Mode::Play)); + assert!(matches!(s.mode, Mode::FirstPerson)); s.exec("mode free"); assert!(matches!(s.mode, Mode::Free)); s.exec("mode menu"); @@ -405,17 +371,17 @@ mod tests { s.mode = Mode::Free; // `mode`-Verb direkt als Action (Ink-Tag-/signals.toml-Pfad). s.exec("signal mode play"); - assert!(matches!(s.mode, Mode::Play)); + assert!(matches!(s.mode, Mode::FirstPerson)); } #[test] fn noclip_toggles_play_and_free() { let mut s = empty_session(); - s.mode = Mode::Play; + s.mode = Mode::FirstPerson; s.exec("noclip"); assert!(matches!(s.mode, Mode::Free)); s.exec("noclip"); - assert!(matches!(s.mode, Mode::Play)); + assert!(matches!(s.mode, Mode::FirstPerson)); } #[test]