diff --git a/MSCO.csproj b/MSCO.csproj index 5ae1c37..eded03f 100644 --- a/MSCO.csproj +++ b/MSCO.csproj @@ -1,4 +1,4 @@ - + @@ -149,4 +149,8 @@ copy "$(TargetPath)" "C:\Users\nico\Documents\MySummerCar\Mods\Mods" /y ) + + + + \ No newline at end of file diff --git a/README.md b/README.md index 4b05574..3a48a77 100644 --- a/README.md +++ b/README.md @@ -1,127 +1,130 @@ -# MSCO – My Summer Car Online - -Multiplayer-Mod für **My Summer Car** (MSCLoader). Spiel mit bis zu 3 Spielern zusammen – per Steam-Einladung -(P2P) oder auf einem dedizierten Server aus dem Server-Browser. - -- Mod: dieses Repository -- Dedizierter Server: [MSCO-Dedicated-Server](https://git.mbm.wtf/MrMaho/MSCO-Dedicated-Server) -- Keymaster & Serverliste: [MSCO-Keymaster](https://git.mbm.wtf/MrMaho/MSCO-Keymaster) – live unter https://msco.mbm.wtf - -## Features - -**Verbinden** -- Launcher im Hauptmenü: P2P-Seite und Server-Browser -- **P2P über Steam:** HOST GAME, Freunde einladen, Beitritt über die Steam-Freundesliste (max. 3 Spieler) -- **Server-Browser:** Suche, Filter (Steam / Non-Steam / volle ausblenden), Ping, Server-Profil - (Besitzer, Version, Laufzeit, Spieler), lokale Server auf diesem PC werden automatisch gefunden -- **Direct Connect** per Adresse, JOIN-Links von der Website (`msco://`) starten das Spiel und verbinden direkt -- Server ohne Steam („Non-Steam“) werden unterstützt, andere Mod-Version = Warnung statt Sperre -- Der Host-Spielstand wird beim Start automatisch an alle übertragen; der eigene Spielstand wird vorher gesichert - und nach dem Spielen wiederhergestellt - -**Synchronisiert** -- Spieler als eigene Figur im MSC-Stil (Karohemd, Jeans, Schnurrbart, Kappe – je Spieler etwas anders) mit - Blickrichtung, Laufen, Ducken/Lehnen, Sitzen, gehaltenem Item und Namensschild -- Items, lose Teile, Schrauben und Fahrzeuge (auch mit G geschoben) mit Besitzer-System – inkl. was jemand in der Hand hält -- Fahrzeuge: Position, Lichter, Motorgeräusch; als **Beifahrer** mitfahren (Taste P) -- **Fahrzeugzustand:** Tank, Öl, Kühlwasser, Bremsflüssigkeit, Batterie, Schrauben-Festigkeit, Schäden, Verschleiß, - Kilometerstand, Lack, Vergaser-/Zündungseinstellungen -- Anbauen/Abbauen von Teilen und Schrauben (PlayMaker-Events) -- Türen, Tore, Hauben (z.B. Garagentor), Geld, Uhrzeit und Wetter - -**Im Spiel** -- **T** – Chat -- **F7** – MSCO-Konsole mit allen Befehlen -- **/admin** – Admin-Menü für Server-Admins bzw. den P2P-Host: Spieler kicken/bannen, GOTO/BRING (teleportieren), - Cheats (+1.000 / +10.000 MK, Bedürfnisse auffüllen, Satsuma zu sich holen) – Cheats werden im Chat angezeigt -- **P** – als Beifahrer ein-/aussteigen -- Alle Tasten sind in den MSCLoader-Einstellungen der Mod änderbar -- Rich Presence: zeigt Freunden deinen Status („In the Menus“, Server, Spielerzahl) - -## Installation - -1. [MSCLoader](https://github.com/piotrulos/MSCModLoader) installieren. -2. `MSCO.dll` von den [Releases](https://git.mbm.wtf/MrMaho/MSCO/releases/latest) herunterladen und in den - Mods-Ordner kopieren (Standard: `Documents\MySummerCar\Mods`). -3. Spiel **über Steam** starten – ohne Steam gehen nur Non-Steam-Server. - -### Einen eigenen Server betreiben - -Siehe [MSCO-Dedicated-Server](https://git.mbm.wtf/MrMaho/MSCO-Dedicated-Server) – Lizenzschlüssel gibt es kostenlos -unter https://msco.mbm.wtf/keys. - -## Probleme? - -| Problem | Lösung | -|---|---| -| Server fehlt im Browser | REFRESH drücken; Filter (STEAM / NON-STEAM) prüfen; der Server muss von außen erreichbar sein | -| „This server requires Steam“ | Spiel über Steam starten | -| Warnung „Version mismatch“ | Mod und Server auf dieselbe Version bringen (Releases) | -| Eigener Spielstand weg | Wird nach dem Verlassen automatisch wiederhergestellt; Sicherung liegt in `AppData\LocalLow\Amistech\My Summer Car\MSCO_Backup` | -| Absturz / Hänger beim Beitreten | `output_log.txt` im Spielordner an den Server-Betreiber bzw. als Issue schicken | - -## Befehle - -In der F7-Konsole direkt, in der MSCLoader-Konsole mit `mp` davor (z.B. `mp connect ...`): - -| Befehl | Beschreibung | -|---|---| -| `connect ` | mit einem dedizierten Server verbinden | -| `disconnect` | Server / Spiel verlassen | -| `host [port]` / `join [port]` | LAN-Testsitzung ohne Steam | -| `save` | Spiel speichern (Host / Einzelspieler) | -| `ping [on\|off]` | Ping zum Server oben rechts anzeigen (grün < 80 ms, gelb < 150 ms, rot darüber) | -| `admin` bzw. `/admin` im Chat | Admin-Menü | -| `vehicles`, `rig` | Diagnose: Fahrzeuge / Spielermodelle | -| `debug` | Sync-Debugausgaben an/aus | -| `clear` | Konsole leeren | - -## Selbst bauen - -- Eine C#-Entwicklungsumgebung, .NET Framework 3.5 (Unity 5.0 / Mono) -- Die Verweise in `MSCO.csproj` zeigen auf `F:\SteamLibrary\steamapps\common\My Summer Car\mysummercar_Data\Managed\` - (UnityEngine, PlayMaker, Assembly-CSharp, Assembly-CSharp-firstpass, MSCLoader, 0Harmony, Newtonsoft.Json, cInput) – - bei anderem Installationsort anpassen. -- Nach dem Build wird die DLL automatisch nach `Documents\MySummerCar\Mods` kopiert (`MSCMODSFOLDER` in der csproj). - -``` -msbuild MSCO.csproj -p:Configuration=Release -``` - -### Updates veröffentlichen (MSC Launcher / MSCLoader) - -- **Kleines Update** (Fehlerbehebungen, neue Funktionen, Netzwerk unverändert): in `MSCO.cs` nur die dritte Stelle von - `ModVersion` erhöhen (`2.8.1` → `2.8.2`), Release bauen und `bin/Release/MSCO.dll` hochladen. Spieler mit 2.8.x - spielen weiter zusammen, Server 2.8 müssen nicht aktualisiert werden. -- **Großes Update** (Protokoll inkompatibel geändert): `ProtocolVersion` in `MSCO.cs` **und** `GameServer.ModVersion` im - Server erhöhen (z.B. `2.9`), `ModVersion` auf `2.9.0`. Dann brauchen alle die neue Mod und den neuen Server. -- Verglichen werden immer nur die ersten zwei Stellen; übers Netz geht nur die Netzwerk-Version. - -## Aufbau - -| Datei | Aufgabe | -|---|---| -| `MSCO.cs` | Mod-Einstieg, Tastenbelegung | -| `MultiplayerManager.cs` | Sitzung, Nachrichten, Spielerliste, Spielstart, HUD | -| `NetSession.cs` | Netzwerk (TCP und Steam P2P), Protokoll | -| `LobbyUI.cs`, `Overlays.cs`, `UiTheme.cs` | Launcher, Konsole/Chat/Admin-Menü, gemeinsamer Stil | -| `ServerBrowser.cs`, `WinHttp.cs` | Serverliste (TLS 1.2 über WinHTTP), Server-Abfrage | -| `ObjectSync.cs` | Items/Teile/Fahrzeuge mit Besitzer-System | -| `VehicleStateSync.cs`, `VehicleFx.cs`, `Passenger.cs` | Fahrzeugzustand, Lichter/Sound, Beifahrer | -| `FsmSync.cs`, `DoorSync.cs`, `WorldSync.cs`, `MoneySync.cs` | Montage-Events, Türen, Zeit/Wetter, Geld | -| `RemotePlayer.cs` | Spielfiguren der Mitspieler | -| `SaveSync.cs`, `MenuHelper.cs` | Spielstand übertragen/sichern, Laden aus dem Menü | -| `SteamLobby.cs`, `JoinLinks.cs`, `DiscordPresence.cs` | Steam-Lobbys, `msco://`-Links, Rich Presence | -| `SafetyPatches.cs`, `InputLock.cs`, `SceneCache.cs` | Absturzschutz, Eingabesperre, geteilte FSM-Suche | - -## Bekannte Einschränkungen - -- Teile, die nach dem Server-Spielstand montiert wurden, werden für neue Spieler nachgespielt – das klappt nicht immer - perfekt. `reset-world` auf dem Server setzt den Stand zurück. -- Maximal 3 Spieler. - -## Lizenz - -GNU AGPL-3.0 – siehe [LICENSE.txt](LICENSE.txt). - -Made by **MBM** – [mbm.wtf](https://mbm.wtf) +# MSCO – My Summer Car Online + +Multiplayer-Mod für **My Summer Car** (MSCLoader). Spiel mit bis zu 3 Spielern zusammen – per Steam-Einladung +(P2P) oder auf einem dedizierten Server aus dem Server-Browser. + +- Mod: dieses Repository +- Dedizierter Server: [MSCO-Dedicated-Server](https://git.mbm.wtf/MrMaho/MSCO-Dedicated-Server) +- Keymaster & Serverliste: [MSCO-Keymaster](https://git.mbm.wtf/MrMaho/MSCO-Keymaster) – live unter https://msco.mbm.wtf + +## Features + +**Verbinden** +- Launcher im Hauptmenü: P2P-Seite und Server-Browser +- **P2P über Steam:** HOST GAME, Freunde einladen, Beitritt über die Steam-Freundesliste (max. 3 Spieler) +- **Server-Browser:** Suche, Filter (Steam / Non-Steam / volle ausblenden), Ping, Server-Profil + (Besitzer, Version, Laufzeit, Spieler), lokale Server auf diesem PC werden automatisch gefunden +- **Direct Connect** per Adresse, JOIN-Links von der Website (`msco://`) starten das Spiel und verbinden direkt +- Server ohne Steam („Non-Steam“) werden unterstützt, andere Mod-Version = Warnung statt Sperre +- Der Host-Spielstand wird beim Start automatisch an alle übertragen; der eigene Spielstand wird vorher gesichert + und nach dem Spielen wiederhergestellt + +**Synchronisiert** +- Spieler als eigene Figur im MSC-Stil (Karohemd, Jeans, Schnurrbart, Kappe – je Spieler etwas anders) mit + Blickrichtung, Laufen, Ducken/Lehnen, Sitzen, gehaltenem Item und Namensschild +- Items, lose Teile, Schrauben und Fahrzeuge (auch mit G geschoben) mit Besitzer-System – inkl. was jemand in der Hand hält +- Fahrzeuge: Position, Lichter, Motorgeräusch; als **Beifahrer** mitfahren (Taste P) +- **Fahrzeugzustand:** Tank, Öl, Kühlwasser, Bremsflüssigkeit, Batterie, Schrauben-Festigkeit, Schäden, Verschleiß, + Kilometerstand, Lack, Vergaser-/Zündungseinstellungen +- Anbauen/Abbauen von Teilen und Schrauben (PlayMaker-Events) +- Türen, Tore, Hauben (z.B. Garagentor), Geld, Uhrzeit und Wetter + +**Im Spiel** +- **T** – Chat +- **F7** – MSCO-Konsole mit allen Befehlen +- **/admin** – Admin-Menü für Server-Admins bzw. den P2P-Host: Spieler kicken/bannen, GOTO/BRING (teleportieren), + Cheats (+1.000 / +10.000 MK, Bedürfnisse auffüllen, Satsuma zu sich holen) – Cheats werden im Chat angezeigt +- **P** – als Beifahrer ein-/aussteigen +- Alle Tasten sind in den MSCLoader-Einstellungen der Mod änderbar +- Rich Presence: zeigt Freunden deinen Status („In the Menus“, Server, Spielerzahl) + +## Installation + +1. [MSCLoader](https://github.com/piotrulos/MSCModLoader) installieren. +2. `MSCO.dll` von den [Releases](https://git.mbm.wtf/MrMaho/MSCO/releases/latest) herunterladen und in den + Mods-Ordner kopieren (Standard: `Documents\MySummerCar\Mods`). +3. Spiel **über Steam** starten – ohne Steam gehen nur Non-Steam-Server. + +### Einen eigenen Server betreiben + +Siehe [MSCO-Dedicated-Server](https://git.mbm.wtf/MrMaho/MSCO-Dedicated-Server) – Lizenzschlüssel gibt es kostenlos +unter https://msco.mbm.wtf/keys. + +## Probleme? + +| Problem | Lösung | +|---|---| +| Server fehlt im Browser | REFRESH drücken; Filter (STEAM / NON-STEAM) prüfen; der Server muss von außen erreichbar sein | +| „This server requires Steam“ | Spiel über Steam starten | +| Warnung „Version mismatch“ | Mod und Server auf dieselbe Version bringen (Releases) | +| Eigener Spielstand weg | Wird nach dem Verlassen automatisch wiederhergestellt; Sicherung liegt in `AppData\LocalLow\Amistech\My Summer Car\MSCO_Backup` | +| Absturz / Hänger beim Beitreten | `output_log.txt` im Spielordner an den Server-Betreiber bzw. als Issue schicken | + +## Befehle + +In der F7-Konsole direkt, in der MSCLoader-Konsole mit `mp` davor (z.B. `mp connect ...`): + +| Befehl | Beschreibung | +|---|---| +| `connect ` | mit einem dedizierten Server verbinden | +| `disconnect` | Server / Spiel verlassen | +| `host [port]` / `join [port]` | LAN-Testsitzung ohne Steam | +| `save` | Spiel speichern (Host / Einzelspieler) | +| `ping [on\|off]` | Ping zum Server oben rechts anzeigen (grün < 80 ms, gelb < 150 ms, rot darüber) | +| `admin` bzw. `/admin` im Chat | Admin-Menü | +| `vehicles`, `rig` | Diagnose: Fahrzeuge / Spielermodelle | +| `debug` | Sync-Debugausgaben an/aus | +| `clear` | Konsole leeren | + +## Selbst bauen + +- Eine C#-Entwicklungsumgebung, .NET Framework 3.5 (Unity 5.0 / Mono) +- Die Verweise in `MSCO.csproj` zeigen auf `F:\SteamLibrary\steamapps\common\My Summer Car\mysummercar_Data\Managed\` + (UnityEngine, PlayMaker, Assembly-CSharp, Assembly-CSharp-firstpass, MSCLoader, 0Harmony, Newtonsoft.Json, cInput) – + bei anderem Installationsort anpassen. +- Nach dem Build wird die DLL automatisch nach `Documents\MySummerCar\Mods` kopiert (`MSCMODSFOLDER` in der csproj). + +``` +msbuild MSCO.csproj -p:Configuration=Release +``` + +### Updates veröffentlichen (MSC Launcher / MSCLoader) + +- **Kleines Update** (Fehlerbehebungen, neue Funktionen, Netzwerk unverändert): in `MSCO.cs` nur die dritte Stelle von + `ModVersion` erhöhen (`2.8.1` → `2.8.2`), Release bauen und `bin/Release/MSCO.dll` hochladen. Spieler mit 2.8.x + spielen weiter zusammen, Server 2.8 müssen nicht aktualisiert werden. +- **Großes Update** (Protokoll inkompatibel geändert): `ProtocolVersion` in `MSCO.cs` **und** `GameServer.ModVersion` im + Server erhöhen (z.B. `2.9`), `ModVersion` auf `2.9.0`. Dann brauchen alle die neue Mod und den neuen Server. +- Verglichen werden immer nur die ersten zwei Stellen; übers Netz geht nur die Netzwerk-Version. +- **Automatisch hochladen**: Ist lokal `MSCO_RELEASE_TOKEN` gesetzt (= `RELEASE_TOKEN` des Keymasters, oder in + `%AppData%\MSCO elease-token.txt`), lädt jeder Release-Build eine neue Version selbst auf den Keymaster + (`release.ps1`, Changelog aus dem passenden Abschnitt in `CHANGELOG.md`). Gibt es die Version schon, passiert nichts. + +## Aufbau + +| Datei | Aufgabe | +|---|---| +| `MSCO.cs` | Mod-Einstieg, Tastenbelegung | +| `MultiplayerManager.cs` | Sitzung, Nachrichten, Spielerliste, Spielstart, HUD | +| `NetSession.cs` | Netzwerk (TCP und Steam P2P), Protokoll | +| `LobbyUI.cs`, `Overlays.cs`, `UiTheme.cs` | Launcher, Konsole/Chat/Admin-Menü, gemeinsamer Stil | +| `ServerBrowser.cs`, `WinHttp.cs` | Serverliste (TLS 1.2 über WinHTTP), Server-Abfrage | +| `ObjectSync.cs` | Items/Teile/Fahrzeuge mit Besitzer-System | +| `VehicleStateSync.cs`, `VehicleFx.cs`, `Passenger.cs` | Fahrzeugzustand, Lichter/Sound, Beifahrer | +| `FsmSync.cs`, `DoorSync.cs`, `WorldSync.cs`, `MoneySync.cs` | Montage-Events, Türen, Zeit/Wetter, Geld | +| `RemotePlayer.cs` | Spielfiguren der Mitspieler | +| `SaveSync.cs`, `MenuHelper.cs` | Spielstand übertragen/sichern, Laden aus dem Menü | +| `SteamLobby.cs`, `JoinLinks.cs`, `DiscordPresence.cs` | Steam-Lobbys, `msco://`-Links, Rich Presence | +| `SafetyPatches.cs`, `InputLock.cs`, `SceneCache.cs` | Absturzschutz, Eingabesperre, geteilte FSM-Suche | + +## Bekannte Einschränkungen + +- Teile, die nach dem Server-Spielstand montiert wurden, werden für neue Spieler nachgespielt – das klappt nicht immer + perfekt. `reset-world` auf dem Server setzt den Stand zurück. +- Maximal 3 Spieler. + +## Lizenz + +GNU AGPL-3.0 – siehe [LICENSE.txt](LICENSE.txt). + +Made by **MBM** – [mbm.wtf](https://mbm.wtf) diff --git a/release.ps1 b/release.ps1 new file mode 100644 index 0000000..d422ef0 --- /dev/null +++ b/release.ps1 @@ -0,0 +1,79 @@ +# Neue Version automatisch auf den Keymaster hochladen (msco.mbm.wtf -> /download, Launcher-Updates). +# Läuft nach dem Release-Build von selbst (MSCO.csproj bzw. MSCO.Launcher.csproj) - oder von Hand: +# powershell -ExecutionPolicy Bypass -File release.ps1 -Product mod -File bin\Release\MSCO.dll +# +# Braucht den Release-Token des Keymasters (RELEASE_TOKEN in dessen .env), lokal als Umgebungsvariable +# MSCO_RELEASE_TOKEN oder in %AppData%\MSCO\release-token.txt. Ohne Token wird nichts hochgeladen. +# Gibt es die Version auf dem Keymaster schon, passiert nichts - also einfach die Version erhöhen und bauen. +param( + [Parameter(Mandatory = $true)][ValidateSet("mod", "launcher")][string]$Product, + [Parameter(Mandatory = $true)][string]$File, + [string]$Version = "", + [string]$Changelog = "" +) +$ErrorActionPreference = "Stop" +$here = Split-Path -Parent $MyInvocation.MyCommand.Path + +$token = $env:MSCO_RELEASE_TOKEN +$tokenFile = Join-Path $env:APPDATA "MSCO\release-token.txt" +if (-not $token -and (Test-Path $tokenFile)) { $token = (Get-Content $tokenFile -Raw).Trim() } +if (-not $token) { + Write-Host "MSCO release: no release token (MSCO_RELEASE_TOKEN or $tokenFile) - not uploading." + exit 0 +} +$keymaster = if ($env:MSCO_KEYMASTER) { $env:MSCO_KEYMASTER.TrimEnd("/") } else { "https://msco.mbm.wtf" } + +if (-not (Test-Path $File)) { Write-Host "MSCO release: $File not found"; exit 1 } + +# Version: aus MSCO.cs (Mod) bzw. aus der Datei (Produktversion) +if (-not $Version) { + $source = Join-Path $here "MSCO.cs" + if ($Product -eq "mod" -and (Test-Path $source)) { + $m = Select-String -Path $source -Pattern 'ModVersion\s*=\s*"([^"]+)"' | Select-Object -First 1 + if ($m) { $Version = $m.Matches[0].Groups[1].Value } + } + if (-not $Version) { $Version = ((Get-Item $File).VersionInfo.ProductVersion -split '\+')[0] } +} + +# Changelog: Abschnitt "## " aus CHANGELOG.md (Text ohne Markdown, gekürzt) +if (-not $Changelog) { + $log = Join-Path $here "CHANGELOG.md" + if (Test-Path $log) { + $lines = Get-Content $log -Encoding UTF8 + $start = [Array]::FindIndex($lines, [Predicate[string]] { param($l) $l -match "^##\s+$([regex]::Escape($Version))\b" }) + if ($start -ge 0) { + $text = @() + for ($i = $start + 1; $i -lt $lines.Count -and $lines[$i] -notmatch '^##\s'; $i++) { + $l = $lines[$i].Trim() -replace '\*\*', '' -replace '`', '' + if ($l) { $text += $l } + } + $Changelog = ($text -join " ") + if ($Changelog.Length -gt 3500) { $Changelog = $Changelog.Substring(0, 3500) + " …" } + } + } +} + +Add-Type -AssemblyName System.Net.Http +$client = New-Object System.Net.Http.HttpClient +$client.Timeout = [TimeSpan]::FromMinutes(10) +$client.DefaultRequestHeaders.Authorization = New-Object System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $token) +$form = New-Object System.Net.Http.MultipartFormDataContent +$form.Add((New-Object System.Net.Http.StringContent($Product)), "product") +$form.Add((New-Object System.Net.Http.StringContent($Version)), "version") +$form.Add((New-Object System.Net.Http.StringContent($Changelog)), "changelog") +$bytes = [System.IO.File]::ReadAllBytes((Resolve-Path $File)) +$form.Add((New-Object System.Net.Http.ByteArrayContent(,$bytes)), "file", [System.IO.Path]::GetFileName($File)) + +try { + $res = $client.PostAsync("$keymaster/api/releases/upload", $form).GetAwaiter().GetResult() + $body = $res.Content.ReadAsStringAsync().GetAwaiter().GetResult() +} catch { + Write-Host "MSCO release: keymaster not reachable ($($_.Exception.Message)) - not uploaded" + exit 0 +} +switch ([int]$res.StatusCode) { + 200 { Write-Host "MSCO release: $Product $Version uploaded to $keymaster" } + 409 { Write-Host "MSCO release: $Product $Version is already on the keymaster - raise the version to publish a new one" } + default { Write-Host "MSCO release: upload failed (HTTP $([int]$res.StatusCode)): $body" } +} +exit 0