86 lines
3.6 KiB
Markdown
86 lines
3.6 KiB
Markdown
# Liar's Dice 3D
|
||
|
||
Würfel-Bluffspiel in Godot 4.7 mit echter 3D-Physik, Mehrspieler über Raum-Codes,
|
||
KI-Bots und einem Booster-System aus Buffs und Debuffs.
|
||
|
||
## Starten
|
||
|
||
godot --path . # oder das Projekt im Godot-Editor öffnen
|
||
|
||
Das Startmenü hat drei Punkte:
|
||
|
||
* **Einzelspieler** – nur die Bot-Anzahl (1–7) einstellen und starten. Es wird
|
||
kein Netzwerk geöffnet.
|
||
* **Mehrspieler** – nur den Namen eintragen, dann **Hosten** oder
|
||
**Beitreten**. Hosten führt direkt in die Lobby; dort steht der Code.
|
||
Beitreten fragt zuerst nach dem Code. Niemand braucht eine IP oder eine
|
||
Portfreigabe.
|
||
* **Lobby** – zeigt den Code, wer schon da ist und die Bot-Anzahl. Nur der
|
||
Host stellt die Bots ein und startet, sobald mindestens 2 Teilnehmer
|
||
zusammen sind (Menschen und Bots zusammengezählt, maximal 8).
|
||
* **Beenden** – schließt das Spiel.
|
||
|
||
## Mehrspieler: wie es zusammenhängt
|
||
|
||
Die Partie läuft nicht beim Host, sondern auf `pirate-dice.marha.de`:
|
||
|
||
Spieler ──wss://443──> ein Serverprozess ──> Raum MQG4 (SubViewport + World3D)
|
||
└──> Raum 4YPV (SubViewport + World3D)
|
||
|
||
* **Ein Prozess, ein Port.** Der Server trägt alle Räume gleichzeitig und
|
||
spricht WebSocket. Traefik reicht das auf 443 durch, es muss kein Port
|
||
freigegeben werden.
|
||
* **Ein Raum** ist ein Knoten unter `/root/Main/Raeume/<CODE>`. Darin ein
|
||
SubViewport mit `own_world_3d` – nur so hat jede Partie ihren eigenen
|
||
Physikraum, sonst lägen alle Würfel im selben.
|
||
* Die Knotennamen sind auf Server und Client gleich. Daran hängt das Ziel
|
||
jedes RPC, deshalb dürfen sie nicht auseinanderlaufen.
|
||
* Broadcasts (`rpc`) würden alle Räume treffen. Deshalb geht alles gezielt per
|
||
`rpc_id` an die Peers des eigenen Raums.
|
||
* Der Server sitzt nicht mit am Tisch: `local_seat` bleibt −1, kein HUD.
|
||
* Der **Host** ist der erste Spieler im Raum. Geht er, rückt der nächste nach.
|
||
Nur er stellt die Bots ein und startet.
|
||
* Der letzte macht das Licht aus: verlässt der letzte Spieler den Raum, wird er
|
||
samt Code sofort abgeräumt.
|
||
|
||
Gemessen mit sechs gleichzeitigen Partien zu acht Plätzen: **3,7 MB je Raum**,
|
||
im Leerlauf unter 1 % eines Kerns, kurze Spitzen beim Würfelwurf.
|
||
|
||
## Lokal entwickeln
|
||
|
||
make server # Spielserver auf :8000, trägt alle Räume
|
||
make dev # Spiel, zeigt auf den lokalen Server
|
||
|
||
Ohne `PIRATE_DICE_SERVER` zeigt das Spiel auf `wss://pirate-dice.marha.de`.
|
||
|
||
## Auf dem Server
|
||
|
||
git pull
|
||
make prod # baut und startet, holt Godot selbst
|
||
make logs
|
||
make down
|
||
|
||
Mehr ist nicht nötig. Der Docker-Build lädt Godot 4.7.2 herunter (Version steht
|
||
im `Dockerfile`), importiert das Projekt einmal vor und startet den Server.
|
||
`restart: unless-stopped` bringt ihn nach einem Neustart von selbst wieder hoch.
|
||
|
||
Es muss kein Port freigegeben werden: alles läuft als WebSocket über Traefik
|
||
auf 443.
|
||
|
||
## Aufbau
|
||
|
||
| Datei | Inhalt |
|
||
|---|---|
|
||
| `scripts/net.gd` | Autoload: WebSocket-Verbindung, Räume, Lobby, Spielstart |
|
||
| `scripts/boosters.gd` | Autoload: Booster-Katalog |
|
||
| `scripts/game.gd` | Spiellogik (host-autoritativ), RPCs, Zustandsabgleich |
|
||
| `scripts/table.gd` | Aufbau der 3D-Szene: Tisch, Würfelzonen, Becher, Kamera |
|
||
| `scripts/die.gd` | Physik-Würfel, Ablesen der Augenzahl aus der Ruhelage |
|
||
| `scripts/ai.gd` | Bot-Entscheidungen (Binomialabschätzung für Gebot/Anfechtung) |
|
||
| `scripts/hud.gd` | Spiel-UI |
|
||
| `scripts/menu.gd` | Startmenü und Lobby |
|
||
|
||
Die gesamte Spiellogik und die Würfelphysik laufen beim Host. Clients erhalten
|
||
nur ihre eigenen Würfel als Transform-Stream, gegnerische Werte erst beim
|
||
Aufdecken – Mitlesen fremder Würfel ist damit nicht möglich.
|