diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs index 4b5e41f..cff8cd3 100644 --- a/Torch.API/ITorchBase.cs +++ b/Torch.API/ITorchBase.cs @@ -16,30 +16,6 @@ namespace Torch.API /// public interface ITorchBase { - /// - /// Fired when the session begins loading. - /// - [Obsolete("Prefer using the TorchSessionManager.SessionStateChanged event")] - event Action SessionLoading; - - /// - /// Fired when the session finishes loading. - /// - [Obsolete("Prefer using the TorchSessionManager.SessionStateChanged event")] - event Action SessionLoaded; - - /// - /// Fires when the session begins unloading. - /// - [Obsolete("Prefer using the TorchSessionManager.SessionStateChanged event")] - event Action SessionUnloading; - - /// - /// Fired when the session finishes unloading. - /// - [Obsolete("Prefer using the TorchSessionManager.SessionStateChanged event")] - event Action SessionUnloaded; - /// /// Gets the currently running session instance, or null if none exists. /// @@ -67,6 +43,16 @@ namespace Torch.API /// The binary version of the current instance. /// Version TorchVersion { get; } + + /// + /// Path of the dedicated instance folder. + /// + string InstancePath { get; } + + /// + /// Name of the dedicated instance. + /// + string InstanceName { get; } /// /// Invoke an action on the game thread. @@ -146,16 +132,6 @@ namespace Torch.API /// ServerState State { get; } - /// - /// Path of the dedicated instance folder. - /// - string InstancePath { get; } - - /// - /// Name of the dedicated instance. - /// - string InstanceName { get; } - /// /// Raised when the server's Init() method has completed. /// diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs index c5faf61..71563d0 100644 --- a/Torch.Server/TorchServer.cs +++ b/Torch.Server/TorchServer.cs @@ -37,15 +37,9 @@ namespace Torch.Server { public class TorchServer : TorchBase, ITorchServer { - private bool _hasRun; - private bool _canRun; - private TimeSpan _elapsedPlayTime; - private bool _isRunning; private float _simRatio; - private ServerState _state; private Stopwatch _uptime; private Timer _watchdog; - private int _players; private MultiplayerManagerDedicated _multiplayerManagerDedicated; internal bool FatalException { get; set; } @@ -67,11 +61,13 @@ namespace Torch.Server var sessionManager = Managers.GetManager(); sessionManager.AddFactory(x => new MultiplayerManagerDedicated(this)); + sessionManager.SessionStateChanged += OnSessionStateChanged; // Needs to be done at some point after MyVRageWindows.Init // where the debug listeners are registered if (!((TorchConfig)Config).EnableAsserts) MyDebug.Listeners.Clear(); + _simUpdateTimer.Elapsed += SimUpdateElapsed; _simUpdateTimer.Start(); } @@ -85,7 +81,7 @@ namespace Torch.Server } } - public bool HasRun { get => _hasRun; set => SetValue(ref _hasRun, value); } + public bool HasRun { get; set; } /// @@ -104,22 +100,19 @@ namespace Torch.Server } /// - public TimeSpan ElapsedPlayTime { get => _elapsedPlayTime; set => SetValue(ref _elapsedPlayTime, value); } + public TimeSpan ElapsedPlayTime { get; set; } /// public Thread GameThread => MySandboxGame.Static?.UpdateThread; /// - public bool IsRunning { get => _isRunning; set => SetValue(ref _isRunning, value); } + public bool IsRunning { get; set; } - public bool CanRun { get => _canRun; set => SetValue(ref _canRun, value); } + public bool CanRun { get; set; } /// public InstanceManager DedicatedInstance { get; } - /// - public string InstanceName { get; } - /// protected override uint SteamAppId => 244850; @@ -127,22 +120,17 @@ namespace Torch.Server protected override string SteamAppName => "SpaceEngineersDedicated"; /// - public ServerState State { get => _state; private set => SetValue(ref _state, value); } + public ServerState State { get; private set; } public event Action Initialized; - /// - public string InstancePath { get; } - - public int OnlinePlayers { get => _players; private set => SetValue(ref _players, value); } + public int OnlinePlayers { get; private set; } /// public override void Init() { Log.Info("Initializing server"); - MySandboxGame.IsDedicated = true; base.Init(); - Managers.GetManager().SessionStateChanged += OnSessionStateChanged; GetManager().LoadInstance(InstancePath); CanRun = true; Initialized?.Invoke(this); @@ -237,21 +225,27 @@ namespace Torch.Server [SuppressPropertyChangedWarnings] private void OnSessionStateChanged(ITorchSession session, TorchSessionState newState) { - if (newState == TorchSessionState.Unloading || newState == TorchSessionState.Unloaded) + switch (newState) { - _watchdog?.Dispose(); - _watchdog = null; - ModCommunication.Unregister(); + case TorchSessionState.Unloading: + _watchdog?.Dispose(); + _watchdog = null; + ModCommunication.Unregister(); + break; + case TorchSessionState.Loaded: + _multiplayerManagerDedicated = CurrentSession.Managers.GetManager(); + _multiplayerManagerDedicated.PlayerJoined += MultiplayerManagerDedicatedOnPlayerJoined; + _multiplayerManagerDedicated.PlayerLeft += MultiplayerManagerDedicatedOnPlayerLeft; + CurrentSession.Managers.GetManager().RegisterCommandModule(typeof(WhitelistCommands)); + ModCommunication.Register(); + break; + case TorchSessionState.Loading: + case TorchSessionState.Unloaded: + break; + default: + throw new ArgumentOutOfRangeException(nameof(newState), newState, null); } - if (newState == TorchSessionState.Loaded) - { - _multiplayerManagerDedicated = CurrentSession.Managers.GetManager(); - _multiplayerManagerDedicated.PlayerJoined += MultiplayerManagerDedicatedOnPlayerJoined; - _multiplayerManagerDedicated.PlayerLeft += MultiplayerManagerDedicatedOnPlayerLeft; - CurrentSession.Managers.GetManager().RegisterCommandModule(typeof(WhitelistCommands)); - ModCommunication.Register(); - } } private void MultiplayerManagerDedicatedOnPlayerLeft(IPlayer player) diff --git a/Torch/Plugins/PluginManager.cs b/Torch/Plugins/PluginManager.cs index 8c2869a..3c2f6e6 100644 --- a/Torch/Plugins/PluginManager.cs +++ b/Torch/Plugins/PluginManager.cs @@ -419,12 +419,15 @@ namespace Torch.Managers AppDomain.CurrentDomain.AssemblyResolve += ResolveDependentAssembly; foreach (Assembly asm in assemblies) { - TorchBase.RegisterAuxAssembly(asm); + TorchLauncher.RegisterAssembly(asm); } } private static bool IsAssemblyCompatible(AssemblyName a, AssemblyName b) { + if (a.Version is null || b.Version is null) + return a.Name == b.Name; + return a.Name == b.Name && a.Version.Major == b.Version.Major && a.Version.Minor == b.Version.Minor; } diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs index e8f14ee..1e844b9 100644 --- a/Torch/TorchBase.cs +++ b/Torch/TorchBase.cs @@ -37,17 +37,16 @@ namespace Torch { static TorchBase() { - MyVRageWindows.Init("SpaceEngineersDedicated", MySandboxGame.Log, null, false); - ReflectedManager.Process(typeof(TorchBase).Assembly); - ReflectedManager.Process(typeof(ITorchBase).Assembly); + TorchLauncher.RegisterAssembly(typeof(ITorchBase).Assembly); + TorchLauncher.RegisterAssembly(typeof(TorchBase).Assembly); + TorchLauncher.RegisterAssembly(Assembly.GetEntryAssembly()); + PatchManager.AddPatchShim(typeof(GameStatePatchShim)); PatchManager.AddPatchShim(typeof(GameAnalyticsPatch)); PatchManager.AddPatchShim(typeof(KeenLogPatch)); PatchManager.AddPatchShim(typeof(XmlRootWriterPatch)); PatchManager.CommitInternal(); - RegisterCoreAssembly(typeof(ITorchBase).Assembly); - RegisterCoreAssembly(typeof(TorchBase).Assembly); - RegisterCoreAssembly(Assembly.GetEntryAssembly()); + //exceptions in English, please Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US"); } @@ -64,6 +63,8 @@ namespace Torch /// public SemanticVersioning.Version TorchVersion { get; } + public string InstancePath { get; protected init;} + public string InstanceName { get; protected init; } /// public Version GameVersion { get; private set; } @@ -78,18 +79,6 @@ namespace Torch /// public ITorchSession CurrentSession => Managers?.GetManager()?.CurrentSession; - /// - public event Action SessionLoading; - - /// - public event Action SessionLoaded; - - /// - public event Action SessionUnloading; - - /// - public event Action SessionUnloaded; - /// /// Common log for the Torch instance. /// @@ -106,7 +95,6 @@ namespace Torch /// Thrown if a TorchBase instance already exists. protected TorchBase(ITorchConfig config) { - RegisterCoreAssembly(GetType().Assembly); #pragma warning disable CS0618 if (Instance != null) throw new InvalidOperationException("A TorchBase instance already exists."); @@ -158,27 +146,6 @@ namespace Torch PatchManager.CommitInternal(); } }; - - sessionManager.SessionStateChanged += (session, state) => - { - switch (state) - { - case TorchSessionState.Loading: - SessionLoading?.Invoke(); - break; - case TorchSessionState.Loaded: - SessionLoaded?.Invoke(); - break; - case TorchSessionState.Unloading: - SessionUnloading?.Invoke(); - break; - case TorchSessionState.Unloaded: - SessionUnloaded?.Invoke(); - break; - default: - throw new ArgumentOutOfRangeException(nameof(state), state, null); - } - }; } [Obsolete("Prefer using Managers.GetManager for global managers")] @@ -193,11 +160,6 @@ namespace Torch return Managers.AddManager(manager); } - public bool IsOnGameThread() - { - return Thread.CurrentThread.ManagedThreadId == MySandboxGame.Static.UpdateThread.ManagedThreadId; - } - #region Game Actions /// @@ -288,8 +250,6 @@ namespace Torch public virtual void Init() { Debug.Assert(!_init, "Torch instance is already initialized."); - SpaceEngineersGame.SetupBasicGameInfo(); - SpaceEngineersGame.SetupPerGameSettings(); ObjectFactoryInitPatch.ForceRegisterAssemblies(); Debug.Assert(MyPerGameSettings.BasicGameInfo.GameVersion != null, "MyPerGameSettings.BasicGameInfo.GameVersion != null"); @@ -297,7 +257,7 @@ namespace Torch try { - Console.Title = $"{Config.InstanceName} - Torch {TorchVersion}, SE {GameVersion}"; + Console.Title = $"{InstanceName} - Torch {TorchVersion}, SE {GameVersion}"; } catch { @@ -311,17 +271,17 @@ namespace Torch #endif Log.Info($"Torch Version: {TorchVersion}"); Log.Info($"Game Version: {GameVersion}"); - Log.Info($"Executing assembly: {Assembly.GetEntryAssembly().FullName}"); + Log.Info($"Executing assembly: {Assembly.GetEntryAssembly()?.FullName}"); Log.Info($"Executing directory: {AppDomain.CurrentDomain.BaseDirectory}"); Managers.GetManager().LoadPlugins(); - Game = new VRageGame(this, TweakGameSettings, SteamAppName, SteamAppId, Config.InstancePath, RunArgs); + Game = new VRageGame(this, TweakGameSettings, SteamAppName, SteamAppId, InstancePath, RunArgs); if (!Game.WaitFor(VRageGame.GameState.Stopped)) Log.Warn("Failed to wait for game to be initialized"); Managers.Attach(); _init = true; - if (GameState >= TorchGameState.Created && GameState < TorchGameState.Unloading) + if (GameState is >= TorchGameState.Created and < TorchGameState.Unloading) // safe to commit here; all important static ctors have run PatchManager.CommitInternal(); } @@ -435,41 +395,5 @@ namespace Torch /// public event TorchGameStateChangedDel GameStateChanged; - - private static readonly HashSet _registeredCoreAssemblies = new HashSet(); - - /// - /// Registers a core (Torch) assembly with the system, including its - /// shims, shims, and components. - /// - /// Assembly to register - internal static void RegisterCoreAssembly(Assembly asm) - { - lock (_registeredCoreAssemblies) - if (_registeredCoreAssemblies.Add(asm)) - { - ReflectedManager.Process(asm); - EventManager.AddDispatchShims(asm); - PatchManager.AddPatchShims(asm); - } - } - - private static readonly HashSet _registeredAuxAssemblies = new HashSet(); - private static readonly TimeSpan _gameStateChangeTimeout = TimeSpan.FromMinutes(1); - - /// - /// Registers an auxillary (plugin) assembly with the system, including its - /// related components. - /// - /// Assembly to register - internal static void RegisterAuxAssembly(Assembly asm) - { - lock (_registeredAuxAssemblies) - if (_registeredAuxAssemblies.Add(asm)) - { - ReflectedManager.Process(asm); - PatchManager.AddPatchShims(asm); - } - } } } \ No newline at end of file diff --git a/Torch/Utils/TorchLauncher.cs b/Torch/Utils/TorchLauncher.cs index 7f58b70..e26a22b 100644 --- a/Torch/Utils/TorchLauncher.cs +++ b/Torch/Utils/TorchLauncher.cs @@ -3,12 +3,16 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using Torch.Event; +using Torch.Managers.PatchManager; +using VRage.Collections; namespace Torch.Utils { - public class TorchLauncher + public static class TorchLauncher { - private static readonly Dictionary Assemblies = new Dictionary(); + private static readonly MyConcurrentHashSet RegisteredAssemblies = new(); + private static readonly Dictionary Assemblies = new(); public static void Launch(params string[] binaryPaths) { @@ -29,6 +33,15 @@ namespace Torch.Utils AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve; } + public static void RegisterAssembly(Assembly assembly) + { + if (!RegisteredAssemblies.Add(assembly)) + return; + ReflectedManager.Process(assembly); + EventManager.AddDispatchShims(assembly); + PatchManager.AddPatchShims(assembly); + } + private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args) { var name = args.Name; diff --git a/Torch/VRageGame.cs b/Torch/VRageGame.cs index 017edd5..9d1ca87 100644 --- a/Torch/VRageGame.cs +++ b/Torch/VRageGame.cs @@ -35,11 +35,13 @@ using VRage.Game.ObjectBuilder; using VRage.Game.SessionComponents; using VRage.GameServices; using VRage.Mod.Io; +using VRage.Platform.Windows; using VRage.Plugins; using VRage.Scripting; using VRage.Steam; using VRage.Utils; using VRageRender; +using Game = Sandbox.Engine.Platform.Game; using MyRenderProfiler = VRage.Profiler.MyRenderProfiler; namespace Torch @@ -141,7 +143,9 @@ namespace Torch private void Create() { bool dedicated = true; + Game.IsDedicated = true; Environment.SetEnvironmentVariable("SteamAppId", _appSteamId.ToString()); + MyVRageWindows.Init("SpaceEngineersDedicated", MySandboxGame.Log, null, false); SpaceEngineersGame.SetupBasicGameInfo(); SpaceEngineersGame.SetupPerGameSettings(); MyFinalBuildConstants.APP_VERSION = MyPerGameSettings.BasicGameInfo.GameVersion;