0.3.0: Freunde und Lobby, Server-Browser entfernt
- Seite Freunde: hinzufuegen, annehmen, online-Anzeige, Lobby erstellen/einladen/beitreten, Server starten - SPIELEN in der Lobby: Ticket fuer die Lobby + Relay-Adresse in BSO.json - Knopf 'Mod herunterladen' holt jederzeit die neueste Mod Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+3
-13
@@ -71,20 +71,10 @@ public static class Api
|
||||
|
||||
public static Task<Result> Logout(string token) => Send(HttpMethod.Post, "/api/auth/logout", new { }, token);
|
||||
|
||||
/// <summary>Spiel-Ticket fuer die Mod (signiert, 24 h) -> { ticket, username, expiresUtc }</summary>
|
||||
public static Task<Result> Ticket(string token) => Send(HttpMethod.Post, "/api/auth/ticket", new { }, token);
|
||||
|
||||
public sealed record ServerEntry(string name, string description, string address, string host, int port, int players, int maxPlayers,
|
||||
string version, int protocol, string onlineSinceUtc);
|
||||
|
||||
/// <summary>Oeffentliche, erreichbare Server (Serverliste der Website).</summary>
|
||||
public static async Task<List<ServerEntry>> Servers()
|
||||
{
|
||||
var r = await Send(HttpMethod.Get, "/api/servers", null, null);
|
||||
if (!r.Ok) throw new Exception(r.Error ?? "Serverliste nicht verfuegbar");
|
||||
return r.Json.GetProperty("servers").Deserialize<List<ServerEntry>>() ?? new List<ServerEntry>();
|
||||
}
|
||||
|
||||
// --- Freunde und Lobby (alles mit dem Konto-Token)
|
||||
public static Task<Result> Get(string path, string token) => Send(HttpMethod.Get, path, null, token);
|
||||
public static Task<Result> Post(string path, string token, object? body = null) => Send(HttpMethod.Post, path, body ?? new { }, token);
|
||||
public static async Task<Release?> Latest(string product)
|
||||
{
|
||||
var r = await Send(HttpMethod.Get, "/api/releases/latest?product=" + product, null, null);
|
||||
|
||||
+4
-2
@@ -85,8 +85,8 @@ public static class Game
|
||||
LauncherLog.Info("BSO installiert nach " + bin);
|
||||
}
|
||||
|
||||
/// <summary>Einstellungen der Mod (BSO\BSO.json) - Name = Kontoname, Server, automatisch verbinden, Spiel-Ticket.</summary>
|
||||
public static void WriteModConfig(string folder, string? name, string server, bool autoConnect, string? ticket)
|
||||
/// <summary>Einstellungen der Mod (BSO\BSO.json) - Name = Kontoname, Server (Adresse oder relay:<Lobby>), Anzeige, Relay, Spiel-Ticket.</summary>
|
||||
public static void WriteModConfig(string folder, string? name, string server, bool autoConnect, string? ticket, string? label = null, string? relay = null)
|
||||
{
|
||||
string file = Path.Combine(Bin(folder), "BSO", "BSO.json");
|
||||
JsonObject json;
|
||||
@@ -96,6 +96,8 @@ public static class Game
|
||||
json["Server"] = server;
|
||||
json["AutoConnect"] = autoConnect;
|
||||
json["Ticket"] = ticket;
|
||||
json["ServerLabel"] = label;
|
||||
if (relay != null) json["Relay"] = relay;
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(file)!);
|
||||
File.WriteAllText(file, json.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace BSO.Launcher;
|
||||
|
||||
/// <summary>
|
||||
/// Fragt einen BSO-Server direkt ab wie die Mod (wie ServerBrowser.cs bei MSCO): Info senden, InfoReply lesen. Liefert die
|
||||
/// Laufzeit (Ping) und den aktuellen Stand (Spieler) - die Liste der Website ist bis zu einer Minute alt.
|
||||
/// Paketaufbau: [int Laenge][byte Typ][Daten], Info = 9, InfoReply = 10 (string Name, string Version, int Spieler, int max).
|
||||
/// </summary>
|
||||
public static class ServerPing
|
||||
{
|
||||
public sealed record Info(int Ping, string Name, string Version, int Players, int MaxPlayers);
|
||||
|
||||
public static async Task<Info?> Query(string host, int port, int timeoutMs = 2500)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var tcp = new TcpClient { NoDelay = true };
|
||||
using var cts = new CancellationTokenSource(timeoutMs);
|
||||
var clock = Stopwatch.StartNew();
|
||||
await tcp.ConnectAsync(host, port, cts.Token);
|
||||
var stream = tcp.GetStream();
|
||||
await stream.WriteAsync(new byte[] { 1, 0, 0, 0, 9 }, cts.Token);
|
||||
var head = new byte[5];
|
||||
await stream.ReadExactlyAsync(head, cts.Token);
|
||||
int ping = (int)clock.ElapsedMilliseconds;
|
||||
int length = BitConverter.ToInt32(head, 0);
|
||||
if (head[4] != 10 || length < 1 || length > 4096) return null;
|
||||
var payload = new byte[length - 1];
|
||||
await stream.ReadExactlyAsync(payload, cts.Token);
|
||||
using var r = new BinaryReader(new MemoryStream(payload), Encoding.UTF8);
|
||||
return new Info(ping, r.ReadString(), r.ReadString(), r.ReadInt32(), r.ReadInt32());
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user