Files
MSCO-Dedicated-Server/README.md
T

209 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MSCO Dedicated Server
Dedizierter Server für **MSCO – My Summer Car Online**. Er hält einen gemeinsamen Spielstand, speichert alles,
was die Spieler verändern, und gibt es an später Beitretende weiter. .NET 10, läuft unter Linux (Docker oder systemd)
und Windows.
- Mod: [MSCO](https://git.mbm.wtf/MrMaho/MSCO)
- Keymaster & Serverliste: [MSCO-Keymaster](https://git.mbm.wtf/MrMaho/MSCO-Keymaster) – https://msco.mbm.wtf
## Voraussetzungen
- Ein **Lizenzschlüssel** von https://msco.mbm.wtf/keys (Login mit Steam).
Der Server prüft ihn beim Start und meldet sich danach regelmäßig beim Master für die Serverliste.
- Ein My-Summer-Car-Spielstand als Startwelt.
- Port **7777/TCP** im Router/Firewall freigegeben (sonst wird der Server nicht gelistet).
- Server und Mod müssen dieselbe Version haben (sonst bekommen Spieler eine Warnung).
## Mit Docker (empfohlen)
```bash
git clone https://git.mbm.wtf/MrMaho/MSCO-Dedicated-Server.git
cd MSCO-Dedicated-Server
docker compose up -d --build # erster Start legt data/server.json an und beendet sich
```
1. In `data/server.json` mindestens `LicenseKey` eintragen.
2. Die Spielstand-Dateien nach `data/save/` kopieren (siehe unten).
3. `docker compose up -d`
| Aktion | Befehl |
|---|---|
| Konsole | `docker attach msco-server` – verlassen mit **Strg+P, dann Strg+Q** (Strg+C beendet den Server) |
| Einzelner Befehl | `docker exec msco-server msco <befehl>`, z.B. `msco players` |
| Logs | `docker logs -f msco-server` |
| Stoppen | `docker compose stop` – speichert vorher den Weltzustand und meldet den Server ab |
| Update | `git pull && docker compose up -d --build` |
Anderer Port: in `data/server.json` **und** in `docker-compose.yml` ändern.
### Linux: „Permission denied“ in `data/`
Der Container läuft als Benutzer-ID **1000** (der erste Linux-Benutzer), damit dir die Dateien in `data/` gehören.
Hat dein Benutzer eine andere ID (`id -u` / `id -g`), trag sie in eine `.env` neben der `docker-compose.yml` ein:
```bash
echo "MSCO_UID=$(id -u)" > .env
echo "MSCO_GID=$(id -g)" >> .env
```
Wurden Dateien schon von einer älteren Version als root angelegt (typisch: „Permission denied“ beim Hochladen
per SFTP oder bei `mkdir` in `data/`), einmal zurückholen:
```bash
docker compose down
sudo chown -R $(id -u):$(id -g) data
docker compose up -d --build
```
## Ohne Docker
**Linux (systemd):** .NET 10 Runtime installieren (`sudo apt install dotnet-runtime-10.0`), dann
`dotnet publish -c Release -o /opt/msco-server` und [`deploy/msco-server.service`](deploy/msco-server.service)
einrichten (Anleitung oben in der Datei). Daten liegen in `/var/lib/msco-server`.
Für eine Konsole den Server stattdessen in `screen`/`tmux` starten.
**Windows:** `dotnet publish -c Release -o publish`, dann `publish\MSCO.Server.exe` starten.
Startparameter:
- `--data <ordner>` – Datenordner (Standard: Programmordner; Docker: `/data`)
- `--import-save [pfad]` – Spielstand übernehmen (ohne Pfad: der eigene Spielstand dieses PCs, auch Proton)
- `--cmd <befehl>` – Befehl an einen laufenden Server im selben Datenordner schicken
## Spielstand
In `data/save/` gehören diese Dateien aus dem My-Summer-Car-Spielstand:
`defaultES2File.txt`, `items.txt`, `meshsave.txt`, `graveyard.txt` (und `notepad.txt`, falls vorhanden).
- Windows: `%USERPROFILE%\AppData\LocalLow\Amistech\My Summer Car`
- Linux (Proton): `~/.steam/steam/steamapps/compatdata/516750/pfx/drive_c/users/steamuser/AppData/LocalLow/Amistech/My Summer Car`
### Spielstand hochladen (SFTP, z.B. WinSCP / FileZilla)
Die Dateien einfach nach `data/save/` im Server-Ordner hochladen, z.B. `/home/<benutzer>/MSCO-Dedicated-Server/data/save/`.
Das geht auch, während der Server läuft. Kommt dabei **„Permission denied“**, gehört der Ordner noch root
(siehe Abschnitt „Linux: Permission denied“ oben) – einmal `sudo chown -R $(id -u):$(id -g) data` ausführen.
Meldet der **Server** nach dem Hochladen `Cannot read the save game … Permission denied`, gehören die neuen
Dateien einem anderen Benutzer (z.B. mit einem anderen SFTP-Konto oder als root hochgeladen) oder deine
Benutzer-ID ist nicht 1000. Der Server nennt im Log seine Benutzer-ID und den passenden `chown`-Befehl.
### Neuen Spielstand übernehmen
Nach dem Hochladen eines **anderen** Spielstands die alten Änderungen verwerfen und die Dateien neu einlesen –
sonst passt der gespeicherte Weltzustand nicht zum neuen Spielstand:
```bash
docker exec msco-server msco reset-world
docker exec msco-server msco reload-save
```
Ohne Docker: die beiden Befehle in der Server-Konsole eingeben, oder den Server stoppen, `data/world.json` löschen
und neu starten.
## Einstellungen (`data/server.json`)
| Einstellung | Bedeutung |
|---|---|
| `LicenseKey` | Schlüssel von der Keymaster-Seite (Pflicht) |
| `Name`, `Description` | Anzeige im Server-Browser |
| `MaxPlayers`, `Port` | Spieler-Limit (max. 3 sinnvoll), Port |
| `Public` | `false` = nicht in der Liste, nur Direct Connect |
| `RequireSteam` | `true` = nur Spieler mit Steam; `false` = Non-Steam-Server (Spieler werden über den Namen erkannt) |
| `PublicAddress` | öffentliche IP/Domain für die Liste (nur hinter NAT/Proxy nötig) |
| `AutosaveSeconds` | wie oft der Weltzustand gespeichert wird |
| `SaveSyncMinutes` | wie oft (Minuten) sich der Server von einem Spieler im Spiel den **aktuellen Spielstand** hochladen lässt (Standard 5, zusätzlich bei jedem Beitritt; 0 = nur beim Beitritt) |
| `SteamWebApiKey` | Steam-Anmeldetickets der Spieler bei Steam prüfen – **nötig für Admins** (kostenlos: https://steamcommunity.com/dev/apikey) |
| `BannedSteamIds` | gesperrte Spieler |
| `Admins` | SteamID64s, die im Spiel mit `/admin` kicken/bannen dürfen (nur mit `SteamWebApiKey`, siehe Sicherheit) |
Fehlende Einstellungen ergänzt der Server beim Start automatisch. Umgebungsvariablen (`MSCO_LICENSE_KEY`,
`MSCO_NAME`, `MSCO_PORT`, `MSCO_MAX_PLAYERS`, `MSCO_PUBLIC`, `MSCO_REQUIRE_STEAM`, `MSCO_PUBLIC_ADDRESS`,
`MSCO_STEAM_WEB_API_KEY`) überschreiben `server.json`.
## Konsolenbefehle
| Befehl | Beschreibung |
|---|---|
| `status`, `players` | Übersicht, Spielerliste mit IDs |
| `kick <id> [grund]`, `ban <id> [grund]` | Spieler entfernen / sperren |
| `bans`, `unban <SteamID64 oder name:spieler>` | Gesperrte anzeigen / Sperre aufheben |
| `say <text>` | Chatnachricht an alle |
| `admins`, `op <id oder SteamID64>`, `deop <...>` | Admins anzeigen / geben / nehmen |
| `save` | Weltzustand jetzt speichern |
| `reset-world` | alle Änderungen seit dem Spielstand verwerfen – verbundene Spieler bekommen eine Meldung und verbinden sich automatisch neu |
| `reload-save` | Spielstand-Dateien neu einlesen – verbundene Spieler verbinden sich automatisch neu |
| `backups`, `restore-save <nr>` | gesicherte Spielstände anzeigen / einen davon zurückholen (z.B. wenn der aktuelle kaputt ist) – alle verbinden sich neu |
| `stop` | speichern und beenden |
Im Spiel öffnen Admins mit `/admin` (Chat, Taste T) oder `admin` (F7-Konsole) das Admin-Menü: Kick/Ban,
GOTO/BRING (zu einem Spieler / Spieler zu sich teleportieren) und Cheats (Geld, Bedürfnisse auffüllen, Satsuma zu sich holen).
Cheats werden allen im Chat angezeigt, Teleports stehen im Server-Log.
Der Chat landet auch im Server-Log.
## Was der Server speichert
**Aktueller Spielstand statt Nachspielen:** Tritt jemand bei (und alle `SaveSyncMinutes`), bittet der Server einen
Spieler, der schon im Spiel ist, zu speichern und den Spielstand hochzuladen – genau wie das Spiel selbst speichert
(Schrauben, angebaute Teile, alles). Neue Spieler bekommen diesen Stand; alte Aktionen werden dann nicht mehr
nachgespielt. Der vorherige Spielstand liegt jeweils in `data/save_backups/` (die letzten 5).
- `save/` – der Ausgangs-Spielstand, den jeder neue Spieler bekommt.
- `world.json` – alles, was seitdem passiert ist: Positionen bewegter Objekte, Schraub-/Montage-Aktionen,
Geld, Türen/Tore, Fahrzeugzustand (Tank, Öl, Schrauben, Verschleiß …) und die letzte Position jedes Spielers.
Beim Beitreten: Spielstand laden → Objekte erfassen → Weltzustand anwenden → an der letzten eigenen Position weiterspielen.
## Betrieb in Produktion
**Checkliste**
- [ ] `LicenseKey` gesetzt, Server startet ohne Fehler (`docker logs msco-server`)
- [ ] Nur Port **7777/TCP** nach außen offen; der Server braucht sonst nur ausgehend HTTPS zu `msco.mbm.wtf`
- [ ] Log meldet keine Warnung „NOT reachable from the internet“ (sonst erscheint der Server nicht in der Liste)
- [ ] Steam-Server (`RequireSteam: true`): `SteamWebApiKey` eintragen, damit Anmeldetickets wirklich bei Steam geprüft werden
- [ ] Mindestens eine SteamID in `Admins`
- [ ] Backups von `data/` eingerichtet (siehe unten)
**Neustarts:** Docker startet den Server nach einem Absturz neu (`restart: on-failure`). Bei Konfigurationsfehlern
(kein/ungültiger Schlüssel, kein Spielstand) beendet er sich mit Code 1 und wird nach 3 Versuchen nicht mehr
gestartet – dann ins Log schauen. `docker compose stop` / `systemctl stop` speichern vorher den Weltzustand.
**Logs:** werden von Docker auf 3 × 10 MB begrenzt. Chat, Beitritte, Kicks/Bans und Admin-Aktionen stehen darin.
**Backups:** Alles Wichtige liegt in `data/` (`server.json`, `save/`, `world.json`). Den Server dafür nicht
anhalten – der Weltzustand wird atomar geschrieben. Beispiel (täglich per cron):
```bash
tar czf /backup/msco-$(date +%F).tar.gz -C /pfad/zu/MSCO-Dedicated-Server data
```
**Updates:** Server und Mod müssen dieselbe Version haben. Nach einem neuen Release:
```bash
git pull
docker compose up -d --build
```
Spieler mit einer anderen Mod-Version bekommen beim Verbinden eine Warnung.
**Weltzustand zurücksetzen:** Wird `world.json` mit der Zeit sehr groß oder macht Probleme beim Beitreten,
einen aktuellen Spielstand nach `data/save/` legen und `msco reset-world` ausführen.
## Sicherheit
- Die Adresse des Masters (`https://msco.mbm.wtf`) ist fest eingebaut, damit niemand die Schlüsselprüfung mit
einem eigenen Master umgehen kann. Sie lässt sich weder in `server.json` noch per Umgebungsvariable ändern.
- `data/` enthält Lizenzschlüssel und API-Keys – nicht veröffentlichen (steht in `.gitignore`).
- Der Container läuft nicht als root. Spielerdaten (Nachrichten, Objektzustände) werden in der Größe begrenzt,
unbekannte oder zu große Nachrichten verworfen.
- **Admins nur mit `SteamWebApiKey`:** Ohne Key prüft der Server die Steam-Tickets nicht – jeder könnte dann eine
fremde SteamID (z.B. die eines Admins) angeben. Deshalb gibt es ohne Key keine Admin-Rechte (das Log warnt beim
Start), und eine unbestätigte SteamID kann keinen verbundenen Spieler verdrängen.
- Gebannte Spieler werden über ihre (bei Steam geprüfte) SteamID erkannt. Auf Non-Steam-Servern gibt es keine
verlässliche Identität – dort sind Bans nur über den Namen möglich.
## Lizenz
GNU AGPL-3.0 – siehe [LICENSE](LICENSE).
Made by **MBM** – [mbm.wtf](https://mbm.wtf)