123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- using System;
- using System.IO;
- using UnityEngine;
- namespace Mirror
- {
-
- struct Stats
- {
-
- public int connections;
- public double uptime;
- public int configuredTickRate;
- public int actualTickRate;
-
- public long sentBytesPerSecond;
- public long receiveBytesPerSecond;
-
- public float serverTickInterval;
- public double fullUpdateAvg;
- public double serverEarlyAvg;
- public double serverLateAvg;
- public double transportEarlyAvg;
- public double transportLateAvg;
-
- public Stats(
- // general
- int connections,
- double uptime,
- int configuredTickRate,
- int actualTickRate,
- // traffic
- long sentBytesPerSecond,
- long receiveBytesPerSecond,
- // cpu
- float serverTickInterval,
- double fullUpdateAvg,
- double serverEarlyAvg,
- double serverLateAvg,
- double transportEarlyAvg,
- double transportLateAvg
- )
- {
-
- this.connections = connections;
- this.uptime = uptime;
- this.configuredTickRate = configuredTickRate;
- this.actualTickRate = actualTickRate;
-
- this.sentBytesPerSecond = sentBytesPerSecond;
- this.receiveBytesPerSecond = receiveBytesPerSecond;
-
- this.serverTickInterval = serverTickInterval;
- this.fullUpdateAvg = fullUpdateAvg;
- this.serverEarlyAvg = serverEarlyAvg;
- this.serverLateAvg = serverLateAvg;
- this.transportEarlyAvg = transportEarlyAvg;
- this.transportLateAvg = transportLateAvg;
- }
- }
-
- public class RemoteStatistics : NetworkBehaviour
- {
-
- protected NetworkStatistics NetworkStatistics;
-
-
-
- [Tooltip("Send stats every 'interval' seconds to client.")]
- public float sendInterval = 1;
- double lastSendTime;
- [Header("GUI")]
- public bool showGui;
- public KeyCode hotKey = KeyCode.F11;
- Rect windowRect = new Rect(0, 0, 400, 400);
-
-
-
- [Header("Authentication")]
- public string passwordFile = "remote_statistics.txt";
- protected bool serverAuthenticated;
- protected bool clientAuthenticated;
- protected string serverPassword = null;
- protected string clientPassword = "";
-
- Stats stats;
- void LoadPassword()
- {
-
-
-
- string path = Path.GetFullPath(passwordFile);
- if (File.Exists(path))
- {
-
-
- try
- {
- serverPassword = File.ReadAllText(path);
- }
- catch (Exception exception)
- {
- Debug.LogWarning($"RemoteStatistics: failed to read password file: {exception}");
- }
- }
- else
- {
- Debug.LogWarning($"RemoteStatistics: password file has not been created. Authentication will be impossible. Please save the password in: {path}");
- }
- }
- protected override void OnValidate()
- {
- base.OnValidate();
- syncMode = SyncMode.Owner;
- }
-
-
- public override void OnStartServer()
- {
- NetworkStatistics = NetworkManager.singleton.GetComponent<NetworkStatistics>();
- if (NetworkStatistics == null) throw new Exception($"RemoteStatistics requires a NetworkStatistics component on {NetworkManager.singleton.name}!");
-
- LoadPassword();
- }
- public override void OnStartLocalPlayer()
- {
-
- windowRect.x = Screen.width / 2 - windowRect.width / 2;
- windowRect.y = Screen.height / 2 - windowRect.height / 2;
- }
- [TargetRpc]
- void TargetRpcSync(Stats v)
- {
-
- clientAuthenticated = true;
- stats = v;
- }
- [Command]
- public void CmdAuthenticate(string v)
- {
-
-
- if (!string.IsNullOrWhiteSpace(serverPassword) &&
- serverPassword.Equals(v))
- {
- serverAuthenticated = true;
- Debug.Log($"RemoteStatistics: connectionId {connectionToClient.connectionId} authenticated with player {name}");
- }
- }
- void UpdateServer()
- {
-
- if (!serverAuthenticated) return;
-
- if (NetworkTime.localTime >= lastSendTime + sendInterval)
- {
- lastSendTime = NetworkTime.localTime;
-
- TargetRpcSync(new Stats(
-
- NetworkServer.connections.Count,
- NetworkTime.time,
- NetworkServer.tickRate,
- NetworkServer.actualTickRate,
-
- NetworkStatistics.serverSentBytesPerSecond,
- NetworkStatistics.serverReceivedBytesPerSecond,
-
- NetworkServer.tickInterval,
- NetworkServer.fullUpdateDuration.average,
- NetworkServer.earlyUpdateDuration.average,
- NetworkServer.lateUpdateDuration.average,
- 0,
- 0
- ));
- }
- }
- void UpdateClient()
- {
- if (Input.GetKeyDown(hotKey))
- showGui = !showGui;
- }
- void Update()
- {
- if (isServer) UpdateServer();
- if (isLocalPlayer) UpdateClient();
- }
- void OnGUI()
- {
- if (!isLocalPlayer) return;
- if (!showGui) return;
- windowRect = GUILayout.Window(0, windowRect, OnWindow, "Remote Statistics");
- windowRect = Utils.KeepInScreen(windowRect);
- }
-
- void GUILayout_TextAndValue(string text, string value)
- {
- GUILayout.BeginHorizontal();
- GUILayout.Label(text);
- GUILayout.FlexibleSpace();
- GUILayout.Label(value);
- GUILayout.EndHorizontal();
- }
-
- void GUILayout_ProgressBar(double ratio, int width)
- {
-
- ratio = Mathd.Clamp01(ratio);
- GUILayout.HorizontalScrollbar(0, (float)ratio, 0, 1, GUILayout.Width(width));
- }
-
-
-
- void GUILayout_TextAndProgressBar(string text, double ratio, int progressbarWidth, string caption, int captionWidth, Color captionColor)
- {
- GUILayout.BeginHorizontal();
- GUILayout.Label(text);
- GUILayout.FlexibleSpace();
- GUILayout_ProgressBar(ratio, progressbarWidth);
-
- GUI.color = captionColor;
- GUILayout.Label(caption, GUILayout.Width(captionWidth));
- GUI.color = Color.white;
- GUILayout.EndHorizontal();
- }
- void GUI_Authenticate()
- {
- GUILayout.BeginVertical("Box");
- GUILayout.Label("<b>Authentication</b>");
-
-
-
-
-
-
-
- GUILayout.Label("<i>Connection is not encrypted. Use with care!</i>");
-
-
- clientPassword = GUILayout.PasswordField(clientPassword, '*');
-
- GUI.enabled = !string.IsNullOrWhiteSpace(clientPassword);
- if (GUILayout.Button("Authenticate"))
- {
- CmdAuthenticate(clientPassword);
- }
- GUI.enabled = true;
- GUILayout.EndVertical();
- }
- void GUI_General(
- int connections,
- double uptime,
- int configuredTickRate,
- int actualTickRate)
- {
- GUILayout.BeginVertical("Box");
- GUILayout.Label("<b>General</b>");
-
- GUILayout_TextAndValue("Connections:", $"<b>{connections}</b>");
-
- GUILayout_TextAndValue("Uptime:", $"<b>{Utils.PrettySeconds(uptime)}</b>");
-
-
-
- GUI.color = actualTickRate < configuredTickRate ? Color.red : Color.green;
- GUILayout_TextAndValue("Tick Rate:", $"<b>{actualTickRate} Hz / {configuredTickRate} Hz</b>");
- GUI.color = Color.white;
- GUILayout.EndVertical();
- }
- void GUI_Traffic(
- long serverSentBytesPerSecond,
- long serverReceivedBytesPerSecond)
- {
- GUILayout.BeginVertical("Box");
- GUILayout.Label("<b>Network</b>");
- GUILayout_TextAndValue("Outgoing:", $"<b>{Utils.PrettyBytes(serverSentBytesPerSecond) }/s</b>");
- GUILayout_TextAndValue("Incoming:", $"<b>{Utils.PrettyBytes(serverReceivedBytesPerSecond)}/s</b>");
- GUILayout.EndVertical();
- }
- void GUI_Cpu(
- float serverTickInterval,
- double fullUpdateAvg,
- double serverEarlyAvg,
- double serverLateAvg,
- double transportEarlyAvg,
- double transportLateAvg)
- {
- const int barWidth = 120;
- const int captionWidth = 90;
- GUILayout.BeginVertical("Box");
- GUILayout.Label("<b>CPU</b>");
-
-
-
- double fullRatio = fullUpdateAvg / serverTickInterval;
- GUILayout_TextAndProgressBar(
- "World Update Avg:",
- fullRatio,
- barWidth, $"<b>{fullUpdateAvg * 1000:F1} ms</b>",
- captionWidth,
- fullRatio <= 0.9 ? Color.green : Color.red);
-
-
-
- double serverRatio = (serverEarlyAvg + serverLateAvg) / serverTickInterval;
- GUILayout_TextAndProgressBar(
- "Server Update Avg:",
- serverRatio,
- barWidth, $"<b>{serverEarlyAvg * 1000:F1} + {serverLateAvg * 1000:F1} ms</b>",
- captionWidth,
- serverRatio <= 0.9 ? Color.green : Color.red);
-
-
-
-
-
-
-
-
-
-
-
-
- GUILayout.EndVertical();
- }
- void GUI_Notice()
- {
-
-
-
-
-
-
-
-
-
-
- }
- void OnWindow(int windowID)
- {
- if (!clientAuthenticated)
- {
- GUI_Authenticate();
- }
- else
- {
- GUI_General(
- stats.connections,
- stats.uptime,
- stats.configuredTickRate,
- stats.actualTickRate
- );
- GUI_Traffic(
- stats.sentBytesPerSecond,
- stats.receiveBytesPerSecond
- );
- GUI_Cpu(
- stats.serverTickInterval,
- stats.fullUpdateAvg,
- stats.serverEarlyAvg,
- stats.serverLateAvg,
- stats.transportEarlyAvg,
- stats.transportLateAvg
- );
- GUI_Notice();
- }
-
- GUI.DragWindow(new Rect(0, 0, 10000, 10000));
- }
- }
- }
|