Wiki: alle Seiten

mregosar committed 2026-10-26 00:55:49 +01:00
1 parent 4991e3bdb2
commit 3b685aa0d6
10 files changed
+286 -2

No files matched your search

+23
@@ -0,0 +1,23 @@
# Ablauf eines Matches
1. **Match erstellen (`/neu`).** Teamnamen, Spielmodus (Wingman 2 gegen 2 oder Competitive 5 gegen 5), Serie (Best of 1, 3 oder 5) und wer das Veto beginnt (Münzwurf oder festes Team). Der Browser des Organisators erhält einen geheimen Organisator-Token.
2. **Server vorbereiten.** Beim Anlegen fordert das Backend im Hintergrund einen Server an. Er startet schon während Lobby und Veto. Der Status ist auf der Match-Seite sichtbar.
3. **Einladungen.** Drei Zugangscodes im Format `ABCD-EFGH`:
- Team A: `/join/<code>`
- Team B: `/join/<code>`
- Zuschauer: `/watch/<code>` für Stream und Kommentatoren
Ein Code gilt nur für die Webseite. Den CS2-Serverzugang bekommen Spieler getrennt. Codes lassen sich jederzeit neu erzeugen, der alte Link wird dann ungültig.
4. **Spieler treten bei.** Über den Teamlink gibt ein Spieler seinen Namen ein (optional die SteamID64). Der erste Spieler eines Teams wird Captain. Jeder Spieler setzt sich auf „bereit“. Ein Team ist bereit, wenn mindestens ein Spieler dabei ist, ein Captain existiert und alle beigetretenen Spieler bereit sind. Mit `REQUIRE_FULL_TEAMS=true` muss das Team vollständig sein.
5. **Map-Veto.** Sind beide Teams bereit, startet der Organisator das Veto. Die Captains bannen und wählen abwechselnd nach dem festen Ablauf (siehe [Map-Pools und Veto](Map-Pools-und-Veto)). Die letzte verbleibende Map wird automatisch Entscheidungsmap.
6. **Server konfigurieren.** Nach dem Veto richtet das Backend den laufenden Server ein: Spielmodus, erste Map, Teamnamen, Startseiten, Match-Einstellungen, Passwörter und die [Turnierregeln](Turnierregeln).
7. **Während der Serie.** Der Organisator beendet die Aufwärmphase (`mp_warmup_end`), pausiert und setzt fort (`mp_pause_match`, `mp_unpause_match`), lädt die nächste Map, stoppt den Server oder beendet das Match.
8. **Fehlerfälle.** Startet der Server nicht oder schlägt die Konfiguration fehl, zeigt die Seite den Grund. Der Organisator kann den Vorgang über „Server neu starten“ bzw. „Konfiguration wiederholen“ erneut anstoßen.
## Automatisches Herunterfahren
Das Backend prüft regelmäßig alle Server:
- Match abgeschlossen oder abgebrochen: Server wird gestoppt.
- Lobby, Veto oder Server ohne Spieler: Nach `SERVER_IDLE_TIMEOUT_MINUTES` ohne Aktivität wird der Server gestoppt.
- Nach `SERVER_MAX_LIFETIME_HOURS` wird jeder Server gestoppt, unabhängig von der Aktivität.
+26
@@ -0,0 +1,26 @@
# Admin-Bereich und Rollback
## Admin-Bereich
Unter `/admin` verwaltet der Admin alle Matches. Die Anmeldung läuft über `ADMIN_PASSWORD`. Ohne dieses Passwort gibt es den Bereich nicht. Die Anmeldung ist auf 5 Versuche pro Minute begrenzt.
Der Admin kann:
- Veto starten und Veto-Schritte auch für ein Team ausführen
- Server neu starten, stoppen und konfigurieren
- Aufwärmphase beenden, pausieren und fortsetzen
- nächste Map laden, Match abschließen oder abbrechen
- Codes erneuern und Spieler entfernen
- Matches löschen
## Rollback
Ein Rollback spielt eine gespeicherte Runde zurück. Die Funktion ist nur für Admins verfügbar.
**Voraussetzungen:**
- Das Match ist live und der Server konfiguriert.
- Der Server startet mit dem Parameter `-allow_round_backup_files`. Die Anwendung setzt ihn über `CS2_ADDITIONAL_ARGS`.
- CS2 speichert nach jeder Runde eine Sicherung (`mp_backup_round_auto 1`). Die Dateien sind pro Match über ein Präfix eindeutig zugeordnet.
**Ablauf:** Der Admin wählt im Rollback-Bereich die gespeicherte Runde. Die Anwendung lädt die Sicherung, pausiert das Match (`mp_pause_match`) und berechnet den Live-Stand neu.
Die Funktion ist gegen einen echten CS2-Server geprüft.
+33
@@ -0,0 +1,33 @@
# Docker-Betrieb
Mit `SERVER_ADAPTER=docker` startet die Anwendung pro Match einen Container mit dem Image [joedwards32/cs2](https://github.com/joedwards32/CS2). Das Image lädt CS2 über SteamCMD. Alle Container teilen sich ein Volume.
## Grundlagen
- **Container:** Namen `cs2mv-<matchId>`, Label `cs2-mapveto=1`.
- **Ports:** Pro Match zwei Ports aus `CS2_PORT_RANGE_START` bis `CS2_PORT_RANGE_END` (Spiel TCP und UDP, CSTV UDP).
- **Spieleranzahl:** `CS2_MAXPLAYERS` ist 6 bei Wingman und 12 bei Competitive. CSTV belegt einen Slot.
- **Volume:** `CS2_DOCKER_VOLUME` (Standard `cs2-mapveto-gamefiles`), rund 60 bis 73 GB. So lädt nicht jeder Container neu.
- **Start-Warteschlange:** Die Container starten nacheinander, damit SteamCMD nicht parallel auf das Volume schreibt. Ein Container gilt als bereit, sobald der Update-Check beendet ist oder RCON antwortet.
- **Startzeit:** `CS2_START_TIMEOUT_MINUTES` (Standard 20).
## LAN oder Internet
- Ohne `CS2_GSLT` läuft der Server im LAN-Modus (`sv_lan 1`). Spieler im selben Netz verbinden sich direkt.
- Mit `CS2_GSLT` (Game Server Login Token für App 730) ist der Server öffentlich erreichbar.
## Voraussetzungen auf dem Docker-Host
- Docker erreichbar über `DOCKER_HOST`, bei SSH etwa `ssh://USER@HOST`.
- `CS2_PUBLIC_HOST` ist die Adresse, unter der Spieler den Host erreichen.
- `CS2_RCON_HOST` ist die Adresse, unter der das Backend die RCON-Ports erreicht.
- Passwörter bestehen nur aus Buchstaben und Ziffern. Die Anwendung erzeugt sie selbst.
## Betrieb als Container
Ein Container mit Webseite, Backend und Datenbank startet die CS2-Container auf demselben Host. Dafür gibt es `deploy/compose.yml` mit `deploy/.env`. Details im Repository unter `docs/container.md`.
## Bekannte Grenzen
- Der Docker- und der Static-Adapter sind bislang nicht gegen einen echten Server im Dauerbetrieb geprüft.
- Die Auswertung der `status`-Ausgabe (Map-Name, Spielerzahl) ist noch nicht gegen die echte Ausgabe getestet.
+18 -2
@@ -1,3 +1,19 @@
# Wiki
# CS2 Mapveto – Wiki
Erste Seite, Inhalt folgt.
Diese Seiten erklären den Betrieb und die Bedienung der Match-Verwaltung für Counter-Strike 2.
## Inhalt
- [Schnellstart](Schnellstart) – Installation und Start
- [Ablauf eines Matches](Ablauf-eines-Matches) – von der Erstellung bis zum Serverbeitritt
- [Rollen und Rechte](Rollen-und-Rechte) – wer darf was
- [Konfiguration](Konfiguration) – wichtigste Umgebungsvariablen
- [Map-Pools und Veto](Map-Pools-und-Veto) – Abläufe für Wingman und Competitive
- [Live-Ergebnisse und Stream](Live-Ergebnisse-und-Stream) – Auswertung der CS2-Logs und Stream-Ansichten
- [Turnierregeln](Turnierregeln) – Serverwerte nach FACEIT- und ESL-Richtwerten
- [Admin-Bereich und Rollback](Admin-Bereich-und-Rollback) – Verwaltung aller Matches, Rundenrücksprung
- [Docker-Betrieb](Docker-Betrieb) – CS2-Server als Container auf einem Docker-Host
## Stand
Die Dokumentation folgt der README im Repository. Nicht gegen einen echten CS2-Server getestet sind bislang die Docker- und Static-Adapter sowie die Auswertung der `status`-Ausgabe.
+26
@@ -0,0 +1,26 @@
# Konfiguration
Alle Variablen mit Standardwerten stehen in `.env.example` im Repository. Hier die wichtigsten.
| Variable | Standard | Zweck |
|---|---|---|
| `PORT` | `3000` | Port des Backends |
| `PUBLIC_URL` | `http://localhost:5173` | Basis für Einladungslinks |
| `DATABASE_FILE` | `data/cs2-mapveto.db` | SQLite-Datei |
| `CREATE_MATCH_PASSWORD` | leer | Passwort zum Erstellen von Matches |
| `REQUIRE_FULL_TEAMS` | `false` | `true`: Veto nur mit vollständigen Teams |
| `SERVER_ADAPTER` | `demo` | `demo`, `docker` oder `static` |
| `SERVER_IDLE_TIMEOUT_MINUTES` | `30` | Frist bis zum automatischen Herunterfahren |
| `SERVER_MAX_LIFETIME_HOURS` | `8` | harte Obergrenze pro Server |
| `CS2_TV_DELAY` | `90` | CSTV-Verzögerung in Sekunden |
| `CS2_GSLT` | leer | Docker: Game Server Login Token. Leer = LAN-Modus (`sv_lan 1`) |
| `CS2_PUBLIC_HOST` | – | **Pflicht bei Docker:** öffentliche Adresse des Docker-Hosts |
| `LOG_RECEIVER_URL` | `PUBLIC_URL` | Adresse, unter der der CS2-Server das Backend erreicht |
| `SERIES_AUTO_ADVANCE_SECONDS` | `30` | Wartezeit nach einem Map-Ende; `-1` = nur manuell |
| `STREAM_KEY` | leer | Schlüssel für die Stream-Übersicht aller Matches |
| `ADMIN_PASSWORD` | leer | Aktiviert den Admin-Bereich unter `/admin` |
| `LOG_DEBUG` | `false` | empfangene Logzeilen im Terminal ausgeben |
Ohne `ADMIN_PASSWORD` antwortet `/admin` mit 404.
Passwörter für Server und CSTV erzeugt das Backend selbst. Sie bestehen nur aus Buchstaben und Ziffern, weil das Container-Image Umgebungswerte auswertet.
+38
@@ -0,0 +1,38 @@
# Live-Ergebnisse und Stream
## Live-Ergebnisse
Beim Konfigurieren setzt die Anwendung auf dem Server `log on` und `logaddress_add_http "<LOG_RECEIVER_URL>/api/logs/<match>/<schlüssel>"`. Der Server schickt seine Logzeilen per HTTP ans Backend. Der Schlüssel ist pro Match und Serverstart zufällig. Zeilen mit falschem Schlüssel werden abgelehnt.
**Ausgewertet werden:** Matchstart nach der Aufwärmphase, jedes Rundenende mit Sieger und Grund, die Seitenzuordnung und das Spielende.
**Angezeigt werden:** Live-Stand und Rundenverlauf pro Map, Serienstand, Ergebnisse in der Übersicht.
**Nach dem Spielende:** Ist die Serie offen, lädt die Anwendung nach `SERIES_AUTO_ADVANCE_SECONDS` die nächste Map. Ist sie entschieden, etwa 2:0 in Best of 3, schließt sie das Match ab und gibt den Server frei.
**Voraussetzung:** Der Server muss `LOG_RECEIVER_URL` erreichen. Ob Daten ankommen, zeigt das Serverpanel des Organisators. Mit `LOG_DEBUG=true` gibt das Backend alle empfangenen Zeilen aus.
**Geprüft** mit echten Logzeilen eines CS2-Servers (Wingman). Die Beispieldatei liegt unter `server/test/fixtures/echte-logs-wingman.log`.
Zwei Eigenheiten von CS2 berücksichtigt der Parser:
- CS2 sendet `Match_Start` schon beim Laden der Map. Gezählt wird erst, wenn der Organisator die Aufwärmphase beendet.
- Direkt nach der Halbzeit nennt CS2 zu Rundenbeginn noch die alte Seitenzuordnung. Ausgewertet werden deshalb nur die Zeilen direkt nach einem Rundenende.
## Stream-Übersicht aller Matches
Unter `/stream` zeigt eine 1920×1080-Seite alle laufenden Vetos und Matches, live aktualisiert.
- **Karten:** eine pro Match. Im Veto zeigt die Karte den Zug und das Map-Board, im Match den Live-Stand und die Seiten.
- **Raster:** passt sich der Anzahl an (1, 2, 4 oder 6). Bei mehr als 6 Matches blättert die Seite alle 12 Sekunden weiter.
- **Unten:** offene Lobbys und die Ergebnisse der letzten drei Stunden.
- **Einzelnes Match:** Ein Klick auf eine Karte öffnet `/stream/match/<matchId>`, die Übersicht nur dieses Matches. Der Link enthält keinen Zuschauercode.
- **Schlüssel:** Mit `STREAM_KEY` nur über `/stream?key=<schlüssel>`, sonst offen. `?bg=transparent` macht den Hintergrund durchsichtig.
- **Datenschutz:** Codes, Verbindungsdaten und Passwörter erscheinen nie.
## Stream-Übersicht eines Matches
Unter `/stream/<Zuschauercode>` gibt es eine Vollbild-Übersicht für den Stream. Den Link findet der Organisator bei den Einladungen.
- **Format:** 1920×1080, skaliert auf jede Fenstergröße. In OBS als Browserquelle mit 1920×1080 einbinden.
- **Ablauf:** wechselt zwischen Lobby, Veto und Match (Spielstand, Rundenverlauf, Map-Leiste).
- **Laufband:** zeigt nur Ereignisse, die für Zuschauer relevant sind.
+44
@@ -0,0 +1,44 @@
# Map-Pools und Veto
Die Pools liegen in `server/config/map-pools.json` (Pfad über `MAP_POOL_FILE` änderbar). Jeder Pool enthält eine Map-Liste mit ID, Name und Farbe, die Teamgröße, `game_type`/`game_mode` und je Format einen Ablauf.
## Schritte
| Schritt | Bedeutung |
|---|---|
| `ban:X` / `ban:Y` | Team X bzw. Y bannt eine Map |
| `pick:X` / `pick:Y` | Team X bzw. Y wählt eine Map für die Serie |
| `side:X` / `side:Y` | Team wählt die Startseite (CT/T) |
| `decider` | die letzte verbleibende Map wird automatisch übernommen |
X ist das Team, das das Veto beginnt (Münzwurf oder vom Organisator festgelegt), Y das andere.
Beim Start prüft die Anwendung jeden Ablauf: Anzahl Picks = Maps der Serie − 1, Bans + Picks + 1 = Pool-Größe, genau eine Entscheidungsmap. Ungültige Abläufe machen nur dieses Format unauswählbar.
## Competitive (7 Maps)
Ancient, Anubis, Dust II, Inferno, Mirage, Nuke, Train
| Format | Ablauf |
|---|---|
| BO1 | X bannt, Y bannt, X bannt, Y bannt, X bannt, Y bannt → Entscheidungsmap, X wählt Seite |
| BO3 | X bannt, Y bannt, X pickt (Y wählt Seite), Y pickt (X wählt Seite), X bannt, Y bannt → Entscheidungsmap, X wählt Seite |
| BO5 | X bannt, Y bannt, X pickt (Y Seite), Y pickt (X Seite), X pickt (Y Seite), Y pickt (X Seite) → Entscheidungsmap, Y wählt Seite |
## Wingman (4 Maps)
Inferno, Nuke, Overpass, Vertigo
| Format | Ablauf |
|---|---|
| BO1 | X bannt, Y bannt, X bannt → Entscheidungsmap, Y wählt Seite |
| BO3 | X bannt, Y pickt (X Seite), X pickt (Y Seite) → Entscheidungsmap, X wählt Seite |
| BO5 | nicht unterstützt. Mit 4 Maps sind keine 5 Karten möglich. Ein Pool mit mindestens 5 Maps und einem `bo5`-Ablauf macht es auswählbar. |
## Regel für Startseiten
- Auf einer gewählten Map wählt das Gegnerteam des wählenden Teams die Startseite.
- Auf der Entscheidungsmap wählt das Team, das der Ablauf dafür vorsieht.
- Ohne `side`-Schritt werden die Seiten im Spiel festgelegt.
Die gewählte Startseite geht als `mp_teamname_1` (Team mit CT-Start) und `mp_teamname_2` (T-Start) an den Server.
+23
@@ -0,0 +1,23 @@
# Rollen und Rechte
| Rolle | Zugang über | Darf |
|---|---|---|
| Organisator | Token beim Erstellen | Veto starten, Spieler entfernen, Captain setzen, Codes erneuern, Server neu starten, stoppen und konfigurieren, pausieren und fortsetzen, nächste Map, Match beenden. Sieht Einladungen, Spieler- und CSTV-Verbindung sowie die Match-Übersicht |
| Captain | Teamcode (erster Spieler oder ernannt) | wie Spieler, dazu Veto-Aktionen des eigenen Teams und Captain-Übergabe |
| Spieler | Teamcode | bereit melden, Team verlassen. Sieht die Spieler-Verbindungsdaten nach dem Veto |
| Zuschauer | Zuschauercode | alles live verfolgen. Sieht nur den CSTV-Zugang, nicht das Spielerpasswort |
| Gast | ohne Code | nur Teamnamen und Status |
## Organisator spielt selbst mit
In der Lobby kann der Organisator unter „Selbst mitspielen?“ einem Team beitreten. Er bleibt Organisator und ist zusätzlich Spieler bzw. Captain. Ein zweiter Browser ist nicht nötig.
## Schutzmaßnahmen
- **Fremde Beitritte:** Jeder Code gehört zu genau einem Team. Zuschauercodes erlauben keinen Beitritt. Codebasierte Endpunkte sind pro IP begrenzt (20 Versuche pro Minute).
- **Doppelte Aktionen:** Jede Veto-Aktion trägt die Schrittnummer. Ein doppelter Klick liefert „Diese Aktion ist veraltet“.
- **Tokens:** Organisator- und Spieler-Tokens sind 256 Bit zufällig und werden nur als SHA-256-Hash gespeichert.
- **Server-Zugangsdaten** (RCON-Passwort, Container-Handle, GSLT) bleiben im Backend. Die Snapshots an Clients enthalten sie nie.
- **Befehls-Injection:** Teamnamen werden vor der Serverkonsole bereinigt. Passwörter sind rein alphanumerisch.
Alle Prüfungen laufen im Backend. Die Oberfläche blendet nur aus, was die Rolle nicht darf.
+37
@@ -0,0 +1,37 @@
# Schnellstart
## Als Container (empfohlen für den Betrieb)
Ein Container enthält Webseite, Backend und Datenbank. Er startet die CS2-Server-Container auf demselben Docker-Host. Details: [Docker-Betrieb](Docker-Betrieb).
```bash
docker -H ssh://USER@DOCKER-HOST-IP build -t cs2-mapveto:latest .
```
## Zum Entwickeln
```bash
npm install
cp .env.example .env # optional, Standardwerte funktionieren für die Demo
npm run dev # Backend auf :3000, Frontend auf :5173
```
Dann http://localhost:5173 öffnen.
## Produktion (ein Prozess)
Das Backend liefert das gebaute Frontend aus.
```bash
npm install
npm run build
PUBLIC_URL=https://veto.example.de npm start
```
Lauscht auf `PORT` (Standard 3000).
## Tests
```bash
npm test
```
+18
@@ -0,0 +1,18 @@
# Turnierregeln
Jeder konfigurierte Server setzt nach dem Mapwechsel diese Werte. Sie orientieren sich an FACEIT- und ESL-Richtwerten.
| Befehl | Wert | Zweck |
|---|---|---|
| `sv_pausable` | `1` | erlaubt Pausen (`mp_pause_match`) |
| `mp_halftime` | `1` | Seitenwechsel zur Halbzeit |
| `mp_freezetime` | `20` | Freezetime in Sekunden |
| `mp_buytime` | `20` | Kaufzeit in Sekunden |
| `mp_startmoney` | `800` | Startgeld |
| `mp_roundtime` | `1.92` | Rundenzeit in Minuten (1:55) |
Dazu kommen die Match-Einstellungen `mp_maxrounds` (24 bei Competitive, 16 bei Wingman), `mp_overtime_enable`, `mp_match_can_clinch 1` und `mp_autoteambalance 0`.
**Wichtig:** Die Werte stammen nicht aus dem Regelwerk eines konkreten Turniers. Vor einem echten Turnier mit dem Veranstalter abgleichen und in `server/src/servers/cs2Config.js` anpassen.
**Noch nicht geprüft:** ob `sv_pausable` und die Pause-Befehle am echten Server wirken.