diff --git a/BSO.Launcher.csproj b/BSO.Launcher.csproj
index 36f40ce..5fa9338 100644
--- a/BSO.Launcher.csproj
+++ b/BSO.Launcher.csproj
@@ -8,7 +8,7 @@
enable
BSO.Launcher
BSO-Launcher
- 0.2.0
+ 0.3.0
MBM.wtf
BSO Launcher
BSO Launcher - Bus Simulator Online
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e8150c..f928d12 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,12 @@
Neue Version: hier einen Abschnitt `## ` anlegen, `` in `BSO.Launcher.csproj` erhöhen, dann
`dotnet publish -c Release -o publish -p:BsoRelease=true` – der Abschnitt wird der Changelog auf der Website und im Launcher.
+## 0.3.0
+- Freunde: per Benutzername hinzufügen, Anfragen annehmen, sehen wer online ist
+- Lobby: Freunde einladen, Server starten, zusammen spielen – der Server läuft auf dem BSO-Relay, keine Portfreigabe nötig
+- Knopf „Mod herunterladen“ holt jederzeit die neueste Mod
+- Server-Browser entfernt
+
## 0.2.0
- Server-Browser: alle öffentlichen Server mit Spielerzahl und Ping, BEITRETEN startet das Spiel und verbindet automatisch
- Direkt per Adresse verbinden
diff --git a/MainForm.cs b/MainForm.cs
index 001883d..4c3a85b 100644
--- a/MainForm.cs
+++ b/MainForm.cs
@@ -19,9 +19,9 @@ public sealed class MainForm : Form
readonly Settings settings = Settings.Load();
/// Befehle, die nur einmal gleichzeitig laufen duerfen (Downloads/Installationen/Start).
- static readonly HashSet Exclusive = new() { "installMod", "launch", "join", "installLauncherUpdate", "uninstall" };
+ static readonly HashSet Exclusive = new() { "installMod", "launch", "playLobby", "installLauncherUpdate", "uninstall" };
readonly HashSet running = new();
- static readonly HashSet QuietCommands = new() { "window", "status", "me", "init", "releases", "servers" };
+ static readonly HashSet QuietCommands = new() { "window", "status", "me", "init", "releases", "friends", "lobby" };
bool updateInstalled;
static readonly JsonSerializerOptions Json = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
@@ -288,18 +288,23 @@ public sealed class MainForm : Form
return await InstallMod();
case "launch":
return await Launch();
- case "servers":
- return await ServerList();
- case "join":
- {
- // Beitreten: Server merken, beim Start automatisch verbinden, Spiel starten
- string address = Arg(args, "address").Trim();
- if (address.Length == 0 || address.Length > 260) throw new Exception("Ungueltige Serveradresse");
- settings.Server = address;
- settings.AutoConnect = true;
- settings.Save();
- return await Launch();
- }
+ case "playLobby":
+ return await Launch(lobby: true);
+
+ // --- Freunde und Lobby (Website, mit dem Konto-Token)
+ case "friends": return await Site("GET", "/api/friends");
+ case "friendRequest": return await Site("POST", "/api/friends/request", new { username = Arg(args, "username").Trim() });
+ case "friendAccept": return await Site("POST", "/api/friends/accept", new { id = Arg(args, "id") });
+ case "friendRemove": return await Site("POST", "/api/friends/remove", new { id = Arg(args, "id") });
+ case "lobby": return await Site("GET", "/api/lobby");
+ case "lobbyCreate": return await Site("POST", "/api/lobby/create");
+ case "lobbyInvite": return await Site("POST", "/api/lobby/invite", new { accountId = Arg(args, "accountId") });
+ case "lobbyJoin": return await Site("POST", "/api/lobby/join", new { lobbyId = Arg(args, "lobbyId") });
+ case "lobbyDecline": return await Site("POST", "/api/lobby/decline", new { lobbyId = Arg(args, "lobbyId") });
+ case "lobbyLeave": return await Site("POST", "/api/lobby/leave");
+ case "lobbyKick": return await Site("POST", "/api/lobby/kick", new { accountId = Arg(args, "accountId") });
+ case "lobbyStart": return await Site("POST", "/api/lobby/start");
+ case "lobbyStop": return await Site("POST", "/api/lobby/stop");
case "releases":
{
var r = await Api.Releases();
@@ -375,19 +380,21 @@ public sealed class MainForm : Form
};
}
- /// Serverliste der Website, jeder Server direkt angefragt (Ping, aktuelle Spielerzahl). Nicht erreichbar = ohne Ping.
- static async Task