diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs
index ba766c5..edf21bb 100644
--- a/Torch.API/ITorchBase.cs
+++ b/Torch.API/ITorchBase.cs
@@ -101,10 +101,15 @@ namespace Torch.API
Task Save(long callerId);
///
- /// Initialize the Torch instance.
+ /// Initialize the Torch instance. Before this is invalid.
///
void Init();
+ ///
+ /// Disposes the Torch instance. After this is invalid.
+ ///
+ void Dispose();
+
///
/// The current state of the game this instance of torch is controlling.
///
diff --git a/Torch.Client/Torch.Client.csproj b/Torch.Client/Torch.Client.csproj
index 9ed8a34..40f2506 100644
--- a/Torch.Client/Torch.Client.csproj
+++ b/Torch.Client/Torch.Client.csproj
@@ -127,7 +127,6 @@
-
@@ -140,6 +139,9 @@
Settings.settings
True
+
+
+
ResXFileCodeGenerator
Resources.Designer.cs
diff --git a/Torch.Client/TorchClient.cs b/Torch.Client/TorchClient.cs
index 839c40a..22d2d15 100644
--- a/Torch.Client/TorchClient.cs
+++ b/Torch.Client/TorchClient.cs
@@ -14,6 +14,7 @@ using Torch.API;
using Torch.API.Managers;
using Torch.API.Session;
using Torch.Client.Manager;
+using Torch.Client.UI;
using Torch.Session;
using VRage;
using VRage.FileSystem;
@@ -27,7 +28,9 @@ namespace Torch.Client
{
private MyCommonProgramStartup _startup;
private IMyRender _renderer;
- private const uint APP_ID = 244850;
+
+ protected override uint SteamAppId => 244850;
+ protected override string SteamAppName => "Space Engineers";
public TorchClient()
{
@@ -46,10 +49,9 @@ namespace Torch.Client
Directory.SetCurrentDirectory(Program.SpaceEngineersInstallAlias);
MyFileSystem.ExePath = Path.Combine(Program.SpaceEngineersInstallAlias, Program.SpaceEngineersBinaries);
Log.Info("Initializing Torch Client");
- base.Init();
-
- SpaceEngineersGame.SetupBasicGameInfo();
_startup = new MyCommonProgramStartup(RunArgs);
+ SpaceEngineersGame.SetupBasicGameInfo();
+ SpaceEngineersGame.SetupPerGameSettings();
if (_startup.PerformReporting())
throw new InvalidOperationException("Torch client won't launch when started in error reporting mode");
@@ -58,27 +60,16 @@ namespace Torch.Client
throw new InvalidOperationException("Only one instance of Space Engineers can be running at a time.");
var appDataPath = _startup.GetAppDataPath();
- MyInitializer.InvokeBeforeRun(APP_ID, MyPerGameSettings.BasicGameInfo.ApplicationName, appDataPath);
- MyInitializer.InitCheckSum();
- _startup.InitSplashScreen();
- if (!_startup.Check64Bit())
- throw new InvalidOperationException("Torch requires a 64bit operating system");
+ Config.InstancePath = appDataPath;
+ base.Init();
+ OverrideMenus();
+ SetRenderWindowTitle($"Space Engineers v{GameVersion} with Torch v{TorchVersion}");
+ }
- _startup.DetectSharpDxLeaksBeforeRun();
- var steamService = new SteamService(Game.IsDedicated, APP_ID);
- MyServiceManager.Instance.AddService(steamService);
- _renderer = null;
- SpaceEngineersGame.SetupPerGameSettings();
- // I'm sorry, but it's what Keen does in SpaceEngineers.MyProgram
-#pragma warning disable 612
- SpaceEngineersGame.SetupRender();
-#pragma warning restore 612
- InitializeRender();
- if (!_startup.CheckSteamRunning())
- throw new InvalidOperationException("Space Engineers requires steam to be running");
-
- if (!Game.IsDedicated)
- MyFileSystem.InitUserSpecific(MyGameService.UserId.ToString());
+ public override void Dispose()
+ {
+ base.Dispose();
+ _startup.DetectSharpDxLeaksAfterRun();
}
private void OverrideMenus()
@@ -95,18 +86,6 @@ namespace Torch.Client
MyPerGameSettings.GUI.MainMenu = typeof(TorchMainMenuScreen);
}
-
- public override void Start()
- {
- using (var spaceEngineersGame = new SpaceEngineersGame(RunArgs))
- {
- Log.Info("Starting client");
- OverrideMenus();
- spaceEngineersGame.OnGameLoaded += SpaceEngineersGame_OnGameLoaded;
- spaceEngineersGame.OnGameExit += Dispose;
- spaceEngineersGame.Run(false, _startup.DisposeSplashScreen);
- }
- }
private void SetRenderWindowTitle(string title)
{
@@ -125,58 +104,9 @@ namespace Torch.Client
});
}
- private void SpaceEngineersGame_OnGameLoaded(object sender, EventArgs e)
+ public override void Restart()
{
- SetRenderWindowTitle($"Space Engineers v{GameVersion} with Torch v{TorchVersion}");
- }
-
- public override void Dispose()
- {
- MyGameService.ShutDown();
- _startup.DetectSharpDxLeaksAfterRun();
- MyInitializer.InvokeAfterRun();
- }
-
- public override void Stop()
- {
- MySandboxGame.ExitThreadSafe();
- }
-
- private void InitializeRender()
- {
- try
- {
- if (Game.IsDedicated)
- {
- _renderer = new MyNullRender();
- }
- else
- {
- var graphicsRenderer = MySandboxGame.Config.GraphicsRenderer;
- if (graphicsRenderer == MySandboxGame.DirectX11RendererKey)
- {
- _renderer = new MyDX11Render();
- if (!_renderer.IsSupported)
- {
- MySandboxGame.Log.WriteLine("DirectX 11 renderer not supported. No renderer to revert back to.");
- _renderer = null;
- }
- }
- if (_renderer == null)
- throw new MyRenderException("The current version of the game requires a Dx11 card. \\n For more information please see : http://blog.marekrosa.org/2016/02/space-engineers-news-full-source-code_26.html", MyRenderExceptionEnum.GpuNotSupported);
-
- MySandboxGame.Config.GraphicsRenderer = graphicsRenderer;
- }
-
- MyRenderProxy.Initialize(_renderer);
- MyRenderProxy.GetRenderProfiler().SetAutocommit(false);
- MyRenderProxy.GetRenderProfiler().InitMemoryHack("MainEntryPoint");
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message, "Render Initialization Failed");
- Environment.Exit(-1);
- }
+ throw new NotImplementedException();
}
}
}
diff --git a/Torch.Client/TorchMainMenuScreen.cs b/Torch.Client/TorchMainMenuScreen.cs
deleted file mode 100644
index 0bd9e5c..0000000
--- a/Torch.Client/TorchMainMenuScreen.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma warning disable 618
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Sandbox.Game.Gui;
-using Sandbox.Graphics;
-using Sandbox.Graphics.GUI;
-using Sandbox.Gui;
-using SpaceEngineers.Game.GUI;
-using VRage.Game;
-using VRage.Utils;
-using VRageMath;
-
-namespace Torch.Client
-{
- public class TorchMainMenuScreen : MyGuiScreenMainMenu
- {
- public TorchMainMenuScreen()
- : this(false)
- {
- }
-
- public TorchMainMenuScreen(bool pauseGame)
- : base(pauseGame)
- {
- }
- ///
- public override void RecreateControls(bool constructor)
- {
- base.RecreateControls(constructor);
-
- var buttonSize = MyGuiControlButton.GetVisualStyle(MyGuiControlButtonStyleEnum.Default).NormalTexture.MinSizeGui;
- Vector2 leftButtonPositionOrigin = MyGuiManager.ComputeFullscreenGuiCoordinate(MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_BOTTOM) + new Vector2(buttonSize.X / 2f, 0f);
- var btn = MakeButton(leftButtonPositionOrigin - 9 * MyGuiConstants.MENU_BUTTONS_POSITION_DELTA, MyStringId.GetOrCompute("Torch"), TorchButtonClicked);
- Controls.Add(btn);
- }
-
- private void TorchButtonClicked(MyGuiControlButton obj)
- {
- MyGuiSandbox.AddScreen(new TorchSettingsScreen());
- }
- }
-}
diff --git a/Torch.Client/UI/TorchMainMenuScreen.cs b/Torch.Client/UI/TorchMainMenuScreen.cs
new file mode 100644
index 0000000..2ccbfe6
--- /dev/null
+++ b/Torch.Client/UI/TorchMainMenuScreen.cs
@@ -0,0 +1,56 @@
+#pragma warning disable 618
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Sandbox.Engine.Networking;
+using Sandbox.Engine.Utils;
+using Sandbox.Game;
+using Sandbox.Game.Gui;
+using Sandbox.Graphics;
+using Sandbox.Graphics.GUI;
+using Sandbox.Gui;
+using SpaceEngineers.Game.GUI;
+using Torch.Utils;
+using VRage.Game;
+using VRage.Utils;
+using VRageMath;
+
+namespace Torch.Client.UI
+{
+ public class TorchMainMenuScreen : MyGuiScreenMainMenu
+ {
+#pragma warning disable 169
+ [ReflectedGetter(Name = "m_elementGroup")]
+ private static Func _elementsGroup;
+#pragma warning restore 169
+
+ public TorchMainMenuScreen() : this(false)
+ {
+ }
+
+ public TorchMainMenuScreen(bool pauseGame)
+ : base(pauseGame)
+ {
+ }
+ ///
+ public override void RecreateControls(bool constructor)
+ {
+ base.RecreateControls(constructor);
+
+ Vector2 minSizeGui = MyGuiControlButton.GetVisualStyle(MyGuiControlButtonStyleEnum.Default).NormalTexture.MinSizeGui;
+ Vector2 value = MyGuiManager.ComputeFullscreenGuiCoordinate(MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_BOTTOM, 54, 54) + new Vector2(minSizeGui.X / 2f, 0f) + new Vector2(15f, 0f) / MyGuiConstants.GUI_OPTIMAL_SIZE;
+
+ MyGuiControlButton myGuiControlButton = MakeButton(value - 9 * MyGuiConstants.MENU_BUTTONS_POSITION_DELTA,
+ MyStringId.GetOrCompute("Torch"), TorchButtonClicked, MyCommonTexts.ToolTipExitToWindows);
+ Controls.Add(myGuiControlButton);
+ _elementsGroup.Invoke(this).Add(myGuiControlButton);
+ }
+
+ private void TorchButtonClicked(MyGuiControlButton obj)
+ {
+ MyGuiSandbox.AddScreen(MyGuiSandbox.CreateScreen());
+ }
+ }
+}
diff --git a/Torch.Client/UI/TorchNavScreen.cs b/Torch.Client/UI/TorchNavScreen.cs
new file mode 100644
index 0000000..9b657a2
--- /dev/null
+++ b/Torch.Client/UI/TorchNavScreen.cs
@@ -0,0 +1,49 @@
+using Sandbox;
+using Sandbox.Game.Gui;
+using Sandbox.Graphics.GUI;
+using VRage;
+using VRage.Game;
+using VRage.Utils;
+using VRageMath;
+
+namespace Torch.Client.UI
+{
+ public class TorchNavScreen : MyGuiScreenBase
+ {
+ private MyGuiControlElementGroup _elementGroup;
+
+ public TorchNavScreen() : base(new Vector2(0.5f, 0.5f), MyGuiConstants.SCREEN_BACKGROUND_COLOR, new Vector2(0.35875f, 0.558333337f))
+ {
+ EnabledBackgroundFade = true;
+ RecreateControls(true);
+ }
+
+ public override void RecreateControls(bool constructor)
+ {
+ base.RecreateControls(constructor);
+ _elementGroup = new MyGuiControlElementGroup();
+ _elementGroup.HighlightChanged += ElementGroupHighlightChanged;
+ AddCaption(MyCommonTexts.ScreenCaptionOptions, null, null);
+ var value = new Vector2(0f, -m_size.Value.Y / 2f + 0.146f);
+ var num = 0;
+ var myGuiControlButton = new MyGuiControlButton(value + num++ * MyGuiConstants.MENU_BUTTONS_POSITION_DELTA, MyGuiControlButtonStyleEnum.Default, null, null, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, null, MyTexts.Get(MyCommonTexts.ScreenOptionsButtonGame), 0.8f, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_CENTER, MyGuiControlHighlightType.WHEN_ACTIVE, delegate(MyGuiControlButton sender)
+ {
+ MyGuiSandbox.AddScreen(MyGuiSandbox.CreateScreen());
+ }, GuiSounds.MouseClick, 1f, null);
+ Controls.Add(myGuiControlButton);
+ _elementGroup.Add(myGuiControlButton);
+ CloseButtonEnabled = true;
+ }
+
+ private void ElementGroupHighlightChanged(MyGuiControlElementGroup obj)
+ {
+ foreach (MyGuiControlBase current in _elementGroup)
+ if (current.HasFocus && obj.SelectedElement != current)
+ FocusedControl = obj.SelectedElement;
+ }
+
+ public override string GetFriendlyName() => "Torch";
+
+ public void OnBackClick(MyGuiControlButton sender) => CloseScreen();
+ }
+}
diff --git a/Torch.Client/UI/TorchSettingsScreen.cs b/Torch.Client/UI/TorchSettingsScreen.cs
new file mode 100644
index 0000000..07f4726
--- /dev/null
+++ b/Torch.Client/UI/TorchSettingsScreen.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Sandbox.Graphics.GUI;
+using VRageMath;
+
+namespace Torch.Client.UI
+{
+ public class TorchSettingsScreen : MyGuiScreenBase
+ {
+ public TorchSettingsScreen() : base(new Vector2(0.5f, 0.5f), MyGuiConstants.SCREEN_BACKGROUND_COLOR,
+ new Vector2(0.35875f, 0.558333337f))
+ {
+ EnabledBackgroundFade = true;
+ RecreateControls(true);
+ }
+
+ ///
+ public override string GetFriendlyName() => "Torch Settings";
+
+ public void OnBackClick(MyGuiControlButton sender) => CloseScreen();
+ }
+}
diff --git a/Torch.Server/Managers/InstanceManager.cs b/Torch.Server/Managers/InstanceManager.cs
index f11a446..ab26246 100644
--- a/Torch.Server/Managers/InstanceManager.cs
+++ b/Torch.Server/Managers/InstanceManager.cs
@@ -32,23 +32,13 @@ namespace Torch.Server.Managers
{
}
-
- ///
- public override void Attach()
- {
- MyFileSystem.ExePath = Path.Combine(_filesystemManager.TorchDirectory, "DedicatedServer64");
- MyFileSystem.Init("Content", Torch.Config.InstancePath);
- //Initializes saves path. Why this isn't in Init() we may never know.
- MyFileSystem.InitUserSpecific(null);
- }
-
+
public void LoadInstance(string path, bool validate = true)
{
if (validate)
ValidateInstance(path);
MyFileSystem.Reset();
- MyFileSystem.ExePath = Path.Combine(_filesystemManager.TorchDirectory, "DedicatedServer64");
MyFileSystem.Init("Content", path);
//Initializes saves path. Why this isn't in Init() we may never know.
MyFileSystem.InitUserSpecific(null);
diff --git a/Torch.Server/Managers/MultiplayerManagerDedicatedEventShim.cs b/Torch.Server/Managers/MultiplayerManagerDedicatedEventShim.cs
index d0d7433..c9a302d 100644
--- a/Torch.Server/Managers/MultiplayerManagerDedicatedEventShim.cs
+++ b/Torch.Server/Managers/MultiplayerManagerDedicatedEventShim.cs
@@ -24,20 +24,9 @@ namespace Torch.Server.Managers
}
}
-// class AdminsCanJoinExample : IEventHandler
-// {
-// [EventHandler(SkipCancelled = false)]
-// public void Handle(ref ValidateAuthTicketEvent info)
-// {
-// if (MySandboxGame.ConfigDedicated.Administrators.Contains(info.SteamID.ToString())
-// || (info.ServerGroup == MySandboxGame.ConfigDedicated.GroupID && info.Officer))
-// info.Verdict = JoinResult.OK;
-// }
-// }
-
///
- /// Event that occurs when a player tries to connect to the server.
- /// Use these values to choose a ,
+ /// Event that occurs when a player tries to connect to a dedicated server.
+ /// Use these values to choose a ,
/// or leave it unset to allow the default logic to handle the request.
///
public struct ValidateAuthTicketEvent : IEvent
@@ -73,7 +62,7 @@ namespace Torch.Server.Managers
public readonly bool Officer;
///
- /// A future verdict on this authorization request. If null, let the default logic choose.
+ /// A future verdict on this authorization request. If null, let the default logic choose. If not async use
///
public Task FutureVerdict;
diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs
index 81bf533..d97d6fe 100644
--- a/Torch.Server/TorchServer.cs
+++ b/Torch.Server/TorchServer.cs
@@ -44,19 +44,58 @@ namespace Torch.Server
{
//public MyConfigDedicated DedicatedConfig { get; set; }
///
- public float SimulationRatio { get => _simRatio; set { _simRatio = value; OnPropertyChanged(); } }
+ public float SimulationRatio
+ {
+ get => _simRatio;
+ set
+ {
+ _simRatio = value;
+ OnPropertyChanged();
+ }
+ }
+
///
- public TimeSpan ElapsedPlayTime { get => _elapsedPlayTime; set { _elapsedPlayTime = value; OnPropertyChanged(); } }
+ public TimeSpan ElapsedPlayTime
+ {
+ get => _elapsedPlayTime;
+ set
+ {
+ _elapsedPlayTime = value;
+ OnPropertyChanged();
+ }
+ }
+
///
public Thread GameThread { get; private set; }
+
///
- public ServerState State { get => _state; private set { _state = value; OnPropertyChanged(); } }
+ public ServerState State
+ {
+ get => _state;
+ private set
+ {
+ _state = value;
+ OnPropertyChanged();
+ }
+ }
+
///
- public bool IsRunning { get => _isRunning; set { _isRunning = value; OnPropertyChanged(); } }
+ public bool IsRunning
+ {
+ get => _isRunning;
+ set
+ {
+ _isRunning = value;
+ OnPropertyChanged();
+ }
+ }
+
///
public InstanceManager DedicatedInstance { get; }
+
///
public string InstanceName => Config?.InstanceName;
+
///
public string InstancePath => Config?.InstancePath;
@@ -80,30 +119,20 @@ namespace Torch.Server
sessionManager.AddFactory((x) => new MultiplayerManagerDedicated(this));
}
+ ///
+ protected override uint SteamAppId => 244850;
+
+ ///
+ protected override string SteamAppName => "SpaceEngineersDedicated";
+
///
public override void Init()
{
Log.Info($"Init server '{Config.InstanceName}' at '{Config.InstancePath}'");
+ Sandbox.Engine.Platform.Game.IsDedicated = true;
+
base.Init();
- MyPerGameSettings.SendLogToKeen = false;
- MyPerServerSettings.GameName = MyPerGameSettings.GameName;
- MyPerServerSettings.GameNameSafe = MyPerGameSettings.GameNameSafe;
- MyPerServerSettings.GameDSName = MyPerServerSettings.GameNameSafe + "Dedicated";
- MyPerServerSettings.GameDSDescription = "Your place for space engineering, destruction and exploring.";
- MySessionComponentExtDebug.ForceDisable = true;
- MyPerServerSettings.AppId = 244850;
- MyFinalBuildConstants.APP_VERSION = MyPerGameSettings.BasicGameInfo.GameVersion;
- InvokeBeforeRun();
-
- //MyObjectBuilderSerializer.RegisterFromAssembly(typeof(MyObjectBuilder_CheckpointSerializer).Assembly);
- MyPlugins.RegisterGameAssemblyFile(MyPerGameSettings.GameModAssembly);
- MyPlugins.RegisterGameObjectBuildersAssemblyFile(MyPerGameSettings.GameModObjBuildersAssembly);
- MyPlugins.RegisterSandboxAssemblyFile(MyPerGameSettings.SandboxAssembly);
- MyPlugins.RegisterSandboxGameAssemblyFile(MyPerGameSettings.SandboxGameAssembly);
- MyPlugins.Load();
- MyGlobalTypeMetadata.Static.Init();
-
Managers.GetManager().SessionStateChanged += OnSessionStateChanged;
GetManager().LoadInstance(Config.InstancePath);
}
@@ -117,81 +146,64 @@ namespace Torch.Server
}
}
- private void InvokeBeforeRun()
- {
- MySandboxGame.Log.Init("SpaceEngineers-Dedicated.log", MyFinalBuildConstants.APP_VERSION_STRING);
- MySandboxGame.Log.WriteLine("Steam build: Always true");
- MySandboxGame.Log.WriteLine("Environment.ProcessorCount: " + MyEnvironment.ProcessorCount);
- //MySandboxGame.Log.WriteLine("Environment.OSVersion: " + GetOsName());
- MySandboxGame.Log.WriteLine("Environment.CommandLine: " + Environment.CommandLine);
- MySandboxGame.Log.WriteLine("Environment.Is64BitProcess: " + MyEnvironment.Is64BitProcess);
- MySandboxGame.Log.WriteLine("Environment.Is64BitOperatingSystem: " + Environment.Is64BitOperatingSystem);
- //MySandboxGame.Log.WriteLine("Environment.Version: " + GetNETFromRegistry());
- MySandboxGame.Log.WriteLine("Environment.CurrentDirectory: " + Environment.CurrentDirectory);
- MySandboxGame.Log.WriteLine("MainAssembly.ProcessorArchitecture: " + Assembly.GetExecutingAssembly().GetArchitecture());
- MySandboxGame.Log.WriteLine("ExecutingAssembly.ProcessorArchitecture: " + MyFileSystem.MainAssembly.GetArchitecture());
- MySandboxGame.Log.WriteLine("IntPtr.Size: " + IntPtr.Size);
- MySandboxGame.Log.WriteLine("Default Culture: " + CultureInfo.CurrentCulture.Name);
- MySandboxGame.Log.WriteLine("Default UI Culture: " + CultureInfo.CurrentUICulture.Name);
- MySandboxGame.Log.WriteLine("IsAdmin: " + new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator));
-
- MyLog.Default = MySandboxGame.Log;
-
- Thread.CurrentThread.Name = "Main thread";
-
- //Because we want exceptions from users to be in english
- Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
- Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
-
- MySandboxGame.Config = new MyConfig("SpaceEngineers-Dedicated.cfg");
- MySandboxGame.Config.Load();
- }
-
- [ReflectedStaticMethod(Type = typeof(DedicatedServer), Name = "RunInternal")]
- private static Action _dsRunInternal;
-
- ///
public override void Start()
{
if (State != ServerState.Stopped)
return;
+ State = ServerState.Starting;
+ IsRunning = true;
+ Log.Info("Starting server.");
+ MySandboxGame.ConfigDedicated = DedicatedInstance.DedicatedConfig.Model;
DedicatedInstance.SaveConfig();
_uptime = Stopwatch.StartNew();
- IsRunning = true;
- GameThread = Thread.CurrentThread;
- State = ServerState.Starting;
- Log.Info("Starting server.");
-
- MySandboxGame.IsDedicated = true;
- MySandboxGame.ConfigDedicated = DedicatedInstance.DedicatedConfig.Model;
- Environment.SetEnvironmentVariable("SteamAppId", MyPerServerSettings.AppId.ToString());
-
- VRage.Service.ExitListenerSTA.OnExit += delegate { MySandboxGame.Static?.Exit(); };
-
base.Start();
- // Stops RunInternal from calling MyFileSystem.InitUserSpecific(null), we call it in InstanceManager.
- MySandboxGame.IsReloading = true;
- try
- {
- _dsRunInternal.Invoke();
- }
- catch (TargetInvocationException e)
- {
- // Makes log formatting a little nicer.
- throw e.InnerException ?? e;
- }
+ }
+
+ ///
+ public override void Stop()
+ {
+ if (State == ServerState.Stopped)
+ Log.Error("Server is already stopped");
+ Log.Info("Stopping server.");
+ base.Stop();
+ Log.Info("Server stopped.");
+ LogManager.Flush();
+ _stopHandle.Set();
- MySandboxGame.Log.Close();
State = ServerState.Stopped;
+ IsRunning = false;
+ }
+
+ ///
+ /// Restart the program. DOES NOT SAVE!
+ ///
+ public override void Restart()
+ {
+ var exe = Assembly.GetExecutingAssembly().Location;
+ ((TorchConfig) Config).WaitForPID = Process.GetCurrentProcess().Id.ToString();
+ Config.Autostart = true;
+ Process.Start(exe, Config.ToString());
+ Save(0).Wait();
+ Stop();
+ LogManager.Flush();
+ Process.GetCurrentProcess().Kill();
}
///
public override void Init(object gameInstance)
{
base.Init(gameInstance);
- State = ServerState.Running;
- SteamServerAPI.Instance.GameServer.SetKeyValue("SM", "Torch");
+ var game = gameInstance as MySandboxGame;
+ if (game != null && MySession.Static != null)
+ {
+ State = ServerState.Running;
+// SteamServerAPI.Instance.GameServer.SetKeyValue("SM", "Torch");
+ }
+ else
+ {
+ State = ServerState.Stopped;
+ }
}
///
@@ -205,18 +217,22 @@ namespace Torch.Server
if (_watchdog == null && Config.TickTimeout > 0)
{
Log.Info("Starting server watchdog.");
- _watchdog = new Timer(CheckServerResponding, this, TimeSpan.Zero, TimeSpan.FromSeconds(Config.TickTimeout));
+ _watchdog = new Timer(CheckServerResponding, this, TimeSpan.Zero,
+ TimeSpan.FromSeconds(Config.TickTimeout));
}
}
+ #region Freeze Detection
+
private static void CheckServerResponding(object state)
{
var mre = new ManualResetEvent(false);
- ((TorchServer)state).Invoke(() => mre.Set());
+ ((TorchServer) state).Invoke(() => mre.Set());
if (!mre.WaitOne(TimeSpan.FromSeconds(Instance.Config.TickTimeout)))
{
#if DEBUG
- Log.Error($"Server watchdog detected that the server was frozen for at least {((TorchServer)state).Config.TickTimeout} seconds.");
+ Log.Error(
+ $"Server watchdog detected that the server was frozen for at least {((TorchServer) state).Config.TickTimeout} seconds.");
Log.Error(DumpFrozenThread(MySandboxGame.Static.UpdateThread));
#else
Log.Error(DumpFrozenThread(MySandboxGame.Static.UpdateThread));
@@ -278,47 +294,7 @@ namespace Torch.Server
return stack;
}
- ///
- public override void Stop()
- {
- if (State == ServerState.Stopped)
- Log.Error("Server is already stopped");
-
- if (Thread.CurrentThread != MySandboxGame.Static.UpdateThread)
- {
- Log.Debug("Invoking server stop on game thread.");
- Invoke(Stop);
- return;
- }
-
- Log.Info("Stopping server.");
-
- //Unload all the static junk.
- //TODO: Finish unloading all server data so it's in a completely clean state.
- MySandboxGame.Static.Exit();
-
- Log.Info("Server stopped.");
- LogManager.Flush();
- _stopHandle.Set();
- State = ServerState.Stopped;
- IsRunning = false;
- Process.GetCurrentProcess().Kill();
- }
-
- ///
- /// Restart the program. DOES NOT SAVE!
- ///
- public override void Restart()
- {
- var exe = Assembly.GetExecutingAssembly().Location;
- ((TorchConfig)Config).WaitForPID = Process.GetCurrentProcess().Id.ToString();
- Config.Autostart = true;
- Process.Start(exe, Config.ToString());
- Save(0).Wait();
- Stop();
- LogManager.Flush();
- Process.GetCurrentProcess().Kill();
- }
+ #endregion
///
public override Task Save(long callerId)
@@ -357,8 +333,9 @@ namespace Torch.Server
}
if (MySession.Static.Players.TryGetPlayerId(callerId, out MyPlayer.PlayerId result))
{
- Managers.GetManager()?.SendMessageAsOther("Server", response, statusCode == SaveGameStatus.Success ? MyFontEnum.Green : MyFontEnum.Red, result.SteamId);
+ Managers.GetManager()?.SendMessageAsOther("Server", response,
+ statusCode == SaveGameStatus.Success ? MyFontEnum.Green : MyFontEnum.Red, result.SteamId);
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Torch/Managers/PatchManager/MSIL/MsilInstruction.cs b/Torch/Managers/PatchManager/MSIL/MsilInstruction.cs
index 879343d..a85e265 100644
--- a/Torch/Managers/PatchManager/MSIL/MsilInstruction.cs
+++ b/Torch/Managers/PatchManager/MSIL/MsilInstruction.cs
@@ -186,10 +186,10 @@ namespace Torch.Managers.PatchManager.MSIL
-#pragma warning disable 169
+#pragma warning disable 649
[ReflectedMethod(Name = "StackChange")]
private static Func _stackChange;
-#pragma warning restore 169
+#pragma warning restore 649
///
/// Estimates the stack delta for this instruction.
diff --git a/Torch/Session/TorchSessionManager.cs b/Torch/Session/TorchSessionManager.cs
index 426b320..7d8ea14 100644
--- a/Torch/Session/TorchSessionManager.cs
+++ b/Torch/Session/TorchSessionManager.cs
@@ -97,6 +97,7 @@ namespace Torch.Session
CurrentSession.Managers.AddManager(manager);
}
(CurrentSession as TorchSession)?.Attach();
+ _log.Info($"Loaded torch session for {MySession.Static.Name}");
SetState(TorchSessionState.Loaded);
}
catch (Exception e)
@@ -115,7 +116,9 @@ namespace Torch.Session
_log.Warn("Session unloading event occurred when we don't have a session.");
return;
}
+ _log.Info($"Unloading torch session for {_currentSession.KeenSession.Name}");
SetState(TorchSessionState.Unloading);
+ _currentSession.Detach();
}
catch (Exception e)
{
@@ -133,9 +136,8 @@ namespace Torch.Session
_log.Warn("Session unloading event occurred when we don't have a session.");
return;
}
- _log.Info($"Unloading torch session for {_currentSession.KeenSession.Name}");
+ _log.Info($"Unloaded torch session for {_currentSession.KeenSession.Name}");
SetState(TorchSessionState.Unloaded);
- _currentSession.Detach();
_currentSession = null;
}
catch (Exception e)
diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs
index 0d93ac7..a187169 100644
--- a/Torch/TorchBase.cs
+++ b/Torch/TorchBase.cs
@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
+using System.Runtime;
using System.Runtime.CompilerServices;
+using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -12,6 +15,9 @@ using NLog;
using ProtoBuf.Meta;
using Sandbox;
using Sandbox.Engine.Multiplayer;
+using Sandbox.Engine.Networking;
+using Sandbox.Engine.Platform.VideoMode;
+using Sandbox.Engine.Utils;
using Sandbox.Game;
using Sandbox.Game.Multiplayer;
using Sandbox.Game.Screens.Helpers;
@@ -19,6 +25,7 @@ using Sandbox.Game.World;
using Sandbox.Graphics.GUI;
using Sandbox.ModAPI;
using SpaceEngineers.Game;
+using SpaceEngineers.Game.GUI;
using Torch.API;
using Torch.API.Managers;
using Torch.API.ModAPI;
@@ -31,16 +38,22 @@ using Torch.Managers.PatchManager;
using Torch.Patches;
using Torch.Utils;
using Torch.Session;
+using VRage;
using VRage.Collections;
using VRage.FileSystem;
using VRage.Game;
using VRage.Game.Common;
using VRage.Game.Components;
using VRage.Game.ObjectBuilder;
+using VRage.Game.SessionComponents;
+using VRage.GameServices;
+using VRage.Library;
using VRage.ObjectBuilders;
using VRage.Plugins;
using VRage.Scripting;
+using VRage.Steam;
using VRage.Utils;
+using VRageRender;
namespace Torch
{
@@ -67,8 +80,10 @@ namespace Torch
/// Use only if necessary, prefer dependency injection.
///
public static ITorchBase Instance { get; private set; }
+
///
public ITorchConfig Config { get; protected set; }
+
///
public Version TorchVersion { get; }
@@ -79,8 +94,10 @@ namespace Torch
///
public Version GameVersion { get; private set; }
+
///
public string[] RunArgs { get; set; }
+
///
[Obsolete("Use GetManager() or the [Dependency] attribute.")]
public IPluginManager Plugins { get; protected set; }
@@ -90,10 +107,13 @@ namespace Torch
///
public event Action SessionLoading;
+
///
public event Action SessionLoaded;
+
///
public event Action SessionUnloading;
+
///
public event Action SessionUnloaded;
@@ -120,7 +140,9 @@ namespace Torch
Instance = this;
TorchVersion = Assembly.GetExecutingAssembly().GetName().Version;
- TorchVersionVerbose = Assembly.GetEntryAssembly().GetCustomAttribute()?.InformationalVersion ?? TorchVersion.ToString();
+ TorchVersionVerbose = Assembly.GetEntryAssembly()
+ .GetCustomAttribute()
+ ?.InformationalVersion ?? TorchVersion.ToString();
RunArgs = new string[0];
Managers = new DependencyManager();
@@ -140,6 +162,39 @@ namespace Torch
Managers.AddManager(new EventManager(this));
Managers.AddManager(Plugins);
TorchAPI.Instance = this;
+
+ GameStateChanged += (game, state) =>
+ {
+ if (state == TorchGameState.Created)
+ {
+ // If the attached assemblies change (MySandboxGame.ctor => MySandboxGame.ParseArgs => MyPlugins.RegisterFromArgs)
+ // attach assemblies to object factories again.
+ ObjectFactoryInitPatch.ForceRegisterAssemblies();
+ // safe to commit here; all important static ctors have run
+ 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")]
@@ -252,34 +307,30 @@ namespace Torch
#endregion
+ #region Torch Init/Destroy
+
+ protected abstract uint SteamAppId { get; }
+ protected abstract string SteamAppName { get; }
+
///
public virtual void Init()
{
Debug.Assert(!_init, "Torch instance is already initialized.");
SpaceEngineersGame.SetupBasicGameInfo();
SpaceEngineersGame.SetupPerGameSettings();
- // If the attached assemblies change (MySandboxGame.ctor => MySandboxGame.ParseArgs => MyPlugins.RegisterFromArgs)
- // attach assemblies to object factories again.
ObjectFactoryInitPatch.ForceRegisterAssemblies();
- GameStateChanged += (game, state) =>
- {
- if (state == TorchGameState.Created)
- {
- ObjectFactoryInitPatch.ForceRegisterAssemblies();
- // safe to commit here; all important static ctors have run
- PatchManager.CommitInternal();
- }
- };
- Debug.Assert(MyPerGameSettings.BasicGameInfo.GameVersion != null, "MyPerGameSettings.BasicGameInfo.GameVersion != null");
- GameVersion = new Version(new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion.Value).FormattedText.ToString().Replace("_", "."));
+ Debug.Assert(MyPerGameSettings.BasicGameInfo.GameVersion != null,
+ "MyPerGameSettings.BasicGameInfo.GameVersion != null");
+ GameVersion = new Version(new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion.Value).FormattedText
+ .ToString().Replace("_", "."));
try
{
Console.Title = $"{Config.InstanceName} - Torch {TorchVersion}, SE {GameVersion}";
}
catch
{
- // Running as service
+ // Running without a console
}
#if DEBUG
@@ -292,11 +343,7 @@ namespace Torch
Log.Info($"Executing assembly: {Assembly.GetEntryAssembly().FullName}");
Log.Info($"Executing directory: {AppDomain.CurrentDomain.BaseDirectory}");
- MySession.OnLoading += OnSessionLoading;
- MySession.AfterLoading += OnSessionLoaded;
- MySession.OnUnloading += OnSessionUnloading;
- MySession.OnUnloaded += OnSessionUnloaded;
- RegisterVRagePlugin();
+ InitVRageInstance();
Managers.GetManager().LoadPlugins();
Managers.Attach();
_init = true;
@@ -306,109 +353,156 @@ namespace Torch
PatchManager.CommitInternal();
}
- private void OnSessionLoading()
+ ///
+ public virtual void Dispose()
{
- Log.Debug("Session loading");
- try
- {
- SessionLoading?.Invoke();
- }
- catch (Exception e)
- {
- Log.Error(e);
- throw;
- }
+ Managers.Detach();
+ DisposeVRageInstance();
}
- private void OnSessionLoaded()
- {
- Log.Debug("Session loaded");
- try
- {
- SessionLoaded?.Invoke();
- }
- catch (Exception e)
- {
- Log.Error(e);
- throw;
- }
- }
+ #endregion
- private void OnSessionUnloading()
- {
- Log.Debug("Session unloading");
- try
- {
- SessionUnloading?.Invoke();
- }
- catch (Exception e)
- {
- Log.Error(e);
- throw;
- }
- }
+ #region VRage Instance Init/Destroy
- private void OnSessionUnloaded()
+#pragma warning disable 649
+ [ReflectedGetter(Name = "m_plugins", Type = typeof(MyPlugins))]
+ private static readonly Func> _getVRagePluginList;
+#pragma warning restore 649
+
+ protected SpaceEngineersGame GameInstance { get; private set; }
+
+ ///
+ /// Sets up the VRage instance.
+ /// Any flags (ie ) must be set before this is called.
+ ///
+ protected virtual void InitVRageInstance()
{
- Log.Debug("Session unloaded");
- try
+ bool dedicated = Sandbox.Engine.Platform.Game.IsDedicated;
+ Environment.SetEnvironmentVariable("SteamAppId", SteamAppId.ToString());
+ MyServiceManager.Instance.AddService(new MySteamService(dedicated, SteamAppId));
+ if (dedicated && !MyGameService.HasGameServer)
{
- SessionUnloaded?.Invoke();
+ Log.Warn("Steam service is not running! Please reinstall dedicated server.");
+ return;
}
- catch (Exception e)
+
+ SpaceEngineersGame.SetupBasicGameInfo();
+ SpaceEngineersGame.SetupPerGameSettings();
+ MyFinalBuildConstants.APP_VERSION = MyPerGameSettings.BasicGameInfo.GameVersion;
+ MySessionComponentExtDebug.ForceDisable = true;
+ MyPerGameSettings.SendLogToKeen = false;
+ // SpaceEngineersGame.SetupAnalytics();
+
+ MyFileSystem.ExePath = Path.GetDirectoryName(typeof(SpaceEngineersGame).Assembly.Location);
+
+ TweakGameSettings();
+
+ MyInitializer.InvokeBeforeRun(SteamAppId, SteamAppName, Config.InstancePath);
+ // MyInitializer.InitCheckSum();
+
+
+ // Hook into the VRage plugin system for updates.
+ _getVRagePluginList().Add(this);
+
+ if (!MySandboxGame.IsReloading)
+ MyFileSystem.InitUserSpecific(dedicated ? null : MyGameService.UserId.ToString());
+ MySandboxGame.IsReloading = dedicated;
+
+ // render init
{
- Log.Error(e);
- throw;
+ IMyRender renderer = null;
+ if (dedicated)
+ {
+ renderer = new MyNullRender();
+ }
+ else
+ {
+ MyPerformanceSettings preset = MyGuiScreenOptionsGraphics.GetPreset(MyRenderQualityEnum.NORMAL);
+ MyRenderProxy.Settings.User = MyVideoSettingsManager.GetGraphicsSettingsFromConfig(ref preset)
+ .PerformanceSettings.RenderSettings;
+ MyStringId graphicsRenderer = MySandboxGame.Config.GraphicsRenderer;
+ if (graphicsRenderer == MySandboxGame.DirectX11RendererKey)
+ {
+ renderer = new MyDX11Render(new MyRenderSettings?(MyRenderProxy.Settings));
+ if (!renderer.IsSupported)
+ {
+ MySandboxGame.Log.WriteLine(
+ "DirectX 11 renderer not supported. No renderer to revert back to.");
+ renderer = null;
+ }
+ }
+ if (renderer == null)
+ {
+ throw new MyRenderException(
+ "The current version of the game requires a Dx11 card. \\n For more information please see : http://blog.marekrosa.org/2016/02/space-engineers-news-full-source-code_26.html",
+ MyRenderExceptionEnum.GpuNotSupported);
+ }
+ MySandboxGame.Config.GraphicsRenderer = graphicsRenderer;
+ }
+ MyRenderProxy.Initialize(renderer);
+ MyRenderProxy.GetRenderProfiler().SetAutocommit(false);
+ MyRenderProxy.GetRenderProfiler().InitMemoryHack("MainEntryPoint");
}
+
+ GameInstance = new SpaceEngineersGame(RunArgs);
}
///
- /// Hook into the VRage plugin system for updates.
+ /// Called after the basic game information is filled, but before the game is created.
///
- private void RegisterVRagePlugin()
+ protected virtual void TweakGameSettings()
{
- var fieldName = "m_plugins";
- var pluginList = typeof(MyPlugins).GetField(fieldName, BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as List;
- if (pluginList == null)
- throw new TypeLoadException($"{fieldName} field not found in {nameof(MyPlugins)}");
-
- pluginList.Add(this);
}
+ ///
+ /// Tears down the VRage instance
+ ///
+ protected virtual void DisposeVRageInstance()
+ {
+ GameInstance.Dispose();
+ GameInstance = null;
+
+ MyGameService.ShutDown();
+
+ _getVRagePluginList().Remove(this);
+
+ MyInitializer.InvokeAfterRun();
+ }
+
+ #endregion
+
///
public virtual Task Save(long callerId)
{
- return Task.CompletedTask;
+ return SaveGameAsync(null);
}
///
public virtual void Start()
{
-
+ if (MySandboxGame.FatalErrorDuringInit)
+ {
+ Log.Warn($"Failed to start sandbox game: fatal error during init");
+ return;
+ }
+ GameInstance.Run();
}
///
public virtual void Stop()
{
-
+ if (IsOnGameThread())
+ MySandboxGame.Static.Exit();
+ else
+ InvokeBlocking(MySandboxGame.Static.Exit);
}
///
- public virtual void Restart()
- {
-
- }
-
- ///
- public virtual void Dispose()
- {
- Managers.Detach();
- }
+ public abstract void Restart();
///
public virtual void Init(object gameInstance)
{
-
}
///
@@ -435,6 +529,7 @@ 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.
@@ -467,4 +562,4 @@ namespace Torch
}
}
}
-}
+}
\ No newline at end of file