using Sandbox; using Sandbox.Diagnostics; using System; using System.Diagnostics; /// /// The dedicated server's console status bar. It draws some timings and the player count, which is updated every time a log comes in. /// internal class DedicatedServerConsole { ConsoleInput input; Stopwatch uptime; public DedicatedServerConsole() { input = new ConsoleInput(); input.OnInputText += OnInput; uptime = Stopwatch.StartNew(); } RealTimeSince timeSinceUpdate = 10; void UpdateStatus() { if ( timeSinceUpdate < 0.5f ) return; timeSinceUpdate = 0; var uptimeString = $"{uptime.Elapsed.TotalHours:n0}:{uptime.Elapsed.ToString( "mm\\:ss" )}"; int width; try { width = Console.BufferWidth - 1; } catch { // Fall back to a default width width = 80; } var name = string.IsNullOrEmpty( Networking.ServerName ) ? "s&box server" : Networking.ServerName; var maxPlayers = Application.GamePackage?.GetCachedMeta( "MaxPlayers", 32 ) ?? 32; var topLeft = $"{name} ({Connection.All.Count}/{maxPlayers}) [{uptimeString}]"; var topRight = $"Network {PerformanceStats.Timings.Network.AverageMs( 1 ):0.00}ms"; var bottomLeft = $"Physics {PerformanceStats.Timings.Physics.AverageMs( 1 ):0.00}ms,"; bottomLeft += $" NavMesh {PerformanceStats.Timings.NavMesh.AverageMs( 1 ):0.00}ms,"; bottomLeft += $" Animation {PerformanceStats.Timings.Animation.AverageMs( 1 ):0.00}ms"; var bottomRight = $"Scene {PerformanceStats.Timings.Scene.AverageMs( 60 ):0.00}ms"; var lineA = topRight.PadLeft( width ); lineA = topLeft + ((topLeft.Length < lineA.Length) ? lineA.Substring( topLeft.Length ) : ""); var lineB = bottomRight.PadLeft( width ); lineB = bottomLeft + ((bottomLeft.Length < lineB.Length) ? lineB.Substring( bottomLeft.Length ) : ""); input.SetStatus( 1, lineA ); input.SetStatus( 2, lineB ); } public void Clear() { var width = Console.BufferWidth - 1; var height = Console.BufferHeight; var outputEnd = height - 4; var (x, y) = Console.GetCursorPosition(); if ( y >= outputEnd ) { var fillSize = (width - x) + (width * (height - outputEnd - 1)); Span whitespace = stackalloc char[fillSize]; whitespace.Fill( ' ' ); Console.Out.Write( whitespace ); Console.SetCursorPosition( x, y ); } } public void Update() { UpdateStatus(); input.Update(); } void OnInput( string input ) { if ( input == "clear" ) { Console.Clear(); return; } ConVarSystem.Run( input ); } }