From 5ed6229ed5918cfd8c2e1129cce33cca368e14f5 Mon Sep 17 00:00:00 2001 From: Henning Oschwald Date: Thu, 23 Jul 2026 09:37:59 +0200 Subject: [PATCH] next claude coding session --- PLAN.md | 2 +- src/game_plugin.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 37 ++++----------------- 3 files changed, 89 insertions(+), 31 deletions(-) create mode 100644 src/game_plugin.rs diff --git a/PLAN.md b/PLAN.md index c34734c..cf9b5fa 100644 --- a/PLAN.md +++ b/PLAN.md @@ -23,7 +23,7 @@ Ein barrierefreies Multiplayer-Pokergame für blinde Spieler, das primär über - [x] Projektstruktur aufsetzen (`Cargo.toml`; Modul-Struktur `core`/`audio` bereinigt und verdrahtet). - [x] **Poker Engine**: Hand-Rankings (inkl. Wheel-Straight, 7-Karten-Bestbewertung), Deck-Shuffling/Draw und einfache Betting-Logik (Fold/Check/Call/Raise, All-In) implementiert und getestet. - [x] **Audio-Grundlagen**: `audio::tts` ruft die Web Speech API korrekt an (`SpeechSynthesisUtterance`); auf nativen Targets Dummy-Ausgabe für Tests. -- [ ] Bevy-`App`-Grundgerüst (Plugins/Systems) aufsetzen – noch offen, da die Bevy-0.19-API in dieser Umgebung nicht gegen einen echten Build geprüft werden konnte (siehe Hinweis in `main.rs`). +- [x] Bevy-`App`-Grundgerüst aufgesetzt: `AudiopokerPlugin` (`src/game_plugin.rs`) verdrahtet `core::game`/`core::logic` und `audio` über Bevy-Messages (`Announce`, `PlaySfx`) mit `Startup`/`Update`-Systemen. API-Stand: Bevy 0.19 (`Message`/`MessageWriter`/`MessageReader`/`add_message`, seit 0.17 getrennt von Observer-`Event`s). **Bitte lokal mit `cargo check`/`cargo run` verifizieren**, da hier kein zu Bevy 0.19 passender Compiler zur Verfügung stand. ### Phase 2: Networking & Multiplayer - [ ] Server-Architektur für Spielräume und Spielerverwaltung aufbauen. diff --git a/src/game_plugin.rs b/src/game_plugin.rs new file mode 100644 index 0000000..694569e --- /dev/null +++ b/src/game_plugin.rs @@ -0,0 +1,81 @@ +//! Verbindet die (bewusst Bevy-unabhängige) Kernlogik aus `core` und `audio` +//! mit einer echten Bevy-`App` (siehe PLAN.md, Phase 1: "Bevy Config"). +//! +//! Hinweis zur Bevy-Version: Seit Bevy 0.17 sind gepufferte Events als +//! `Message` (statt `Event`) modelliert und laufen über `MessageWriter` / +//! `MessageReader` / `app.add_message::()`. `Event` bezeichnet seither +//! ausschließlich Observer-Events. Dieser Code ist auf Bevy 0.19 ausgelegt. + +use bevy::prelude::*; + +use crate::audio::AudioEngine; +use crate::core::game::{GameManager, GameState}; +use crate::core::logic::Deck; + +/// Bevy-Resource-Wrapper um den Engine-unabhängigen Spielzustand. +/// Bewusst als Newtype, damit `core::game` selbst keine Bevy-Abhängigkeit braucht. +#[derive(Resource)] +pub struct Table(pub GameState); + +/// Bevy-Resource-Wrapper um die Engine-unabhängige Audio-Engine (`audio::AudioEngine`). +#[derive(Resource)] +pub struct AudioRes(pub AudioEngine); + +/// Message: Ein Text soll per TTS angesagt werden (z. B. "Spieler 1 setzt 50"). +#[derive(Message, Debug, Clone)] +pub struct Announce(pub String); + +/// Message: Ein Soundeffekt soll abgespielt werden (z. B. "shuffle", "chip"). +#[derive(Message, Debug, Clone)] +pub struct PlaySfx(pub &'static str); + +pub struct AudiopokerPlugin; + +impl Plugin for AudiopokerPlugin { + fn build(&self, app: &mut App) { + app.insert_resource(AudioRes(AudioEngine::new())) + .add_message::() + .add_message::() + .add_systems(Startup, setup_game) + .add_systems(Update, (speak_announcements, play_sfx_cues)); + } +} + +/// Startet eine neue Partie, teilt Karten aus und kündigt beides per +/// TTS/SFX-Message an. Läuft einmalig im `Startup`-Schedule. +fn setup_game( + mut commands: Commands, + mut announcements: MessageWriter, + mut sfx_cues: MessageWriter, +) { + let mut game = GameManager::start_new_game(vec!["Spieler 1".into(), "Spieler 2".into()]); + + let mut deck = Deck::new(); + deck.shuffle(); + for player in game.players.iter_mut() { + player.hole_cards = deck.deal_hand(2); + } + game.community_cards = deck.deal_hand(5); + + sfx_cues.write(PlaySfx("shuffle")); + announcements.write(Announce(format!( + "Neues Spiel gestartet mit {} Spielern.", + game.players.len() + ))); + + commands.insert_resource(Table(game)); +} + +/// Liest `Announce`-Messages und spricht sie über die TTS-Engine. +fn speak_announcements(mut reader: MessageReader, audio: Res) { + for Announce(text) in reader.read() { + audio.0.tts.speak(text); + } +} + +/// Liest `PlaySfx`-Messages und spielt den zugehörigen Soundeffekt. +fn play_sfx_cues(mut reader: MessageReader, audio: Res) { + for PlaySfx(id) in reader.read() { + audio.0.sfx.play_sound(id); + } +} diff --git a/src/main.rs b/src/main.rs index c94e4b1..498a9de 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,36 +1,13 @@ mod audio; mod core; +mod game_plugin; -use audio::AudioEngine; -use core::game::GameManager; -use core::logic::Deck; +use bevy::prelude::*; +use game_plugin::AudiopokerPlugin; -// TODO(Phase 1 Rest / Phase 3): echte Bevy-`App` mit Plugins/Systems -// aufsetzen, sobald die Bevy-0.19-API-Oberfläche geprüft ist. Ohne -// funktionierende Rust-Toolchain in dieser Umgebung wollte ich hier -// keinen ungeprüften Bevy-Boilerplate-Code hinterlassen, der eventuell -// gegen die tatsächliche 0.19-API nicht kompiliert. Stattdessen dient -// main() aktuell als Smoke-Test für die bisher fertiggestellte -// Poker-Engine (Deck/Hand/Betting) und die Audio-Anbindung. fn main() { - let audio_engine = AudioEngine::new(); - - let mut game = GameManager::start_new_game(vec!["Spieler 1".into(), "Spieler 2".into()]); - - let mut deck = Deck::new(); - deck.shuffle(); - - for player in game.players.iter_mut() { - player.hole_cards = deck.deal_hand(2); - } - game.community_cards = deck.deal_hand(5); - - audio_engine.tts.speak("Neues Spiel gestartet."); - audio_engine.sfx.play_sound("shuffle"); - - println!( - "Spiel gestartet mit {} Spielern, Runde: {:?}", - game.players.len(), - game.current_round - ); + App::new() + .add_plugins(DefaultPlugins) + .add_plugins(AudiopokerPlugin) + .run(); }