seems to be configuration rework
This commit is contained in:
@@ -22,7 +22,6 @@ namespace Torch
|
|||||||
bool ShouldUpdatePlugins { get; }
|
bool ShouldUpdatePlugins { get; }
|
||||||
bool ShouldUpdateTorch { get; }
|
bool ShouldUpdateTorch { get; }
|
||||||
int TickTimeout { get; set; }
|
int TickTimeout { get; set; }
|
||||||
string WaitForPID { get; set; }
|
|
||||||
string ChatName { get; set; }
|
string ChatName { get; set; }
|
||||||
string ChatColor { get; set; }
|
string ChatColor { get; set; }
|
||||||
string TestPlugin { get; set; }
|
string TestPlugin { get; set; }
|
||||||
|
@@ -12,6 +12,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
using Sandbox.Engine.Utils;
|
using Sandbox.Engine.Utils;
|
||||||
@@ -42,7 +43,7 @@ namespace Torch.Server
|
|||||||
ConfigPersistent = torchConfig;
|
ConfigPersistent = torchConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Initialize(string[] args)
|
public bool Initialize(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
if (_init)
|
if (_init)
|
||||||
return false;
|
return false;
|
||||||
@@ -55,15 +56,14 @@ namespace Torch.Server
|
|||||||
Log.Debug("Debug logging enabled.");
|
Log.Debug("Debug logging enabled.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This is what happens when Keen is bad and puts extensions into the System namespace.
|
if (!configuration.GetValue("noupdate", false))
|
||||||
if (!Enumerable.Contains(args, "-noupdate"))
|
|
||||||
RunSteamCmd();
|
RunSteamCmd();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Config.WaitForPID))
|
if (configuration.GetSection("waitForPid") is { } processPid)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var pid = int.Parse(Config.WaitForPID);
|
var pid = processPid.Get<int>();
|
||||||
var waitProc = Process.GetProcessById(pid);
|
var waitProc = Process.GetProcessById(pid);
|
||||||
Log.Info("Continuing in 5 seconds.");
|
Log.Info("Continuing in 5 seconds.");
|
||||||
Log.Warn($"Waiting for process {pid} to close");
|
Log.Warn($"Waiting for process {pid} to close");
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Configuration.Xml;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Config;
|
using NLog.Config;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
@@ -13,31 +15,21 @@ namespace Torch.Server
|
|||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var context = CreateApplicationContext();
|
var configurationBuilder = new ConfigurationBuilder()
|
||||||
|
.AddEnvironmentVariables("TORCH")
|
||||||
|
.AddCommandLine(args);
|
||||||
|
var configuration = configurationBuilder.Build();
|
||||||
|
|
||||||
SetupLogging();
|
var context = CreateApplicationContext(configuration);
|
||||||
|
|
||||||
var oldTorchCfg = Path.Combine(context.TorchDirectory.FullName, "Torch.cfg");
|
SetupLogging(context);
|
||||||
var torchCfg = Path.Combine(context.InstanceDirectory.FullName, "Torch.cfg");
|
var config = SetupConfiguration(context, configurationBuilder);
|
||||||
|
|
||||||
if (File.Exists(oldTorchCfg))
|
|
||||||
File.Move(oldTorchCfg, torchCfg);
|
|
||||||
|
|
||||||
var config = Persistent<TorchConfig>.Load(torchCfg);
|
|
||||||
config.Data.InstanceName = context.InstanceName;
|
|
||||||
config.Data.InstancePath = context.InstanceDirectory.FullName;
|
|
||||||
|
|
||||||
if (!config.Data.Parse(args))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Invalid arguments");
|
|
||||||
Environment.Exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var handler = new UnhandledExceptionHandler(config.Data);
|
var handler = new UnhandledExceptionHandler(config.Data);
|
||||||
AppDomain.CurrentDomain.UnhandledException += handler.OnUnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += handler.OnUnhandledException;
|
||||||
|
|
||||||
var initializer = new Initializer(config);
|
var initializer = new Initializer(config);
|
||||||
if (!initializer.Initialize(args))
|
if (!initializer.Initialize(configuration))
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -47,62 +39,13 @@ namespace Torch.Server
|
|||||||
context.GameBinariesDirectory.FullName);
|
context.GameBinariesDirectory.FullName);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CopyNative();
|
|
||||||
|
|
||||||
initializer.Run();
|
initializer.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyNative()
|
private static void SetupLogging(IApplicationContext context)
|
||||||
{
|
{
|
||||||
var log = LogManager.GetLogger("TorchLauncher");
|
var oldNlog = Path.Combine(context.TorchDirectory.FullName, "NLog.config");
|
||||||
|
var newNlog = Path.Combine(context.InstanceDirectory.FullName, "NLog.config");
|
||||||
if (ApplicationContext.Current.GameFilesDirectory.Attributes.HasFlag(FileAttributes.ReadOnly))
|
|
||||||
{
|
|
||||||
log.Warn("Torch directory is readonly. You should copy steam_api64.dll, Havok.dll from bin manually");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var apiSource = Path.Combine(ApplicationContext.Current.GameBinariesDirectory.FullName, "steam_api64.dll");
|
|
||||||
var apiTarget = Path.Combine(ApplicationContext.Current.GameFilesDirectory.FullName, "steam_api64.dll");
|
|
||||||
if (!File.Exists(apiTarget))
|
|
||||||
{
|
|
||||||
File.Copy(apiSource, apiTarget);
|
|
||||||
}
|
|
||||||
else if (File.GetLastWriteTime(apiTarget) < ApplicationContext.Current.GameBinariesDirectory.LastWriteTime)
|
|
||||||
{
|
|
||||||
File.Delete(apiTarget);
|
|
||||||
File.Copy(apiSource, apiTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
var havokSource = Path.Combine(ApplicationContext.Current.GameBinariesDirectory.FullName, "Havok.dll");
|
|
||||||
var havokTarget = Path.Combine(ApplicationContext.Current.GameFilesDirectory.FullName, "Havok.dll");
|
|
||||||
|
|
||||||
if (!File.Exists(havokTarget))
|
|
||||||
{
|
|
||||||
File.Copy(havokSource, havokTarget);
|
|
||||||
}
|
|
||||||
else if (File.GetLastWriteTime(havokTarget) < File.GetLastWriteTime(havokSource))
|
|
||||||
{
|
|
||||||
File.Delete(havokTarget);
|
|
||||||
File.Copy(havokSource, havokTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (UnauthorizedAccessException)
|
|
||||||
{
|
|
||||||
// file is being used by another process, probably previous torch has not been closed yet
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
log.Error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetupLogging()
|
|
||||||
{
|
|
||||||
var oldNlog = Path.Combine(ApplicationContext.Current.TorchDirectory.FullName, "NLog.config");
|
|
||||||
var newNlog = Path.Combine(ApplicationContext.Current.InstanceDirectory.FullName, "NLog.config");
|
|
||||||
if (File.Exists(oldNlog) && !File.ReadAllText(oldNlog).Contains("FlowDocument"))
|
if (File.Exists(oldNlog) && !File.ReadAllText(oldNlog).Contains("FlowDocument"))
|
||||||
File.Move(oldNlog, newNlog);
|
File.Move(oldNlog, newNlog);
|
||||||
else if (!File.Exists(newNlog))
|
else if (!File.Exists(newNlog))
|
||||||
@@ -111,22 +54,47 @@ namespace Torch.Server
|
|||||||
|
|
||||||
Target.Register<LogViewerTarget>(nameof(LogViewerTarget));
|
Target.Register<LogViewerTarget>(nameof(LogViewerTarget));
|
||||||
TorchLogManager.RegisterTargets(Environment.GetEnvironmentVariable("TORCH_LOG_EXTENSIONS_PATH") ??
|
TorchLogManager.RegisterTargets(Environment.GetEnvironmentVariable("TORCH_LOG_EXTENSIONS_PATH") ??
|
||||||
Path.Combine(ApplicationContext.Current.InstanceDirectory.FullName, "LoggingExtensions"));
|
Path.Combine(context.InstanceDirectory.FullName, "LoggingExtensions"));
|
||||||
|
|
||||||
TorchLogManager.SetConfiguration(new XmlLoggingConfiguration(newNlog));
|
TorchLogManager.SetConfiguration(new XmlLoggingConfiguration(newNlog));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IApplicationContext CreateApplicationContext()
|
private static Persistent<TorchConfig> SetupConfiguration(IApplicationContext context, IConfigurationBuilder builder)
|
||||||
{
|
{
|
||||||
var isService = Environment.GetEnvironmentVariable("TORCH_SERVICE")
|
var oldTorchCfg = Path.Combine(context.TorchDirectory.FullName, "Torch.cfg");
|
||||||
?.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase) ?? false;
|
var torchCfg = Path.Combine(context.InstanceDirectory.FullName, "Torch.cfg");
|
||||||
|
|
||||||
|
if (File.Exists(oldTorchCfg))
|
||||||
|
File.Move(oldTorchCfg, torchCfg);
|
||||||
|
|
||||||
|
var configurationSource = new XmlConfigurationSource
|
||||||
|
{
|
||||||
|
Path = torchCfg
|
||||||
|
};
|
||||||
|
|
||||||
|
configurationSource.ResolveFileProvider();
|
||||||
|
builder.Sources.Insert(0, configurationSource);
|
||||||
|
|
||||||
|
var configuration = builder.Build();
|
||||||
|
|
||||||
|
var config = new Persistent<TorchConfig>(torchCfg, configuration.Get<TorchConfig>());
|
||||||
|
config.Data.InstanceName = context.InstanceName;
|
||||||
|
config.Data.InstancePath = context.InstanceDirectory.FullName;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IApplicationContext CreateApplicationContext(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
var isService = configuration.GetValue("service", false);
|
||||||
|
|
||||||
var workingDir = AppContext.BaseDirectory;
|
var workingDir = AppContext.BaseDirectory;
|
||||||
var gamePath = Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? workingDir;
|
var gamePath = configuration.GetValue("gamePath", workingDir);
|
||||||
var binDir = Path.Combine(gamePath, "DedicatedServer64");
|
var binDir = Path.Combine(gamePath, "DedicatedServer64");
|
||||||
|
|
||||||
Directory.SetCurrentDirectory(gamePath);
|
Directory.SetCurrentDirectory(gamePath);
|
||||||
|
|
||||||
var instanceName = Environment.GetEnvironmentVariable("TORCH_INSTANCE") ?? "Instance";
|
var instanceName = configuration.GetValue("instanceName", "Instance");
|
||||||
string instancePath;
|
string instancePath;
|
||||||
|
|
||||||
if (Path.IsPathRooted(instanceName))
|
if (Path.IsPathRooted(instanceName))
|
||||||
@@ -136,7 +104,7 @@ namespace Torch.Server
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
instancePath = Directory.CreateDirectory(instanceName).FullName;
|
instancePath = Directory.CreateDirectory(instanceName!).FullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ApplicationContext(new(workingDir), new(gamePath), new(binDir),
|
return new ApplicationContext(new(workingDir), new(gamePath), new(binDir),
|
||||||
|
@@ -38,6 +38,10 @@
|
|||||||
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
||||||
<PackageReference Include="MdXaml" Version="1.13.0" />
|
<PackageReference Include="MdXaml" Version="1.13.0" />
|
||||||
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.0.226801" />
|
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.0.226801" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="6.0.0" />
|
||||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
||||||
<PackageReference Include="PropertyChanged.Fody" Version="4.0.0" PrivateAssets="all" />
|
<PackageReference Include="PropertyChanged.Fody" Version="4.0.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
@@ -71,10 +71,6 @@ namespace Torch.Server
|
|||||||
[Display(Name = "No GUI", Description = "Do not show the Torch UI.", GroupName = "Window")]
|
[Display(Name = "No GUI", Description = "Do not show the Torch UI.", GroupName = "Window")]
|
||||||
public bool NoGui { get => _noGui; set => Set(value, ref _noGui); }
|
public bool NoGui { get => _noGui; set => Set(value, ref _noGui); }
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
[XmlIgnore, Arg("waitforpid", "Makes Torch wait for another process to exit.")]
|
|
||||||
public string WaitForPID { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[Display(Name = "Update Torch", Description = "Check every start for new versions of torch.", GroupName = "Server")]
|
[Display(Name = "Update Torch", Description = "Check every start for new versions of torch.", GroupName = "Server")]
|
||||||
public bool GetTorchUpdates { get => _getTorchUpdates; set => Set(value, ref _getTorchUpdates); }
|
public bool GetTorchUpdates { get => _getTorchUpdates; set => Set(value, ref _getTorchUpdates); }
|
||||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using NLog;
|
||||||
using Torch.Event;
|
using Torch.Event;
|
||||||
using Torch.Managers.PatchManager;
|
using Torch.Managers.PatchManager;
|
||||||
using VRage.Collections;
|
using VRage.Collections;
|
||||||
@@ -11,11 +12,14 @@ namespace Torch.Utils
|
|||||||
{
|
{
|
||||||
public static class TorchLauncher
|
public static class TorchLauncher
|
||||||
{
|
{
|
||||||
|
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
||||||
private static readonly MyConcurrentHashSet<Assembly> RegisteredAssemblies = new();
|
private static readonly MyConcurrentHashSet<Assembly> RegisteredAssemblies = new();
|
||||||
private static readonly Dictionary<string, string> Assemblies = new();
|
private static readonly Dictionary<string, string> Assemblies = new();
|
||||||
|
|
||||||
public static void Launch(params string[] binaryPaths)
|
public static void Launch(params string[] binaryPaths)
|
||||||
{
|
{
|
||||||
|
CopyNative();
|
||||||
|
|
||||||
foreach (var file in binaryPaths.SelectMany(path => Directory.EnumerateFiles(path, "*.dll")))
|
foreach (var file in binaryPaths.SelectMany(path => Directory.EnumerateFiles(path, "*.dll")))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -42,6 +46,51 @@ namespace Torch.Utils
|
|||||||
PatchManager.AddPatchShims(assembly);
|
PatchManager.AddPatchShims(assembly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void CopyNative()
|
||||||
|
{
|
||||||
|
if (ApplicationContext.Current.GameFilesDirectory.Attributes.HasFlag(FileAttributes.ReadOnly))
|
||||||
|
{
|
||||||
|
Log.Warn("Torch directory is readonly. You should copy steam_api64.dll, Havok.dll from bin manually");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var apiSource = Path.Combine(ApplicationContext.Current.GameBinariesDirectory.FullName, "steam_api64.dll");
|
||||||
|
var apiTarget = Path.Combine(ApplicationContext.Current.GameFilesDirectory.FullName, "steam_api64.dll");
|
||||||
|
if (!File.Exists(apiTarget))
|
||||||
|
{
|
||||||
|
File.Copy(apiSource, apiTarget);
|
||||||
|
}
|
||||||
|
else if (File.GetLastWriteTime(apiTarget) < ApplicationContext.Current.GameBinariesDirectory.LastWriteTime)
|
||||||
|
{
|
||||||
|
File.Delete(apiTarget);
|
||||||
|
File.Copy(apiSource, apiTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
var havokSource = Path.Combine(ApplicationContext.Current.GameBinariesDirectory.FullName, "Havok.dll");
|
||||||
|
var havokTarget = Path.Combine(ApplicationContext.Current.GameFilesDirectory.FullName, "Havok.dll");
|
||||||
|
|
||||||
|
if (!File.Exists(havokTarget))
|
||||||
|
{
|
||||||
|
File.Copy(havokSource, havokTarget);
|
||||||
|
}
|
||||||
|
else if (File.GetLastWriteTime(havokTarget) < File.GetLastWriteTime(havokSource))
|
||||||
|
{
|
||||||
|
File.Delete(havokTarget);
|
||||||
|
File.Copy(havokSource, havokTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
// file is being used by another process, probably previous torch has not been closed yet
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
|
private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
|
||||||
{
|
{
|
||||||
var name = args.Name;
|
var name = args.Name;
|
||||||
|
Reference in New Issue
Block a user