Files
RobustToolbox/Robust.Client/GameController/GameController.Standalone.cs
Vera Aguilera Puerto c06707d519 Adds ServerOptions, improve GameControllerOptions, fix engine integration tests (#1844)
* Adds ServerOptions, improve GameControllerOptions, fix engine integration tests

* Do component auto-registration in engine integration tests by default

* Fix integration tests on content, register components ONLY if not contentstarted or options are null

* Add integration test for engine integration tests working correctly

* Move cvar overrides out of content and into engine.
2021-07-03 15:19:46 +02:00

133 lines
3.9 KiB
C#

using System;
using System.Threading;
using Robust.LoaderApi;
using Robust.Shared;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Robust.Client
{
internal partial class GameController
{
private IGameLoop? _mainLoop;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IDependencyCollection _dependencyCollection = default!;
private static bool _hasStarted;
private Thread? _gameThread;
public static void Main(string[] args)
{
Start(args, new GameControllerOptions());
}
public static void Start(string[] args, GameControllerOptions options, bool contentStart = false, IMainArgs? loaderArgs=null)
{
if (_hasStarted)
{
throw new InvalidOperationException("Cannot start twice!");
}
_hasStarted = true;
if (CommandLineArgs.TryParse(args, out var parsed))
{
ParsedMain(parsed, contentStart, loaderArgs, options);
}
}
private static void ParsedMain(CommandLineArgs args, bool contentStart, IMainArgs? loaderArgs, GameControllerOptions options)
{
IoCManager.InitThread();
var mode = args.Headless ? DisplayMode.Headless : DisplayMode.Clyde;
InitIoC(mode);
var gc = IoCManager.Resolve<GameController>();
gc.SetCommandLineArgs(args);
gc._loaderArgs = loaderArgs;
// When the game is ran with the startup executable being content,
// we have to disable the separate load context.
// Otherwise the content assemblies will be loaded twice which causes *many* fun bugs.
gc.ContentStart = contentStart;
gc.Run(mode, options);
}
public void OverrideMainLoop(IGameLoop gameLoop)
{
_mainLoop = gameLoop;
}
public void Run(DisplayMode mode, GameControllerOptions options, Func<ILogHandler>? logHandlerFactory = null)
{
if (!StartupSystemSplash(options, logHandlerFactory))
{
Logger.Fatal("Failed to start game controller!");
return;
}
if (_clyde.SeparateWindowThread)
{
var stackSize = _configurationManager.GetCVar(CVars.SysGameThreadStackSize);
var priority = (ThreadPriority) _configurationManager.GetCVar(CVars.SysGameThreadPriority);
_gameThread = new Thread(() => GameThreadMain(mode), stackSize)
{
IsBackground = false,
Priority = priority,
Name = "Game thread",
};
_gameThread.Start();
// Will block until game exit
_clyde.EnterWindowLoop();
if (_gameThread.IsAlive)
{
Logger.Debug("Window loop exited; waiting for game thread to exit");
_gameThread.Join();
}
}
else
{
ContinueStartupAndLoop(mode);
}
Cleanup();
Logger.Debug("Goodbye");
IoCManager.Clear();
}
private void GameThreadMain(DisplayMode mode)
{
IoCManager.InitThread(_dependencyCollection);
ContinueStartupAndLoop(mode);
// Game thread exited, make sure window thread unblocks to finish shutdown.
_clyde.TerminateWindowLoop();
}
private void ContinueStartupAndLoop(DisplayMode mode)
{
if (!StartupContinue(mode))
{
Logger.Fatal("Failed to start game controller!");
return;
}
DebugTools.AssertNotNull(_mainLoop);
_mainLoop!.Run();
}
}
}