Files
sbox-public/engine/Sandbox.Engine/Application.cs
Conna Wiles 2f8d00a7ed Networking: Local Instance Id (#3912)
Every time we Join via New Instance, the new instance is given an new id - that id is used locally to determine the SteamId it gives the server (from some base SteamId for bots). This means you can properly test stuff like persistent data per SteamId rather than local instances using the same SteamId as the editor host. This is safe from spoofing though, because real servers and lobbies verify the SteamId the user provides.
2026-01-27 17:28:02 +00:00

240 lines
6.5 KiB
C#

using Editor;
using Sandbox.Engine;
using Sandbox.Engine.Settings;
using Sandbox.Utility;
using Sandbox.VR;
using System.Globalization;
namespace Sandbox;
public static class Application
{
/// <summary>
/// Prevent double initialization
/// </summary>
internal static bool IsInitialized { get; private set; }
/// <summary>
/// Steam AppId of S&amp;box.
/// </summary>
public static ulong AppId { get; internal set; } = 590830;
/// <summary>
/// True if we're running the engine as part of a unit test
/// </summary>
public static bool IsUnitTest { get; internal set; }
/// <summary>
/// True if running without a graphics window, such as in a terminal.
/// </summary>
public static bool IsHeadless { get; private set; }
/// <summary>
/// True if running in a terminal like console, instead of a game window or editor.
/// </summary>
public static bool IsConsoleApp => IsHeadless;
/// <summary>
/// True if this is a dedicated server
/// </summary>
public static bool IsDedicatedServer { get; private set; }
/// <summary>
/// True if running a benchmark
/// </summary>
internal static bool IsBenchmark { get; private set; }
/// <summary>
/// True if running with the tools or editor attached
/// </summary>
public static bool IsEditor { get; private set; }
/// <summary>
/// True if running with -joinlocal. This is an instance that launches and joins
/// an in process editor session.
/// </summary>
internal static bool IsJoinLocal { get; private set; }
/// <summary>
/// A local instance Id assigned when the instance is spawned with -joinlocal. We can use
/// this to create a deterministic fake SteamId for example.
/// </summary>
internal static int LocalInstanceId { get; private set; }
/// <summary>
/// The engine's version string
/// </summary>
public static string Version { get; internal set; }
/// <summary>
/// True if this is compiled and published on steam
/// </summary>
internal static bool IsRetail { get; private set; }
/// <summary>
/// The date of this version, as a UTC datetime.
/// </summary>
public static DateTime VersionDate { get; internal set; }
/// <summary>
/// Number of exceptions we've had. Resets on game exit.
/// </summary>
internal static int ExceptionCount { get; set; }
/// <summary>
/// True if the game is running in standalone mode
/// </summary>
public static bool IsStandalone { get; internal set; }
/// <summary>
/// The language code for the current language
/// </summary>
[ConVar( "language", ConVarFlags.Saved | ConVarFlags.Protected, Name = "Language" )]
public static string LanguageCode { get; internal set; } = "en";
/// <summary>
/// True if the game is running in VR mode
/// </summary>
public static bool IsVR => VRSystem.IsActive; // garry: I think this is right? But feels like this should be set at startup and never change?
internal static void Initialize( bool dedicated, bool headless, bool toolsMode, bool testMode, bool isRetail )
{
if ( IsInitialized )
throw new InvalidOperationException( "Already Initialized" );
IsInitialized = true;
IsDedicatedServer = dedicated;
IsRetail = isRetail;
IsUnitTest = testMode;
IsHeadless = headless;
IsEditor = toolsMode;
IsJoinLocal = CommandLine.HasSwitch( "-joinlocal" );
IsBenchmark = Environment.GetEnvironmentVariable( "SBOX_MODE" ) == "BENCHMARK";
LocalInstanceId = CommandLine.GetSwitchInt( "+instanceid", 1 );
}
internal static void Shutdown()
{
IsInitialized = false;
}
internal static void TryLoadVersionInfo( string gameFolder )
{
Version = "0000000";
VersionDate = DateTime.Now;
var versionPath = System.IO.Path.Combine( gameFolder, ".version" );
if ( System.IO.File.Exists( versionPath ) )
{
var text = System.IO.File.ReadAllText( versionPath );
var split = text.Split( "\n" );
Version = split[0].Trim();
VersionDate = DateTime.ParseExact( split[4], "dd/MM/yyyy HH:mm:ss", null, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal );
}
}
/// <summary>
/// The currently loaded game package. May be null if no game loaded.
/// Controlled by GameMenuDll.
/// </summary>
internal static Package GamePackage { get; set; }
/// <summary>
/// The currently loaded map package
/// </summary>
internal static Package MapPackage { get; set; }
/// <summary>
/// The currently loaded game package's ident - if applicable.
/// </summary>
internal static string GameIdent { get; set; }
#if DEBUG
public static bool IsDebug => true;
#endif
#if !DEBUG
public static bool IsDebug => false;
#endif
/// <summary>
/// Returns true if the microphone is currently listening
/// </summary>
public static bool IsMicrophoneListening => VoiceManager.IsListening;
/// <summary>
/// Returns true if the microphone is currently listening and actually hearing/capturing sounds
/// </summary>
public static bool IsMicrophoneRecording => VoiceManager.IsRecording;
/// <summary>
/// Is the game window in focus?
/// </summary>
public static bool IsFocused => NativeEngine.EngineGlobal.IsWindowFocused();
internal static bool WantsExit { get; set; }
/// <summary>
/// Exits the application if we're running in standalone mode or we are a Dedicated Server.
/// </summary>
internal static void Exit()
{
WantsExit = true;
}
internal static void ClearGame()
{
GameIdent = default;
GamePackage = default;
ExceptionCount = default;
MapPackage = default;
}
public static bool CheatsEnabled
{
get => ConVarSystem.GetValue( "sv_cheats", "false", true ).ToBool();
}
/// <summary>
/// Allows access to the RenderSettings singleton, which contains settings related to rendering in the game.
/// You're only able to access this when in standalone mode. When accessing in the editor, or in sbox it will return null.
/// </summary>
public static RenderSettings RenderSettings
{
get
{
if ( !IsStandalone ) return null;
return RenderSettings.Instance;
}
}
/// <summary>
/// Gets the active scene. This could be in the menu system, or in the game. This is provided
/// for internal engine, and should never be accessible to the user code.
/// </summary>
internal static Scene GetActiveScene()
{
if ( IGameInstance.Current?.Scene is Scene gameScene && gameScene.IsValid() )
{
return gameScene;
}
if ( IMenuDll.Current?.Scene is Scene menuScene && menuScene.IsValid() )
{
return menuScene;
}
return null;
}
/// <summary>
/// Get the current editor if any. Will return null if we're not in the editor, or there is no active editor session.
/// </summary>
public static EditorSystem Editor => IToolsDll.Current?.ActiveEditor;
}