Files
MSCO-Dedicated-Server/README.md
T

351 lines
23 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
- Launcher für Spieler: [MSCO-Launcher](https://git.mbm.wtf/MrMaho/MSCO-Launcher) – https://msco.mbm.wtf/download
![Web-Panel: Übersicht mit Start/Stop, Spielern, Laufzeit, Welt, Backups und letzter Aktivität](docs/images/panel-dashboard.png)
## 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 in den ersten zwei Stellen der Version passen (z.B. Server 2.8 ↔ Mod 2.8.x), sonst bekommen
Spieler eine Warnung. Kleine Mod-Updates (dritte Stelle) brauchen kein Server-Update.
## 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) |
| `RemoteManagement` | `true` = der Besitzer kann den Server im MSCO Launcher verwalten (Befehle über den Keymaster) |
| `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 30; nur wenn sich etwas geändert hat; 0 = nur beim Beitritt). Speichern lässt das Spiel dieses Spielers einige Sekunden hängen – das Spiel wartet dafür einen ruhigen Moment ab (nicht in schneller Fahrt) |
| `JoinSaveMaxAgeMinutes` | beim Beitritt nur dann frisch speichern lassen, wenn der letzte Spielstand älter ist (Standard 15; 0 = bei jedem Beitritt). Sonst bekommt der Neue den gespeicherten Stand plus alle Änderungen seitdem |
| `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`.
## Web-Panel
Der Server bringt ein Web-Panel mit – **auf demselben Port wie das Spiel** (Standard `7777`). Einfach im Browser
`https://<server-ip>:7777/` öffnen; der Server erkennt selbst, ob ein Browser oder das Spiel verbindet. Es muss also
kein weiterer Port freigegeben werden.
**HTTPS:** Das Panel ist verschlüsselt erreichbar. Ohne eigenes Zertifikat erzeugt der Server einmal ein selbst
signiertes (`data/panel_cert.pfx`) – der Browser warnt beim ersten Besuch („nicht sicher“/„nicht vertrauenswürdig“),
dann *Erweitert → Weiter*. Den **Fingerabdruck** (SHA-256) zeigt das Server-Log beim Start; er muss mit dem im Browser
(Schloss-Symbol → Zertifikat) übereinstimmen. Wer von außen `http://` öffnet, wird auf `https://` umgeleitet, damit
Passwort und Sitzung nie unverschlüsselt übertragen werden (lokal und hinter einem Reverse-Proxy nicht). Eigenes
Zertifikat (PFX): `"PanelCertificatePath": "panel.pfx"` und `"PanelCertificatePassword"` in `server.json`;
abschalten: `"PanelHttps": false`.
| Spieler | Live-Konsole |
|---|---|
| ![Spielerliste mit Kick, Ban und Admin-Rechten](docs/images/panel-players.png) | ![Live-Konsole mit Chat, Beitritten und Befehlseingabe](docs/images/panel-console.png) |
| **Welt & Backups** | **Einstellungen** |
| ![Welt zurücksetzen, Backups, Reset-Punkt und Spielstand-Upload](docs/images/panel-world.png) | ![Einstellungen: Name, Spielerzahl, Sichtbarkeit, Speichern, Ports und Schlüssel](docs/images/panel-settings.png) |
**Erstes Anmelden:** Beim Start ohne Panel-Konto steht im Log ein Einrichtungs-Code:
```bash
docker logs msco-server | grep -A2 "WEB PANEL SETUP"
```
Mit diesem Code legst du im Browser das **Owner**-Konto an (erneut anzeigen: `msco panel`).
| Bereich | Was geht |
|---|---|
| Dashboard | Spieler, Laufzeit, Weltzustand, Backups – **Start / Stop / Restart** des Gameservers, Grund wenn er nicht läuft |
| Players | Liste mit ID, Name, SteamID, IP · Kick, Ban, Admin geben/nehmen · Nachricht an alle |
| Console | Live-Log (Chat, Beitritte, Admin-Aktionen) und Befehle eingeben (mit Verlauf ↑/↓) |
| Admins | Ingame-Admins per SteamID hinzufügen/entfernen (braucht einen [Steam Web API Key](https://steamcommunity.com/dev/apikey)) |
| Bans | Gebannte ansehen, entbannen, SteamID auch offline bannen |
| World & Backups | Welt zurücksetzen, Backup, Reset-Punkt, Backups wiederherstellen, **Spielstand als ZIP, RAR oder 7z hochladen**, als ZIP herunterladen, **neues Spiel starten** |
| Settings | `server.json` bearbeiten (Name, Beschreibung, **Tags**, Spielerzahl, Sichtbarkeit, Ports, Panel, Schlüssel …) |
| Update | neue Server-Versionen prüfen und mit Fortschrittsanzeige installieren (oranger Punkt in der Seitenleiste, wenn eine da ist) |
| Panel Users | weitere Benutzer anlegen: **Moderator** (Spieler/Chat), **Admin** (alles am Server), **Owner** (+ Benutzer) |
- **Das Panel ist unabhängig vom Gameserver:** Es läuft auch, wenn der Server gestoppt ist, abgestürzt ist oder gar
nicht starten kann (z.B. kein Lizenzschlüssel, kein Spielstand). Das Dashboard zeigt dann den Grund – Schlüssel
unter **Settings** eintragen bzw. Spielstand als ZIP unter **World & Backups** hochladen und **Start** drücken.
- **Stop** fährt den Gameserver herunter (Spieler bekommen den Grund, niemand kann beitreten), **Start** startet ihn
wieder, **Restart** lädt Einstellungen, Lizenz und Spielstand neu. Nach einem Absturz startet er automatisch neu.
- Erster Start ganz ohne Einrichtung: `docker compose up -d`, Panel öffnen, Einrichtungs-Code aus dem Log eingeben,
Lizenzschlüssel und Spielstand im Panel hinterlegen, Start.
- Oberfläche auf **Deutsch oder Englisch** (Umschalter unten in der Seitenleiste).
- **Port oder Panel-Einstellungen geändert?** In den Einstellungen unten **„Panel neu starten“** – übernimmt sie sofort,
man bleibt angemeldet und wird auf die neue Adresse weitergeleitet. Ist *Web-Panel aktiviert* abgehakt, wird das
Panel dabei wirklich ausgeschaltet – wieder an mit `panel on` in der Server-Konsole.
- **Tags**: eigene Tags für die Serverliste (z.B. `deutsch, roleplay`, max. 6). `official` und `featured` vergeben nur
die MSCO-Admins im Keymaster.
- **Anmeldungen überstehen Neustarts** (auch Updates): Sitzungen liegen gehasht in `data/panel_sessions.json`.
- **Keymaster nicht erreichbar oder lehnt den Schlüssel ab?** Ein laufender Server läuft bis zum nächsten Neustart weiter
und warnt im Log/Panel. Ein Neustart klappt noch bis 72 Stunden nach der letzten Bestätigung (gespeichert in
`data/license.json`); danach startet der Server von selbst, sobald der Master den Schlüssel wieder bestätigt.
- **Neues Spiel** (Welt & Backups → „Neues Spiel starten“, Konsole `new-game`): statt eines hochgeladenen Spielstands
legt der erste Spieler, der beitritt, eine frische Welt an; der Server übernimmt danach dessen Spielstand. Der
bisherige Spielstand landet in den Backups, „Welt zurücksetzen“ geht dann wieder auf ein neues Spiel zurück.
- **Updates im Panel** (Seite „Update“): Der Server prüft alle 6 Stunden, ob auf git.mbm.wtf eine neuere Version liegt
(Hinweis im Log und in der Seitenleiste). „Update installieren“ lädt den Quellcode, baut ihn mit dem .NET SDK und
startet neu – mit Fortschrittsanzeige (Download, Bauen, Installieren, Neustart), die auch den Neustart des Panels
übersteht; man bleibt angemeldet und Spieler verbinden sich automatisch neu. Das Update liegt in `data/app/current`
und wird beim Start statt der eingebauten Version geladen; startet es dreimal nicht, läuft wieder die eingebaute.
Ein neueres Docker-Image (`git pull && docker compose up -d --build`) ersetzt ein älteres Panel-Update automatisch.
Voraussetzung: .NET SDK (im Docker-Image ab 2.9 enthalten) und ein Dienst, der nach dem Beenden neu startet
(Docker `restart: unless-stopped`, systemd) – unter Windows startet sich der Server selbst neu.
- Passwörter werden nur als PBKDF2-Hash in `data/panel_users.json` gespeichert, Login mit Sperre nach
Fehlversuchen, Sitzungs-Cookie (HttpOnly, SameSite=Strict), Schutz gegen CSRF.
### Hinter einem Reverse-Proxy
Den Proxy einfach auf `http://<server>:7777` zeigen lassen und in `server.json` setzen:
```json
"PanelTrustProxy": true,
"PanelBasePath": ""
```
`PanelTrustProxy` übernimmt die echte Besucher-IP und HTTPS (`X-Forwarded-For` / `-Proto`), `PanelBasePath` (z.B.
`"/panel"`) bzw. `X-Forwarded-Prefix` für einen Unterpfad. Lieber einen eigenen Port? `"PanelPort": 40120` (und im
`docker-compose.yml` freigeben); mit `"PanelBindAddress": "127.0.0.1"` ist das Panel dann nur über den lokalen Proxy
erreichbar. Ganz aus: `"PanelEnabled": false`.
> **Eigener Panel-Port – nicht aussperren:** Der Port gilt erst nach einem Neustart des ganzen Programms
> (`docker compose restart`; der Neustart-Knopf im Panel startet nur den Gameserver neu). Danach ist das Panel **nur
> noch** unter dem neuen Port erreichbar, in Docker nur, wenn er in `docker-compose.yml` unter `ports` steht
> (`- "40120:40120/tcp"`). Schon ausgesperrt? `"PanelPort": 0` in `data/server.json` setzen und
> `docker compose restart` – dann ist das Panel wieder auf dem Spiel-Port.
## Verwalten aus dem MSCO Launcher
Im Launcher unter **Meine Server** verknüpft der Besitzer seinen Server einmal mit dem Lizenzschlüssel. Danach sieht
er dort Status und Spieler und kann Befehle schicken: `say`, `kick`, `ban`, `save`, `backup`, `restart`,
`mods reload`, `status`, `players`. Der Server holt sie alle 5 Sekunden beim Keymaster ab und führt nur Befehle aus
dieser Liste aus (im Log mit „Launcher (Konto)“). Abschalten: im Web-Panel unter *Einstellungen* „Verwalten aus dem
MSCO Launcher“ bzw. `"RemoteManagement": false` in `server.json`.
## Mods
MSCO-Mods (.dll, siehe [MODDING.md](https://git.mbm.wtf/MrMaho/MSCO/src/branch/main/MODDING.md)) in `data/mods` – oder
im Web-Panel unter **Mods** hochladen. Jeder Spieler bekommt beim Beitreten die Liste; fehlende Mods lädt sein Spiel
nach seiner Zustimmung direkt vom Server (SHA-256 geprüft, höchstens 30 Mods à 20 MB). In der Serverliste bekommt der
Server automatisch den Tag **MODDED** und zeigt seine Mods an. Nach Änderungen im Ordner: `mods reload` (Panel: automatisch).
Im Panel unter **Mods → MSCO-Modliste** lassen sich Mods aus der offiziellen Liste
([msco.mbm.wtf/mods](https://msco.mbm.wtf/mods), von den MSCO-Admins geprüft) durchsuchen und mit einem Klick zum Server
hinzufügen oder aktualisieren – der Server lädt sie nur vom offiziellen Keymaster und prüft die SHA-256.
> Mods laufen auf den PCs der Spieler – nur Mods anbieten, denen du vertraust.
## 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 |
| `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 |
| `backup` | aktuellen Spielstand jetzt sichern |
| `reset-world` | ganze Welt zurück auf den Reset-Punkt (den Spielstand, wie er dem Server gegeben wurde: Start, `--import-save`, `reload-save`) – alle verbinden neu |
| `set-reset-point` | aktuellen Spielstand als neuen Reset-Punkt nehmen |
| `stop` / `start` | Gameserver stoppen (das Web-Panel läuft weiter) / wieder starten |
| `restart` | Server neu starten (Einstellungen, Lizenz, Spielstand neu laden) |
| `exit` | ganzes Programm beenden (auch das Panel) – mit Docker startet es danach wieder, dauerhaft aus: `docker compose stop` |
| `new-game` | Spielstand sichern und ein frisches neues Spiel starten (der erste Spieler legt die Welt an) – alle verbinden neu |
| `panel [on\|off]` | Adresse des Web-Panels und ggf. den Einrichtungs-Code anzeigen / Panel an- oder ausschalten |
| `mods`, `mods reload` | Server-Mods anzeigen / `data/mods` neu einlesen |
Im Spiel öffnen Admins mit `/admin` (Chat, Taste T) oder `admin` (F7-Konsole) das Admin-Menü: Kick/Ban,
**Admin geben/nehmen**, GOTO/BRING (zu einem Spieler / Spieler zu sich teleportieren), Cheats (Geld, Bedürfnisse
auffüllen, Satsuma zu sich holen), Items spawnen und Welt/Backups.
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 (wenn der letzte Spielstand älter als `JoinSaveMaxAgeMinutes` ist) 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, Verschleiß, Teile, Lack …), Schalter (Licht, Zündung, Motor …), Jobs und
Events, gekaufte/verbrauchte Items sowie die letzte Position und die Bedürfnisse (Hunger, Durst …) jedes Spielers.
- Den Spielstand holt sich der Server nur, wenn sich seitdem etwas geändert hat (Speichern lässt das Spiel kurz hängen).
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:** am einfachsten im Web-Panel unter **Update**. Server und Mod müssen in den ersten zwei Stellen der
Version passen; die Mod bei den Spielern aktualisiert der Launcher. Ohne Panel:
```bash
git pull
docker compose up -d --build
```
Spieler mit einer anderen Mod-Version bekommen beim Verbinden eine Warnung.
**Weltzustand zurücksetzen:** `msco reset-world` (oder RESET WORLD im Admin-Menü) setzt die ganze Welt auf den
Reset-Punkt zurück – den Spielstand, wie er dem Server gegeben wurde (liegt in `data/save_original/`). Einen **neuen**
Spielstand übernehmen: Dateien nach `data/save/` legen und `msco reload-save` ausführen – der wird dann auch der neue
Reset-Punkt.
## 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.
- Web-Panel: HTTPS (siehe oben), Passwörter als PBKDF2-Hash, Sitzungs-Cookie `HttpOnly` + `SameSite=Strict` (über
HTTPS `Secure`), Schutz gegen fremde Formulare (eigener Header), strenge Content-Security-Policy. Nach 8
Fehlversuchen pro IP bzw. 16 pro Benutzer ist der Login einige Minuten gesperrt. `panel_users.json`,
`panel_sessions.json`, `server.json` und das Zertifikat sind unter Linux nur für den Server-Benutzer lesbar.
- Spieler-Eingaben werden geprüft: Namen/Chat ohne Steuerzeichen (keine gefälschten Log-Zeilen), Chat im Stil von
Server-Meldungen (`* …`), Uhrzeit/Wetter (`msco.*`) und Admin-Einbau von Teilen nur von Admins, ungültige oder
absurde Geldänderungen werden verworfen.
- **Sicherheitsstufe:** Jede Server-Version hat eine Sicherheitsstufe (`GameServer.SecurityLevel`, steigt mit jedem
Sicherheitsupdate). Aktuelle MSCO-Mods treten Servern unter ihrem Minimum nicht bei, und die Serverliste zeigt sie
als **VERALTET**. Fehlt deinem Server ein Sicherheitsupdate, steht das im Log/Panel – dann über das Panel
(*Update*) oder `git pull` + Neubau aktualisieren. Das Minimum können MSCO-Admins im Keymaster anheben.
## Lizenz
GNU AGPL-3.0 – siehe [LICENSE](LICENSE).
Made by **MBM** – [mbm.wtf](https://mbm.wtf)