From 6d349399abea159466c9ee4bbf93ec85d245eb67 Mon Sep 17 00:00:00 2001 From: MrMaho Date: Sat, 26 Sep 2026 22:45:11 +0200 Subject: [PATCH] Ping measurement and display (console: ping) Co-Authored-By: Claude Opus 5.5 --- Commands.cs | 7 +++++ MultiplayerManager.cs | 67 ++++++++++++++++++++++++++++++++++++++++++- NetSession.cs | 3 +- README.md | 1 + 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/Commands.cs b/Commands.cs index 32a05ed..e5f61ac 100644 --- a/Commands.cs +++ b/Commands.cs @@ -13,6 +13,7 @@ namespace MSCO "disconnect - leave the server / game\n" + "host [port] / join [port] - direct LAN game (no Steam)\n" + "save - save the game (host / singleplayer)\n" + + "ping [on|off] - show your ping to the server (toggle)\n" + "/admin - admin menu (kick / ban / teleport / cheats)\n" + "vehicles | rig - debug info about vehicles / player models\n" + "debug - toggle sync debug output\n" + @@ -61,6 +62,12 @@ namespace MSCO case "save": mp.SaveGame(); break; + case "ping": + // "ping" schaltet die Anzeige um, "ping on/off" setzt sie + if (args.Length > 1) mp.ShowPing = args[1].ToLower() == "on" || args[1] == "1"; + else mp.ShowPing = !mp.ShowPing; + print("Ping: " + mp.PingText + " (display " + (mp.ShowPing ? "on" : "off") + ")"); + break; case "admin": case "/admin": mp.OpenAdminMenu(); diff --git a/MultiplayerManager.cs b/MultiplayerManager.cs index 62a58bd..4122ece 100644 --- a/MultiplayerManager.cs +++ b/MultiplayerManager.cs @@ -64,6 +64,9 @@ namespace MSCO Steamworks.CSteamID pendingLobby; // Einladung, die noch angenommen werden muss Steamworks.CSteamID steamHost; // Client: Steam-ID des Hosts float nextPing; + float pingMs = -1f; // geglättete Laufzeit zum Server/Host (-1 = noch unbekannt) + const string PrefShowPing = "MSCO_ShowPing"; + GUIStyle pingStyle; float savingMessageUntil; GUIStyle hudStyle, savingStyle; Texture2D hudBackground; @@ -221,6 +224,48 @@ namespace MSCO return list; } + // ---------------------------------------------------------------- Ping + + /// Laufzeit zum Server/Host in ms (-1 = unbekannt, z.B. alter Server oder man ist selbst Host). + public float PingMs { get { return pingMs; } } + + /// Ping-Anzeige oben rechts (Konsole: "ping"), bleibt gespeichert. + public bool ShowPing + { + get { return PlayerPrefs.GetInt(PrefShowPing, 0) == 1; } + set { PlayerPrefs.SetInt(PrefShowPing, value ? 1 : 0); } + } + + /// Text für Anzeige und Konsole. + public string PingText + { + get + { + if (session == null) return "not connected"; + if (session.IsHost) return "you are the host"; + return pingMs < 0f ? "measuring..." : Mathf.RoundToInt(pingMs) + " ms"; + } + } + + void DrawPing() + { + if (!ShowPing || session == null) return; + if (pingStyle == null) + { + pingStyle = UiTheme.Panel9(new Color(0.06f, 0.06f, 0.07f, 0.85f), 6); + pingStyle.fontSize = 12; + pingStyle.fontStyle = FontStyle.Bold; + pingStyle.alignment = TextAnchor.MiddleCenter; + pingStyle.padding = new RectOffset(10, 10, 0, 0); + } + // Farbe nach Qualität: grün < 80 ms, gelb < 150 ms, sonst rot + Color color = pingMs < 0f ? UiTheme.Muted : pingMs < 80f ? UiTheme.Online : pingMs < 150f ? UiTheme.Pending : UiTheme.Danger; + pingStyle.normal.textColor = color; + var content = new GUIContent("PING " + PingText); + float width = pingStyle.CalcSize(content).x; + GUI.Box(new Rect(Screen.width - width - 12, 8, width, 24), content, pingStyle); + } + // ---------------------------------------------------------------- Cheats (Admin-Menü) /// Cheats nur im Spiel und nur für Server-Admins bzw. den P2P-Host. @@ -637,7 +682,8 @@ namespace MSCO if (Time.realtimeSinceStartup >= nextPing) { nextPing = Time.realtimeSinceStartup + PingInterval; - session.SendToAll(MsgType.Ping); + float sentAt = Time.realtimeSinceStartup; + session.SendToAll(MsgType.Ping, NetSession.Build(w => w.Write(sentAt))); // Zeitstempel für die Ping-Messung } foreach (NetEvent e in session.Poll()) @@ -704,6 +750,7 @@ namespace MSCO if (session != null && session.IsSteam) steam.Leave(); session = null; handshakeDone = false; + pingMs = -1f; teleportToHost = false; dedicated = false; connectingToServer = false; @@ -752,6 +799,22 @@ namespace MSCO { BinaryReader r = m.Reader(); + // Ping-Messung: der Host schickt den Zeitstempel sofort zurück, der Client rechnet die Laufzeit aus + if (m.Type == MsgType.Ping) + { + if (session.IsHost && m.Payload.Length >= 4) session.SendTo(peerId, MsgType.Pong, m.Payload); + return; + } + if (m.Type == MsgType.Pong) + { + if (!session.IsHost && m.Payload.Length >= 4) + { + float rtt = (Time.realtimeSinceStartup - r.ReadSingle()) * 1000f; + if (rtt >= 0f && rtt < 60000f) pingMs = pingMs < 0f ? rtt : Mathf.Lerp(pingMs, rtt, 0.4f); + } + return; + } + if (IsGameMessage(m.Type)) { int from; @@ -1374,6 +1437,7 @@ namespace MSCO if (MenuHelper.InMenu) { lobby.Draw(this); + DrawPing(); overlays.Draw(this, false); return; } @@ -1383,6 +1447,7 @@ namespace MSCO GUI.Label(new Rect(0, Screen.height / 2f - 40, Screen.width, 80), "SAVING GAME...", savingStyle); if (session != null) DrawHud(); + DrawPing(); overlays.Draw(this, session != null); } diff --git a/NetSession.cs b/NetSession.cs index f6893e4..b34fd35 100644 --- a/NetSession.cs +++ b/NetSession.cs @@ -38,7 +38,8 @@ namespace MSCO AdminResult = 27, // Server -> Client: string Meldung Chat = 28, // Chatnachricht (string) VarSync = 29, // Fahrzeugzustand: int n, je [int key, byte typ, wert] - Teleport = 30 // Admin holt einen Spieler zu sich: 3 float Position + Teleport = 30, // Admin holt einen Spieler zu sich: 3 float Position + Pong = 31 // Antwort auf Ping mit demselben Zeitstempel (Laufzeit messen) } public struct Message diff --git a/README.md b/README.md index 1d0f799..65576e2 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ In der F8-Konsole direkt, in der MSCLoader-Konsole mit `mp` davor (z.B. `mp conn | `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 |