DDD-/TDD-Migrationsanalyse
Stand: 2026-09-01. Der Code ist die maßgebliche Quelle. Dieses Dokument beschreibt eine inkrementelle Migration; es autorisiert keinen Big-Bang-Umbau und keine stillen Verhaltensänderungen.
1. Executive Summary
Die Solution ist bereits ein modularer Monolith mit einer brauchbaren Domänengrenze: HolodeckArena.Shared enthält umfangreiche, Godot-freie Regeln für Dungeon-Generierung, Combat, Waffen, Power-ups, Drops, Objectives, Runs, Scoring und Replay. HolodeckArena.Networking ist ebenfalls Godot-frei. HolodeckArena.Game3D verbindet diese Regeln mit Nodes, Scenes, UI, Nakama und lokalen Speichern.
DDD ist daher keine Neuentwicklung, sondern eine Präzisierung bestehender Grenzen. Der größte Nutzen liegt in deterministischen Spielregeln und zustandsreichen Abläufen. Kamera, Rendering, Audio, Input-Mapping und Scene-Wiring bleiben bewusst Godot-spezifisch. Zunächst werden bestehende Regeln mit Characterization-, Determinism- und Golden-Master-Tests eingefroren. Danach delegiert vorhandener Code per Strangler Pattern schrittweise an klar benannte Domain- und Application-Bausteine.
Die größten Risiken sind derzeit nicht fehlende Basisklassen, sondern große Godot-Controller, gemischte Zeit-/Zufallsquellen, konzeptionell poröse Modulgrenzen und unterschiedliche Modelle für denselben Begriff. Neue Assemblies sind zunächst nicht erforderlich.
2. Ist-Architektur
| Bereich | Heutige Verantwortung | Beobachtung |
|---|---|---|
src/HolodeckArena.Shared |
Bootstrap-Helfer und Godot-freie Spielregeln | Bestehender Domain-Kern; fachliche Modulgrenzen sind noch durchlässig. |
src/HolodeckArena.Game3D |
Godot Nodes/Scenes, Application-Orchestrierung, lokale Adapter, Nakama-Integration | Presentation, Application und Infrastructure liegen teilweise im selben Feature-Ordner. |
src/HolodeckArena.Networking |
Transport- und Netzwerkverträge | Technisches Shared Kernel; keine Godot-Abhängigkeit. |
| Bootstrap-/Installer-/Launcher-/Updater-Projekte | Installation, Start und Updates | Eigenständige technische Subdomäne; kein Gameplay-DDD nötig. |
src/server/nakama/modules |
Autoritative RPCs, Validierung und Persistenzprojektionen | Serveradapter mit fachlich relevanten Verträgen; Contract-Tests sind entscheidend. |
tests/HolodeckArena.Game3D.Tests |
xUnit für Shared- und Game3D-Code | Breite Abdeckung wichtiger Regeln, aber kaum echte SceneTree-/Backend-Integration. |
tests/HolodeckArena.Bootstrap.Tests |
xUnit für Bootstrap | Gut isolierte technische Tests. |
Die größten Klassen (DungeonRun3DController, DungeonEnemy3D, PlayerController, ReplayViewerController) bündeln Engine-Lifecycle, Darstellung, Netzwerk und fachliche Entscheidungen. Globale Zugriffe wie DungeonCombatNetworkSync.Instance und EventBus-basierte Abläufe erschweren isolierte Tests. Direkte Datei- und Nakama-Zugriffe sind überwiegend bereits auf Adapterklassen begrenzt.
Architekturprobleme und offene Befunde
- Der zuvor mit
HashCode.Combineerzeugte Boss-Auswahl-Seed wurde in Phase 4 auf die versionierteStableSeedDerivationumgestellt. Der Befund ist behoben und durch eine exakte Sequenz-Baseline geschützt. RunCompletionServiceverwendet seit Phase 3IGameClock;RunSubmissionValidatorliest für den reinen Validierungszeitstempel weiterhinDateTimeOffset.UtcNowdirekt. Der Wert beeinflusst weder Replay-Regeln noch Score und rechtfertigt derzeit keinen zusätzlichen Port.- Mehrere Echtzeitpfade verwenden
Time.GetTicksMsec(). Rendering/Animation dürfen das; Run-Dauer, Replay-Ticks und autoritative Commands brauchen eine kontrollierte Simulationszeit. BossAttackSelector,RoomTemplateSelectorundSeededRandomverwenden seit Phase 4 den explizit versioniertenDeterministicRandom. Algorithmuswechsel werden durch Domain- und Generator-Golden-Masters sichtbar.RunCategory,ModifierOperation, Health-/Vital-State und Run-Result-Modelle existieren in mehreren Varianten. Diese Duplikate werden nicht pauschal zusammengelegt; zuerst ist ihre Semantik zu klären.- Der aktuelle Ausgangsstand enthält drei rote xUnit-Fälle wegen eines veralteten UI-Textformats (
+20 %gegenüber Codeverhalten+20%) und einen roten Nakama-Test mit der früheren Chunk-Grenze 64 statt 128. Das sind Baseline-Abweichungen, keine Rechtfertigung für Produktionsänderungen. - TypeScript-Quelle und eingechecktes
build/main.jsverwenden unterschiedliche Replay-Limits. Der Build-/Deployment-Vertrag muss separat geklärt werden.
3. Fachliche Cluster und DDD Assessment
Bewertung: A = sehr gut geeignet, B = Domain Core extrahieren/erhalten, C = bewusst technisch bzw. präsentationsnah lassen.
| Cluster | Eignung | Begründung | Vorteile | Nachteile | Empfehlung |
|---|---|---|---|---|---|
| Stats und Modifikatoren | A | Reihenfolge, Stacks und Quellen sind Regeln. | Schnelle Grenzwerttests; gemeinsame Sprache. | Mapping zu UI-Ressourcen. | Als Domain Core beibehalten; Operation-Duplikat klären. |
| Damage, Health, Armor | A | Invarianten und Zustandsübergänge; bereits weitgehend rein. | Zentrale Combat-Semantik. | Game3D-Events müssen adaptiert werden. | CombatantVitalState konsolidieren; Godot-Fassade zunächst erhalten. |
| Waffen und Munition | A | Fire-Policies, Cooldowns, Ammo und Validierung sind regelreich. | Client/Server-Parität; Replay-Sicherheit. | Umfangreiche Konfiguration und Mapping. | DDD vollständig für Regeln; VFX/Nodes außerhalb. |
| Autoritativer Combat | A | Sessionzustand, Idempotenz, Treffer und Replay-Ereignisse. | Deterministische Servertests. | Aktuelle Klasse hat viele Verantwortlichkeiten. | Aggregate schrittweise zerlegen, nicht neu schreiben. |
| Loadouts | A | Slot-, Unlock- und Run-Policy-Invarianten. | Früh validierbar und wiederverwendbar. | Abhängigkeit zu Progression/Weapons/Runs. | Aggregate/Policy, Grenzen explizit machen. |
| Power-ups, Buffs, Debuffs | A | Stacks, Ausschlüsse, Dauer und Choice-Idempotenz. | Hoher Testwert; deterministische Hashes. | Effekte brauchen Adapter zu Stats/Godot. | RunPowerUpState als Aggregate weiterentwickeln. |
| Drops und Rewards | A | Seed, Quellen, Zustandsübergänge und Auswahlregeln. | Reproduzierbare Runs. | Spawn-Visualisierung bleibt Godot. | Domain Schedule/State; Spawn als Adapter. |
| Objectives | A | Fortschritt, Bossanforderungen und einmaliger Abschluss. | Klare Invarianten und Events. | Signals müssen sauber übersetzt werden. | Eigenständiger Domain-Baustein im Run Context. |
| Run Lifecycle und Completion | A | Start/Abschluss/Abbruch, Idempotenz, Resultatbildung. | Zentraler Konsistenzpunkt. | Heutiger Service mischt Clock/Persistenz/Awards. | Schlankes Run-Aggregate plus Application Use Cases. |
| Scoring und Medals | A | Versionierte, leaderboard-relevante Berechnung. | Golden Masters; Server/Client-Parität. | Jede Regeländerung braucht Versionierung. | Vollständig Domain; Strategien versionieren. |
| Seed und Determinismus | A | Reproduzierbarkeit ist fachliche Garantie. | Replay- und Debug-Sicherheit. | Abstraktionen können übertrieben werden. | Stabiler RNG/Hash als Domain Service; Clock nur an relevanten Grenzen. |
| Dungeon-/Run-Definition | A | Seed erzeugt unveränderliche, prüfbare Run-Struktur. | Golden Masters und Servervalidierung. | Große Snapshots und Mappingaufwand. | Factory/Domain Service; Ergebnis als immutable Artifact. |
| Raum-/Levelinstanziierung | B | Auswahlregeln fachlich, Scene-Aufbau technisch. | Generator getrennt von Godot ladbar. | Zwei Repräsentationen bleiben nötig. | Auswahlkern extrahieren; Scene-Spawning Godot lassen. |
| Gegnerzustand und KI | B | Combat-/Phasenregeln fachlich; Navigation/Physics technisch. | Decision-Tests ohne SceneTree. | Synchronisation zwischen State und Node. | Pure Decision Policies; Bewegung/Navigation im Adapter. |
| Boss Encounters | B | Phasen, Attack-Auswahl und Rewards fachlich. | Seedbare Phasentests. | Animation, Navigation und Telegraphing eng an Godot. | Domain Core für Phase/Attack; Node orchestriert Darstellung. |
| Spawn und Respawn | B | Budgets/Regeln fachlich; Instanziierung technisch. | Determinism- und Grenzwerttests. | Scene-/Authority-Kopplung. | Policy + Godot/Online Adapter. |
| Replay-Erzeugung | A | Versioniertes Ereignismodell und Reihenfolge. | Refactoring-Sicherheitsnetz. | Aufnahmequelle bleibt Adapter. | Immutable Replay Domain Artifact; Recorder als Application Port. |
| Replay-Validierung | A | Integrität, Timeline und Regelprüfung. | Betrugsschutz; Serverparität. | Volle Simulation wäre teuer. | Validierungs-Policies trennen; Level explizit benennen. |
| Replay-Upload/-Storage | B | Workflow/Idempotenz relevant, Transport technisch. | Contract- und Recovery-Tests. | Viel Protokoll-Boilerplate. | Application State Machine plus Infrastructure Adapter. |
| Progression/Mastery | A | Unlocks und Fortschrittsinvarianten. | Deterministische Profiltests. | Persistenz-/Migrationsversionen. | Späteres Aggregate ProgressionProfile. |
| Leaderboard | B | Scoreannahme ist fachlich; RPC/SQL/UI technisch. | Manipulationsschutz. | Duplizierte Verträge über C#/TS/SQL. | Submission Use Case; Nakama/SQL als Adapter. |
| Online Session/Matchmaking | B | Sessionzustand und Commands, aber transportnah. | Testbare Zustandsmaschine. | Nakama-Lifecycle bleibt extern. | Application Service; kein großes Domain-Modell. |
| Backend/API/Nakama | C | Externe Technologie. | Klare Ports erleichtern Tests. | Mappingaufwand. | Infrastructure Adapter, keine Entities. |
| Persistenz/Dateisystem | C | Technische Speicherung. | Austauschbare Integrationstests. | Zusätzliche DTO-Mappings. | Adapter hinter Use-Case-spezifischen Ports. |
| Settings | B | Validierung/Defaults teilweise regelhaft; Speicherung/UI technisch. | Pure Validation möglich. | Geringer Fachwert. | Kleine Policies, ansonsten Application/Infrastructure. |
| Input und Movement | C/B | Input-Mapping technisch; erlaubte Aktionen teils fachlich. | Command-Grenze entkoppelt Godot. | Physik bleibt Engine-abhängig. | Input/Physics Godot; nur Action-Gates in Domain. |
| UI/HUD | C | Projektion und Darstellung. | Dünne Presenter gut testbar. | DDD bringt keinen Mehrwert. | Presentation Mapper testen; bewusst Godot-spezifisch. |
| Kamera, Audio, VFX, Animation | C | Rein technische/präsentative Wirkung. | Weniger Architektur-Overhead. | Weniger Unit Tests. | Kein DDD; wenige Godot-Smoke-Tests. |
| Bootstrap/Launcher/Updater | C | Technische Produktinfrastruktur. | Bestehende isolierte Tests genügen. | Getrennte Fehlerdomäne. | Kein Gameplay-DDD; modulare Services beibehalten. |
4. Vorgeschlagene Bounded Contexts
Run (Core Domain)
├── Objectives
├── Combat (Core Domain)
│ ├── Weapons
│ ├── Vital Stats
│ └── Effects
├── Scoring (Core Domain)
└── Replay (Core/Supporting)
└── Validation
Loadout (Supporting Domain) ──policy/snapshot──> Combat
Progression (Supporting Domain) ──unlocks──> Loadout
Procedural Generation (Core Domain) ──RunDefinition──> Run
Run ──Submission──> Leaderboard (Supporting Domain)
Online Session (Supporting Domain) ──commands──> Run/Combat
Godot Presentation, Nakama, SQL, HTTP, Filesystem, Networking
└── Generic Subdomains / Infrastructure Adapters
Context-Beziehungen verwenden bewusst Snapshots und Commands statt fremder, veränderlicher Objekte. RunDefinition, LoadoutSnapshot, CombatResult, RunResult und versionierte Replay-/Submission-Verträge sind Kandidaten für Published Language. Run ist kein Sammel-Aggregate für den kompletten Spielzustand: Combat, Objectives und Replay dürfen eigene Konsistenzgrenzen behalten.
5. Gezielte DDD-Bausteine
| Modell | Root / Bestandteile | Invarianten und Commands | Sinnvolle Events |
|---|---|---|---|
| Combat Session | AuthoritativeDungeonCombatSession; Combatants, zwei Weapon Slots, Ammo Value State |
eindeutige Instanz-IDs; aktive Session/Spieler; monotone Sequenzen; Fire, Reload, SwitchWeapon, UpdatePose |
ShotResolved, CombatantDefeated; nicht jede Ammo-Änderung. |
| Run Lifecycle | neue kleine RunLifecycle; Run-ID, Status, Zeitfenster, Objective Summary |
genau ein Start/Terminalzustand; Start, Complete, Abort |
RunCompleted, RunAborted. Persistenz folgt im Application Layer. |
| Objective Progress | bestehender DungeonObjectiveTracker; Defeat-IDs und Progress |
Kill nur einmal; konfigurierte Spawn-Ursprünge; Abschluss nur einmal | ObjectiveProgressed, ObjectivesCompleted. |
| Run Power-ups | bestehender RunPowerUpState; aktive Effects und Choice-IDs |
Choice/Drop nur einmal; Maximum Stacks; Ausschlüsse; Apply, Tick, Remove |
Nur PowerUpApplied/Expired, falls Adapter sie wirklich benötigen. |
| Loadout | PlayerLoadout; zwei Slot Entries und Policy Snapshot |
gültige/unterschiedliche Slots, Freischaltung, Run-Policy | LoadoutSelected nur an Application-Grenze. |
| Progression Profile | späteres Root; Unlocks/Mastery | monotone Fortschritte; bekannte IDs; versionierte Migration | WeaponUnlocked, MasteryAdvanced. |
| Run Definition | unveränderliches Artifact aus Generator Factory/Service | Hash bindet Seed, Regeln, Layout und Inhalte | Kein Domain Event nötig. |
| Replay | unveränderliches ReplayPayload/Envelope; Events, Checkpoints |
monotone Sequenzen/Ticks, genau ein Start/Ende, Version/Hash | Kein Event pro Replay-Eintrag; Recorder nimmt Application Events auf. |
Repositories werden nur für Aggregate mit echter Lebensdauer benötigt, etwa Progression oder Upload-Session. Kataloge bleiben Read-only-Ports. Specifications sind nur für wiederverwendbare, kombinierbare Auswahlregeln sinnvoll; sonst genügen benannte Policies. Es werden keine EntityBase-/AggregateRootBase-Hierarchien eingeführt.
6. Zielarchitektur
Die bestehenden Projekte werden zunächst weiterverwendet:
HolodeckArena.Shared
├── Dungeons/ # schrittweise ProceduralGeneration Domain
├── Gameplay/ # Combat, Stats, Effects
├── Loadouts/ # Loadout Domain
├── Progression/ # Progression Domain
├── Runs/ # Run, Scoring, Replay contracts/rules
└── Weapons/ # Weapon Domain
HolodeckArena.Game3D
├── Application/ # neue Use Cases/Ports bei Migration
│ ├── Runs/
│ ├── Replays/
│ └── Leaderboards/
├── Features/ # bestehende Godot Adapter; schrittweise ausdünnen
├── Core/ # Godot Bootstrap, Flow, Settings, Wiring
└── Integrations/Nakama/ # Infrastructure Adapter
HolodeckArena.Networking # transportbezogene Verträge
tests/HolodeckArena.Game3D.Tests
├── Characterization/
├── Domain/
├── Application/
├── Infrastructure/
├── Godot/
└── GoldenMasters/
Eine zusätzliche HolodeckArena.Application-Assembly wird erst eingeführt, wenn Use Cases tatsächlich zwischen Godot-Client und Server geteilt werden. Abhängigkeitsrichtung: Game3D/Infrastructure -> Application -> Shared Domain; Domain referenziert weder Godot noch Nakama, HTTP, Datenbank oder Dateisystem.
Godot Nodes lesen Input/Physics, senden Commands, projizieren Ergebnisse, instanziieren Scenes und starten audiovisuelle Effekte. Mehrgliedrige Spielregeln gehören in Shared Domain oder in eine pure Application Policy.
7. Ubiquitous Language
| Begriff | Bedeutung | Heutiger Code | Zielbegriff |
|---|---|---|---|
| Run | einzelne versionierte Dungeon-Partie | Run Session, Run State, Run Result | RunLifecycle, RunDefinition, RunResult getrennt verwenden. |
| Seed | Eingabe für reproduzierbare Inhalte | String-/Numeric Seed, SeedId, Daily/Manual | RunSeed (Wert), SeedId (Backend-Identität). |
| Authority | Instanz, die eine Entscheidung akzeptiert | IRunAuthority, Combat Sync, Nakama Validation |
RunCommandDispatcher, CombatAuthority, SubmissionValidator. |
| Health/Vitals | Lebens- und Schutzwerte eines Combatants | HealthState, CombatantVitalState, Armor Resolver |
CombatantVitals; Godot-Fassade vorübergehend HealthState. |
| Run Result | lokales oder autoritatives Endergebnis | RunResult, AuthoritativeRunResult |
RunCompletionResult und AuthoritativeRunResult. |
| Replay Validation | Prüfung eines Replay-Artefakts | Integrität plus regelbasierte Prüfung | IntegrityValidation, RuleValidation, später SimulationValidation. |
| Modifier | Änderung eines Stats/Waffenwerts | zwei ModifierOperation-Enums |
Kontextqualifiziert StatModifier bzw. WeaponStatModifier. |
| Enemy Definition | katalogisierte Art versus Run-Instanz | Resource, Snapshot, Objective Definition | EnemyArchetype, EnemySnapshot, EnemyInstanceId. |
| Submission | versionierte Einreichung eines Runs | Claim, Envelope, RPC Payload | RunSubmission mit Replay-/Result-Bindung. |
8. TDD Assessment und Testmatrix
| Cluster | heutige Testbarkeit | Testwert | Testart | Priorität |
|---|---|---|---|---|
| Stats/Damage/Vitals | hoch, pure Klassen vorhanden | sehr hoch | Characterization + Unit + Property | P0 |
| Weapons/Combat Authority | hoch im Shared-Kern | sehr hoch | Characterization + Domain + Determinism | P0 |
| Power-ups/Drops/Loadouts | hoch | sehr hoch | Characterization + Domain + Property | P0 |
| Objectives/Run Completion | mittel bis hoch; Completion hat Adapter | sehr hoch | Characterization + Application | P0 |
| Scoring/Medals | hoch | sehr hoch | Golden Master + Boundary | P0 |
| Seed/Dungeon Generation | hoch ohne Scene-Instanziierung | sehr hoch | Determinism + Golden Master + Property | P0 |
| Replay/Validation | hoch für Modelle, mittel für Pipeline | sehr hoch | Golden Master + Contract + Recovery | P0 |
| Leaderboard Submission | mittel | sehr hoch | Contract + Integration | P0/P1 |
| Enemy/Boss/Spawn | mittel; Decision-Code und Nodes gemischt | hoch | Characterization + Godot Integration | P1 |
| Online Session/Nakama | mittel mit Fakes, echte Umgebung fehlt | hoch | Contract + Container Integration | P1 |
| Progression | hoch im Shared-Kern | mittel/hoch | Domain + Migration | P1 |
| Settings | mittel | mittel | Unit + Persistence Integration | P2 |
| UI/HUD | mittel für Mapper, niedrig für Nodes | mittel | Presenter + Godot Smoke | P2 |
| Kamera/Input/Audio/VFX | niedrig ohne Engine | niedrig | wenige Godot Smoke Tests | P3 |
Tests sichern Risiken, nicht Getter. Der größte Anteil läuft als schnelle xUnit-Domain-Tests ohne Godot-Prozess. Godot-Integration prüft nur Scene-Instanziierung, Node-Wiring, Signals und Adapter. Nakama-, SQL-, Storage- und HTTP-Verträge werden separat getestet.
9. Characterization- und Golden-Master-Plan
Vor jeder Produktivmigration muss der betroffene Pfad grün und charakterisiert sein:
- Stats: Flat -> additive Prozent -> Multiplikator, mehrere Quellen, Entfernen, Null-/negative/extreme Werte und Eventanzahl.
- Damage/Vitals: Armorabsorption, Overkill, Zero/negative Damage, GodMode, PreventDeath, einmaliger Tod, Heal/Restore an Grenzen.
- Weapons/Combat: Fire-Timing, Ammo, doppelte Shot-ID, Sequenzen, Modifier-Reihenfolge, Crit/Weakspot, Penetration und Arc-Zielreihenfolge.
- Power-ups/Loadouts/Drops: Stacks, Ausschlüsse, abgelaufene Dauer, idempotente Choice/Collection, ungültige Slots und Unlocks.
- Objectives/Run: Summoned/Respawned-Regeln, doppelter Kill, einmaliger Abschluss, Abort/Complete-Idempotenz und Queue-Recovery.
- Scoring: exakte Breakdown-Werte für Happy Path, 0/Max/Over-Budget, Rundung, falsche Client-Claims und Score-Version.
- Seed/Generation: gleiche Eingabe liefert bytegleiches kanonisches Ergebnis; verschiedene Seeds erzeugen erwartete Vielfalt; ungültige Kataloge scheitern definiert.
- Replay: Reihenfolge, Zeitgrenzen, Hash, Serialisierung/Deserialisierung, Chunk-Grenzen, Recovery und Validation Codes.
Golden Masters werden als kleine, reviewbare JSON-Dateien unter tests/HolodeckArena.Game3D.Tests/GoldenMasters abgelegt. Kandidaten: kanonische RunDefinition für Seeds 1001, 1002, 1003; Score-Breakdowns; Replay-Envelope/Chunks; vollständiges Run Result. Snapshots enthalten Schema-/Algorithmusversionen und keine flüchtigen Zeitstempel oder GUIDs. Änderungen erfordern eine bewusste Review und gegebenenfalls Versionsanhebung.
Property-/Determinism-Tests ergänzen Golden Masters: Health/Armor bleiben im gültigen Bereich, Scores sind innerhalb der definierten Grenzen, identische Seed-/Config-Eingaben sind identisch, Replay-Sequenzen bleiben monoton, Serialize/Deserialize ist semantisch verlustfrei.
10. Migrationsroadmap und Arbeitspakete
Phase 0 – Baseline und Test-Harness
Ziel: Reproduzierbarer grüner Ausgangsstand. Betroffen: Solution-Tests, Nakama-Modultests, Testordner. Neu: Characterization, Domain, GoldenMasters-Struktur und Test-Helper nach Bedarf. Risiken: Veraltete Erwartungen werden mit Bugs verwechselt. Abhängigkeiten: keine Produktivänderung. Tests: komplette xUnit- und Node-Suite. DoD: Abweichungen erklärt, Testgrenzen entsprechen versioniertem Codevertrag, Baseline grün.
Phase 1 – Stats und Vitals charakterisieren
Ziel: Modifier-, Health- und Armor-Verhalten einfrieren. Betroffen: Shared/Gameplay/Stats, Shared/Gameplay/Combat, Game3D/Features/Combat/HealthState.cs. Neu: Characterization-Tests. Risiken: unterschiedliche Death-/PreventDeath-Semantik. Abhängigkeiten: Phase 0. Tests: Tabellen-/Grenzwerttests und Eventreihenfolge. DoD: aktuelles Verhalten vollständig sichtbar, keine Produktivänderung.
Phase 2 – Stats/Vitals Domain konsolidieren
Ziel: eine Godot-freie Regelquelle; vorhandene HealthState-API als Adapter erhalten. Betroffen: dieselben Dateien und ihre Consumer. Neu: nur falls bestehender CombatantVitalState die Semantik nicht ausdrücken kann, gezielte Domain-Typen. Risiken: Eventreihenfolge und Sandbox-PreventDeath. Abhängigkeiten: Phase 1. Tests: Characterization plus Domain Tests. DoD: Godot-Fassade delegiert, keine doppelte Damage-Regel, Tests grün.
Phase 3 – Scoring und Run Completion
Ziel: Score-Versionen als Golden Masters sichern; Clock/Persistenz aus Resultatbildung entfernen. Betroffen: Shared/Runs, Features/Dungeons/Run/Completion. Neu: pure Result Factory, IGameClock nur an der Use-Case-Grenze, Application Tests. Risiken: Leaderboard- und Serialisierungskompatibilität. Abhängigkeiten: Phase 0. Tests: Golden Masters, Idempotenz, Queue-Recovery, Contract-Tests. DoD: identische Resultate/Breakdowns; Service orchestriert nur noch.
Phase 4 – Seed und Procedural Generation
Ziel: reproduzierbaren Generatorvertrag festschreiben. Betroffen: Shared/Dungeons, Room-/Boss-Auswahl und Run Controller Adapter. Neu: kanonischer Snapshot-Serializer und Golden Masters. Risiken: HashCode.Combine, System.Random, Inhaltskatalogänderungen. Abhängigkeiten: stabile Testfixtures. Tests: Multi-Seed-Golden-Masters, Wiederholung in separaten Prozessen. DoD: alle fachlichen Zufallsentscheidungen beziehen RNG explizit; visuelle Zufälligkeit bleibt getrennt.
Phase 5 – Combat und Weapons
Ziel: autoritative Session als klare Konsistenzgrenze und kleinere Policies. Betroffen: Shared/Weapons, Features/Weapons, DungeonCombatNetworkSync, Player/Enemy Adapter. Neu: fokussierte Resolver/Policies nur bei echter Verantwortungsgrenze. Risiken: Trefferreihenfolge, Fire-Timing, Protokoll- und Replayänderungen. Abhängigkeiten: Phase 1/2 und Seed-Vertrag. Tests: Characterization, Determinism, C#/Nakama-Contract. DoD: Nodes senden Absicht statt Schaden; Domain bleibt frameworkfrei; Replay bleibt kompatibel.
Phase 6 – Power-ups, Drops und Loadouts
Ziel: Run-Effekte und Auswahlregeln als getrennte Aggregate/Policies. Betroffen: Shared-Module und Godot-Bridges. Neu: Adapter für Stat-Anwendung/Präsentation. Risiken: Modifier-Reihenfolge, Stack-Hash, Unlock- und Replay-Bindung. Abhängigkeiten: Stats/Combat. Tests: Matrix für Stacks, Ausschlüsse, Dauer, Drops, Slots. DoD: einzige Regelquelle im Domain Core; Godot projiziert Effekte.
Phase 7 – Objectives und Run Lifecycle
Ziel: Start/Complete/Abort und Objective-Abschluss explizit orchestrieren. Betroffen: DungeonObjectiveTracker, DungeonRun3DController, Authority Commands, Completion. Neu: kleines Lifecycle-Modell und Use Cases. Risiken: Signalreihenfolge, doppelte Abschlüsse, Sessionabbruch. Abhängigkeiten: Completion/Combat. Tests: Zustandsübergänge, idempotente Commands, Godot-Adapter-Smoke. DoD: Controller delegiert; Terminalzustand ist eindeutig.
Phase 8 – Replay und Validation
Ziel: Recorder, Artifact, Validierungsstufen und Upload-Workflow trennen. Betroffen: Shared Runs/Replay, Game3D Replay/Completion, Nakama RPCs. Neu: Application Ports/State Machine und Contract Fixtures. Risiken: Format-, Chunk-, Speicher- und Abwärtskompatibilität. Abhängigkeiten: stabile Run-/Combat-Events. Tests: Golden Masters, C#/TS-Contract, Fehler-/Recovery-Pfade. DoD: Versionen explizit, lokale und serverseitige Prüfung konsistent.
Phase 9 – Progression, Leaderboard und Online
Ziel: Profile/Unlocks fachlich kapseln und externe Workflows als Adapter halten. Betroffen: Progression, Leaderboards, Nakama, Session Services. Neu: Use-Case-spezifische Ports; echte Integrationssuite optional per Container. Risiken: SQL-Projektion, Retry/Idempotenz, Protokollversion. Abhängigkeiten: Run Result/Submission stabil. Tests: Domain-, Contract- und Integrationstests. DoD: keine Nakama-Typen im Domain Core; Submission bleibt idempotent.
Phase 10 – Godot-Adapter ausdünnen
Ziel: große Controller auf Lifecycle, Input, Physics und Darstellung reduzieren. Betroffen: nur bereits abgesicherte Pfade in Run/Player/Enemy/Replay Nodes. Neu: wenige Composition-/Adapterklassen. Risiken: Scene-Wiring und Signals. Abhängigkeiten: alle jeweiligen Domain-Migrationen. Tests: Scene-Instanziierung, Node-Verträge, gezielte E2E-Smokes. DoD: keine duplizierten Spielregeln; Nodes bleiben nachvollziehbar und Godot-nah.
11. Standardablauf je Cluster
- Heutiges Verhalten und Consumer inventarisieren.
- Characterization Tests einschließlich Fehler- und Grenzpfaden ergänzen.
- Relevante Tests grün herstellen; bekannte Bugs separat erfassen.
- Minimales Domain-Modell neben die alte Implementierung stellen.
- Alten Einstiegspunkt über Adapter/Application Layer delegieren lassen.
- Gesamte relevante Suite ausführen.
- Erst danach doppelte alte Regel entfernen.
- Suite erneut ausführen und Replay-/Seed-/Contract-Artefakte vergleichen.
- Temporäre Characterization Tests bewerten: behalten, in Domain Tests überführen oder mit Begründung entfernen.
- Dieses Dokument und die Systemdokumentation aktualisieren.
12. Definition of Done und Risiken
Ein Cluster ist migriert, wenn der Domain-Kern keine Godot-, Nakama-, Datei-, HTTP- oder Datenbankabhängigkeit besitzt; Invarianten dort liegen; Nodes/Services delegieren; Characterization-, Domain- und nötige Integrations-/Adaptertests grün sind; keine doppelte Regelimplementierung bleibt; Verträge/Versionen kompatibel oder bewusst migriert sind; und die Dokumentation den Code beschreibt.
Bei jeder Änderung sind insbesondere zu prüfen: Gameplay-Drift, Replay- und Seed-Kompatibilität, Score-/Leaderboard-Verschiebungen, Serialisierungs- und Savegame-Schemas, C#/TypeScript-/SQL-Verträge, Netzwerkreihenfolge, Godot-Signalreihenfolge und Performance. Offensichtliche Bugs werden als eigener Fix mit eigenem Test behandelt, nicht im Architektur-Refactoring versteckt.
13. Umsetzungsstand
- Phase 0: Die zuvor roten Erwartungen für Prozentdarstellung und Replay-Chunk-Grenze wurden an den aktuellen, versionierten Codevertrag angepasst. xUnit- und Nakama-Suiten sind grün.
- Phase 1: Characterization Tests sichern Modifier-Reihenfolge, Change Events, Armor-Overflow, Death Events, GodMode und die Sandbox-Policy
PreventDeath. - Phase 2, erster Strangler-Schritt:
Game3D/Features/Combat/HealthStatebehält seine bestehende Event-Fassade, delegiert Health-/Armor-Zustand aber anShared/Gameplay/Combat/CombatantVitalState. Domain Tests sichern Maximum-Health-, Reset- und Revive-Invarianten.Resetaktualisiert nun konsistent auchMaximumHealth; vorherige direkte Produktiv-Consumer des Shared-Typs existierten nicht. - Phase 3 abgeschlossen:
RunResultFactoryerzeugt Resultat, Score, Award und Loadout-Snapshot ohne Clock-, EventBus-, Queue- oder Persistenzzugriff.RunCompletionServiceorchestriert Capture, Factory, Events und Outbox.IGameClockkontrolliert Abschlusszeit und Fallback-Dauer. Application Tests, Completion-Characterization undperformance-score-v2-Golden-Master sind grün. - Phase 4 abgeschlossen:
DeterministicRandom(fnv1a32-xorshift32-v1) undStableSeedDerivation(fnv1a64-v1) sind die expliziten Quellen für Dungeon-, Boss- und Raumtemplate-Entscheidungen.SeededRandomdelegiert ohne Generator-Drift; der Multi-Seed-Golden-Master für1001bis1003blieb unverändert. Exakte Baselines schützen RNG-, Bossangriffs-, Template-, Rotations- und Boss-Seed-Sequenzen. Visuelle Zufälligkeit inFloatingDamageNumber3Dbleibt bewusst Godot-spezifisch. - Phase 5 abgeschlossen:
IDungeonCombatCommandPorttrenntAdvancedWeaponControllervom konkretenDungeonCombatNetworkSync. Godot sendet Fire-/Reload-/Switch-Absichten; die autoritativeShared/Weapons-Session bleibt die Regelquelle. Bestehende Combat-, Determinismus- und C#/Nakama-Vertragstests bleiben grün. - Phase 6 abgeschlossen:
PowerUpEffectProjectionerzeugt persistente Stat-/Weapon-Modifier und Trigger-Heilung deterministisch im Shared-Core. Der Godot-Controller projiziert diese Ergebnisse nur noch auf Runtime-Komponenten. Drop- und Loadout-Regeln waren bereits frameworkfrei und wurden bewusst nicht neu verpackt. - Phase 7 abgeschlossen:
RunLifecyclemodelliertRunning → Finalizing → Completed/Abortedund verhindert doppelte oder widersprüchliche Terminalübergänge.RunCompletionServicedelegiert daran; bestehende Objective-Tracker bleiben als bereits geeigneter Domain Core erhalten. - Phase 8 abgeschlossen:
ReplayIntegrityValidator,ReplayRuleValidatorundReplayArtifacttrennen Byte-/Hash-/Binding-Prüfung von Timeline- und Gameplay-Regeln.RunSubmissionValidatororchestriert beide Stufen.ReplayUploadStatusschützt den crash-resistenten lokalen Upload-Lifecycle; Chunk-, Recovery-, Golden-Master- und Nakama-Tests sind grün. - Phase 9 abgeschlossen:
PlayerProgressionProfilekapselt Snapshot-Invarianten, Unlocks, Challenges und Mastery-XP;PlayerProgressionComponentbleibt Godot-Adapter.LeaderboardQueryServiceist der Application Use Case vorILeaderboardClient; Nakama- und Submission-Ports bleiben Infrastrukturgrenzen. Das Runtime-Bundle wurde aus dem aktuellen TypeScript neu erzeugt und die Idempotenz-/Leaderboard-Contracts sind grün. - Phase 10 abgeschlossen:
DungeonWorldSceneAssemblervereinheitlicht Template-/Fallback-Welt, Collision, Türen, Room-Tracker sowie Spawn-/Exit-Platzierung für Live-Run und Replay. Player-Input, -Interaction und -Presentation, Enemy-Runtime/Motion/Attack-Presentation und Replay-Playback liegen in fokussierten internen Adaptern. Der Run-Controller delegiert Encounter-Cleanup/Ticks, Replay-Streaming/-Finalisierung und Completion/Abort an Koordinatoren. Öffentliche Scenes, Export-Properties, Events, Formate und Domain-Regeln bleiben unverändert; Contract-Tests undPhase10SceneSmokesichern die Godot-Grenze. - Separater Befund: Ein abgebrochener Run behält einen bereits im Metrics-Snapshot vorhandenen Score, obwohl sein Score-Breakdown neutral ist. Der normale Tracker liefert hier aktuell
0; eine fachliche Bereinigung wäre ein eigener Bugfix.