/// <inheritdoc /> public bool Start(Func <ILogHandler>?logHandlerFactory = null) { // Sets up the configMgr // If a config file path was passed, use it literally. // This ensures it's working-directory relative // (for people passing config file through the terminal or something). // Otherwise use the one next to the executable. if (_commandLineArgs?.ConfigFile != null) { _config.LoadFromFile(_commandLineArgs.ConfigFile); } else { var path = PathHelpers.ExecutableRelativeFile("server_config.toml"); if (File.Exists(path)) { _config.LoadFromFile(path); } else { _config.SetSaveFile(path); } } _config.OverrideConVars(EnvironmentVariables.GetEnvironmentCVars()); if (_commandLineArgs != null) { _config.OverrideConVars(_commandLineArgs.CVars); } //Sets up Logging _config.RegisterCVar("log.enabled", true, CVar.ARCHIVE); _config.RegisterCVar("log.path", "logs", CVar.ARCHIVE); _config.RegisterCVar("log.format", "log_%(date)s-T%(time)s.txt", CVar.ARCHIVE); _config.RegisterCVar("log.level", LogLevel.Info, CVar.ARCHIVE); _logHandlerFactory = logHandlerFactory; var logHandler = logHandlerFactory?.Invoke() ?? null; var logEnabled = _config.GetCVar <bool>("log.enabled"); if (logEnabled && logHandler == null) { var logPath = _config.GetCVar <string>("log.path"); var logFormat = _config.GetCVar <string>("log.format"); var logFilename = logFormat.Replace("%(date)s", DateTime.Now.ToString("yyyy-MM-dd")) .Replace("%(time)s", DateTime.Now.ToString("hh-mm-ss")); var fullPath = Path.Combine(logPath, logFilename); if (!Path.IsPathRooted(fullPath)) { logPath = PathHelpers.ExecutableRelativeFile(fullPath); } logHandler = new FileLogHandler(logPath); } _log.RootSawmill.Level = _config.GetCVar <LogLevel>("log.level"); if (logEnabled && logHandler != null) { _logHandler = logHandler; _log.RootSawmill.AddHandler(_logHandler !); } // Has to be done early because this guy's in charge of the main thread Synchronization Context. _taskManager.Initialize(); LoadSettings(); // Load metrics really early so that we can profile startup times in the future maybe. _metricsManager.Initialize(); var netMan = IoCManager.Resolve <IServerNetManager>(); try { netMan.Initialize(true); netMan.StartServer(); netMan.RegisterNetMessage <MsgSetTickRate>(MsgSetTickRate.NAME); } catch (Exception e) { var port = netMan.Port; Logger.Fatal( "Unable to setup networking manager. Check port {0} is not already in use and that all binding addresses are correct!\n{1}", port, e); return(true); } var dataDir = _commandLineArgs?.DataDir ?? PathHelpers.ExecutableRelativeFile("data"); // Set up the VFS _resources.Initialize(dataDir); #if FULL_RELEASE _resources.MountContentDirectory(@"./Resources/"); #else // Load from the resources dir in the repo root instead. // It's a debug build so this is fine. var contentRootDir = ProgramShared.FindContentRootDir(); _resources.MountContentDirectory($@"{contentRootDir}RobustToolbox/Resources/"); _resources.MountContentDirectory($@"{contentRootDir}bin/Content.Server/", new ResourcePath("/Assemblies/")); _resources.MountContentDirectory($@"{contentRootDir}Resources/"); #endif _modLoader.SetUseLoadContext(!DisableLoadContext); //identical code in game controller for client if (!_modLoader.TryLoadAssembly <GameShared>(_resources, $"Content.Shared")) { Logger.FatalS("eng", "Could not load any Shared DLL."); return(true); } if (!_modLoader.TryLoadAssembly <GameServer>(_resources, $"Content.Server")) { Logger.FatalS("eng", "Could not load any Server DLL."); return(true); } _modLoader.BroadcastRunLevel(ModRunLevel.PreInit); // HAS to happen after content gets loaded. // Else the content types won't be included. // TODO: solve this properly. _serializer.Initialize(); //IoCManager.Resolve<IMapLoader>().LoadedMapData += // IoCManager.Resolve<IRobustMappedStringSerializer>().AddStrings; IoCManager.Resolve <IPrototypeManager>().LoadedData += IoCManager.Resolve <IRobustMappedStringSerializer>().AddStrings; // Initialize Tier 2 services IoCManager.Resolve <IGameTiming>().InSimulation = true; _stateManager.Initialize(); IoCManager.Resolve <IPlayerManager>().Initialize(MaxPlayers); _mapManager.Initialize(); _mapManager.Startup(); IoCManager.Resolve <IPlacementManager>().Initialize(); IoCManager.Resolve <IViewVariablesHost>().Initialize(); IoCManager.Resolve <IDebugDrawingManager>().Initialize(); // Call Init in game assemblies. _modLoader.BroadcastRunLevel(ModRunLevel.Init); _entities.Initialize(); // because of 'reasons' this has to be called after the last assembly is loaded // otherwise the prototypes will be cleared var prototypeManager = IoCManager.Resolve <IPrototypeManager>(); prototypeManager.LoadDirectory(new ResourcePath(@"/Prototypes")); prototypeManager.Resync(); IoCManager.Resolve <IConsoleShell>().Initialize(); IoCManager.Resolve <IConGroupController>().Initialize(); _entities.Startup(); _scriptHost.Initialize(); _modLoader.BroadcastRunLevel(ModRunLevel.PostInit); IoCManager.Resolve <IStatusHost>().Start(); AppDomain.CurrentDomain.ProcessExit += ProcessExiting; _watchdogApi.Initialize(); return(false); }