diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..35e3d93
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,17 @@
+FROM mcr.microsoft.com/windows/servercore:ltsc2022
+
+USER ContainerAdministrator
+ADD https://aka.ms/highdpimfc2013x64enu vc_redist2013.exe
+ADD https://aka.ms/vs/16/release/vc_redist.x64.exe vc_redist.exe
+
+RUN vc_redist2013.exe /passive /norestart
+RUN vc_redist.exe /passive /norestart
+RUN del vc_redist2013.exe && del vc_redist.exe
+
+USER ContainerUser
+COPY . .
+ENV TORCH_GAME_PATH="c:\dedi"
+ENV TORCH_INSTANCE="c:\instance"
+ENV TORCH_SERVICE="true"
+ENTRYPOINT ["Torch.Server.exe"]
+CMD ["-noupdate"]
\ No newline at end of file
diff --git a/Jenkins/jenkins-grab-se.ps1 b/Jenkins/jenkins-grab-se.ps1
deleted file mode 100644
index 0d9f43e..0000000
--- a/Jenkins/jenkins-grab-se.ps1
+++ /dev/null
@@ -1,22 +0,0 @@
-pushd
-
-$steamData = "C:/Steam/Data/"
-$steamCMDPath = "C:/Steam/steamcmd/"
-$steamCMDZip = "C:/Steam/steamcmd.zip"
-
-Add-Type -AssemblyName System.IO.Compression.FileSystem
-
-if (!(Test-Path $steamData)) {
- mkdir "$steamData"
-}
-if (!(Test-Path $steamCMDPath)) {
- if (!(Test-Path $steamCMDZip)) {
- (New-Object System.Net.WebClient).DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", "$steamCMDZip");
- }
- [System.IO.Compression.ZipFile]::ExtractToDirectory($steamCMDZip, $steamCMDPath)
-}
-
-cd "$steamData"
-& "$steamCMDPath/steamcmd.exe" "+login anonymous" "+force_install_dir $steamData" "+app_update 298740 validate" "+quit"
-
-popd
diff --git a/Jenkins/release.ps1 b/Jenkins/release.ps1
deleted file mode 100644
index 81e5e63..0000000
--- a/Jenkins/release.ps1
+++ /dev/null
@@ -1,52 +0,0 @@
-param([string] $ApiBase, [string]$tagName, [string]$authinfo, [string[]] $assetPaths)
-Add-Type -AssemblyName "System.Web"
-
-$headers = @{
- Authorization = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($authinfo))
- Accept = "application/vnd.github.v3+json"
-}
-try
-{
- Write-Output("Checking if release with tag " + $tagName + " already exists...")
- $release = Invoke-RestMethod -Uri ($ApiBase+"releases/tags/$tagName") -Method "GET" -Headers $headers
- Write-Output(" Using existing release " + $release.id + " at " + $release.html_url)
-} catch {
- Write-Output(" Doesn't exist")
- $rel_arg = @{
- tag_name=$tagName
- name="Generated $tagName"
- body=""
- draft=$TRUE
- prerelease=$tagName.Contains("alpha") -or $tagName.Contains("beta")
- }
- Write-Output("Creating new release " + $tagName + "...")
- $release = Invoke-RestMethod -Uri ($ApiBase+"releases") -Method "POST" -Headers $headers -Body (ConvertTo-Json($rel_arg))
- Write-Output(" Created new release " + $tagName + " at " + $release.html_url)
-}
-
-$assetsApiBase = $release.assets_url
-Write-Output("Checking for existing assets...")
-$existingAssets = Invoke-RestMethod -Uri ($assetsApiBase) -Method "GET" -Headers $headers
-$assetLabels = ($assetPaths | ForEach-Object {[System.IO.Path]::GetFileName($_)})
-foreach ($asset in $existingAssets) {
- if ($assetLabels -contains $asset.name) {
- $uri = $asset.url
- Write-Output(" Deleting old asset " + $asset.name + " (id " + $asset.id + "); URI=" + $uri)
- $result = Invoke-RestMethod -Uri $uri -Method "DELETE" -Headers $headers
- }
-}
-Write-Output("Uploading assets...")
-$uploadUrl = $release.upload_url.Substring(0, $release.upload_url.LastIndexOf('{'))
-foreach ($asset in $assetPaths) {
- $assetName = [System.IO.Path]::GetFileName($asset)
- $assetType = [System.Web.MimeMapping]::GetMimeMapping($asset)
- $assetData = [System.IO.File]::ReadAllBytes($asset)
- $headerExtra = $headers + @{
- "Content-Type" = $assetType
- Name = $assetName
- }
- $uri = $uploadUrl + "?name=" + $assetName
- Write-Output(" Uploading " + $asset + " as " + $assetType + "; URI=" + $uri)
- $result = Invoke-RestMethod -Uri $uri -Method "POST" -Headers $headerExtra -Body $assetData
- Write-Output(" ID=" + $result.id + ", found at=" + $result.browser_download_url)
-}
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index 3bc8a6a..0000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,77 +0,0 @@
-def packageAndArchive(buildMode, packageName) {
- zipFile = "bin\\${packageName}.zip"
- packageDir = "bin\\${packageName}\\"
-
- bat "IF EXIST ${zipFile} DEL ${zipFile}"
- bat "IF EXIST ${packageDir} RMDIR /S /Q ${packageDir}"
-
- bat "xcopy bin\\x64\\${buildMode} ${packageDir}"
-
- bat "del ${packageDir}VRage.*"
- bat "del ${packageDir}Sandbox.*"
- bat "del ${packageDir}SpaceEngineers.*"
-
- powershell "Add-Type -Assembly System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::CreateFromDirectory(\"\$PWD\\${packageDir}\", \"\$PWD\\${zipFile}\")"
- archiveArtifacts artifacts: zipFile, caseSensitive: false, onlyIfSuccessful: true
-}
-
-node('windows') {
- stage('Checkout') {
- checkout scm
- bat 'git pull https://github.com/TorchAPI/Torch/ master --tags'
- }
-
- stage('Acquire SE') {
- bat 'powershell -File Jenkins/jenkins-grab-se.ps1'
- bat 'IF EXIST GameBinaries RMDIR GameBinaries'
- bat 'mklink /J GameBinaries "C:/Steam/Data/DedicatedServer64/"'
- bat 'dir GameBinaries'
- }
-
- stage('Acquire NuGet Packages') {
- bat 'cd C:\\Program Files\\Jenkins'
- bat '"C:\\Program Files\\Jenkins\\nuget.exe" restore Torch.sln'
- }
-
- stage('Build') {
- currentBuild.description = bat(returnStdout: true, script: '@powershell -File Versioning/version.ps1').trim()
- if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "Patron" || env.BRANCH_NAME == "publictest") {
- buildMode = "Release"
- } else {
- buildMode = "Release"
- }
- bat "IF EXIST \"bin\" rmdir /Q /S \"bin\""
- bat "IF EXIST \"bin-test\" rmdir /Q /S \"bin-test\""
- bat "\"${tool 'MSBuild'}msbuild\" Torch.sln /p:Configuration=${buildMode} /p:Platform=x64 /t:Clean"
- bat "\"${tool 'MSBuild'}msbuild\" Torch.sln /p:Configuration=${buildMode} /p:Platform=x64"
- }
-
- stage('Archive') {
- archiveArtifacts artifacts: "bin/x64/${buildMode}/Torch*", caseSensitive: false, fingerprint: true, onlyIfSuccessful: true
-
- packageAndArchive(buildMode, "torch-server")
-
- /*packageAndArchive(buildMode, "torch-client", "Torch.Server*")*/
- }
-
- /* Disabled because they fail builds more often than they detect actual problems
- stage('Test') {
- bat 'IF NOT EXIST reports MKDIR reports'
- bat "\"packages/xunit.runner.console.2.2.0/tools/xunit.console.exe\" \"bin-test/x64/${buildMode}/Torch.Tests.dll\" \"bin-test/x64/${buildMode}/Torch.Server.Tests.dll\" \"bin-test/x64/${buildMode}/Torch.Client.Tests.dll\" -parallel none -xml \"reports/Torch.Tests.xml\""
-
- step([
- $class: 'XUnitBuilder',
- thresholdMode: 1,
- thresholds: [[$class: 'FailedThreshold', failureThreshold: '1']],
- tools: [[
- $class: 'XUnitDotNetTestType',
- deleteOutputFiles: true,
- failIfNotNew: true,
- pattern: 'reports/*.xml',
- skipNoTestFiles: false,
- stopProcessingIfError: true
- ]]
- ])
- }
- */
-}
diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs
index 33e4481..4b5e41f 100644
--- a/Torch.API/ITorchBase.cs
+++ b/Torch.API/ITorchBase.cs
@@ -150,6 +150,11 @@ namespace Torch.API
/// 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.API/ITorchConfig.cs b/Torch.API/ITorchConfig.cs
index 2156dfd..077d7b9 100644
--- a/Torch.API/ITorchConfig.cs
+++ b/Torch.API/ITorchConfig.cs
@@ -10,7 +10,9 @@ namespace Torch
bool ForceUpdate { get; set; }
bool GetPluginUpdates { get; set; }
bool GetTorchUpdates { get; set; }
+ [Obsolete("Use Torch.InstanceName instead")]
string InstanceName { get; set; }
+ [Obsolete("Use Torch.InstancePath instead")]
string InstancePath { get; set; }
bool NoGui { get; set; }
bool NoUpdate { get; set; }
diff --git a/Torch.API/Torch.API.csproj b/Torch.API/Torch.API.csproj
index f29f500..48dd83d 100644
--- a/Torch.API/Torch.API.csproj
+++ b/Torch.API/Torch.API.csproj
@@ -5,7 +5,7 @@
Torch
Copyright © Torch API 2017
false
- $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ ..\bin\$(Platform)\$(Configuration)\
True
False
x64
diff --git a/Torch.Server/Initializer.cs b/Torch.Server/Initializer.cs
index fe61e95..f99d13f 100644
--- a/Torch.Server/Initializer.cs
+++ b/Torch.Server/Initializer.cs
@@ -22,40 +22,35 @@ namespace Torch.Server
{
public class Initializer
{
- [Obsolete("It's hack. Do not use it!")]
internal static Initializer Instance { get; private set; }
private static readonly Logger Log = LogManager.GetLogger(nameof(Initializer));
private bool _init;
private const string STEAMCMD_DIR = "steamcmd";
private const string STEAMCMD_ZIP = "temp.zip";
- private static readonly string STEAMCMD_PATH = $"{STEAMCMD_DIR}\\steamcmd.exe";
- private static readonly string RUNSCRIPT_PATH = $"{STEAMCMD_DIR}\\runscript.txt";
+ private static readonly string STEAMCMD_EXE = "steamcmd.exe";
+ private static readonly string RUNSCRIPT_FILE = "runscript.txt";
private const string RUNSCRIPT = @"force_install_dir ../
login anonymous
app_update 298740
quit";
private TorchServer _server;
- private string _basePath;
- internal Persistent ConfigPersistent { get; private set; }
+ internal Persistent ConfigPersistent { get; }
public TorchConfig Config => ConfigPersistent?.Data;
public TorchServer Server => _server;
- public Initializer(string basePath)
+ public Initializer(string basePath, Persistent torchConfig)
{
- _basePath = basePath;
Instance = this;
+ ConfigPersistent = torchConfig;
}
public bool Initialize(string[] args)
{
if (_init)
return false;
-
- AppDomain.CurrentDomain.UnhandledException += HandleException;
-
#if DEBUG
//enables logging debug messages when built in debug mode. Amazing.
LogManager.Configuration.AddRule(LogLevel.Debug, LogLevel.Debug, "main");
@@ -69,37 +64,6 @@ quit";
if (!Enumerable.Contains(args, "-noupdate"))
RunSteamCmd();
- var basePath = new FileInfo(typeof(Program).Assembly.Location).Directory.ToString();
- var apiSource = Path.Combine(basePath, "DedicatedServer64", "steam_api64.dll");
- var apiTarget = Path.Combine(basePath, "steam_api64.dll");
-
- if (!File.Exists(apiTarget))
- {
- File.Copy(apiSource, apiTarget);
- }
- else if (File.GetLastWriteTime(apiTarget) < File.GetLastWriteTime(apiSource))
- {
- File.Delete(apiTarget);
- File.Copy(apiSource, apiTarget);
- }
-
- var havokSource = Path.Combine(basePath, "DedicatedServer64", "Havok.dll");
- var havokTarget = Path.Combine(basePath, "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);
- }
-
- InitConfig();
- if (!Config.Parse(args))
- return false;
-
if (!string.IsNullOrEmpty(Config.WaitForPID))
{
try
@@ -114,9 +78,9 @@ quit";
Thread.Sleep(1000);
}
}
- catch
+ catch (Exception e)
{
- // ignored
+ Log.Warn(e);
}
}
@@ -124,11 +88,11 @@ quit";
return true;
}
- public void Run()
+ public void Run(bool isService, string instanceName, string instancePath)
{
- _server = new TorchServer(Config);
+ _server = new TorchServer(Config, instancePath, instanceName);
- if (Config.NoGui)
+ if (isService || Config.NoGui)
{
_server.Init();
_server.Start();
@@ -164,35 +128,24 @@ quit";
ui.ShowDialog();
}
}
-
- private void InitConfig()
- {
- var configName = "Torch.cfg";
- var configPath = Path.Combine(Directory.GetCurrentDirectory(), configName);
- if (File.Exists(configName))
- {
- Log.Info($"Loading config {configName}");
- }
- else
- {
- Log.Info($"Generating default config at {configPath}");
- }
- ConfigPersistent = Persistent.Load(configPath);
- }
-
+
public static void RunSteamCmd()
{
var log = LogManager.GetLogger("SteamCMD");
- if (!Directory.Exists(STEAMCMD_DIR))
+ var path = Environment.GetEnvironmentVariable("TORCH_STEAMCMD") ?? Path.GetFullPath(STEAMCMD_DIR);
+
+ if (!Directory.Exists(path))
{
- Directory.CreateDirectory(STEAMCMD_DIR);
+ Directory.CreateDirectory(path);
}
- if (!File.Exists(RUNSCRIPT_PATH))
- File.WriteAllText(RUNSCRIPT_PATH, RUNSCRIPT);
+ var runScriptPath = Path.Combine(path, RUNSCRIPT_FILE);
+ if (!File.Exists(runScriptPath))
+ File.WriteAllText(runScriptPath, RUNSCRIPT);
- if (!File.Exists(STEAMCMD_PATH))
+ var steamCmdExePath = Path.Combine(path, STEAMCMD_EXE);
+ if (!File.Exists(steamCmdExePath))
{
try
{
@@ -201,22 +154,21 @@ quit";
using (var file = File.Create(STEAMCMD_ZIP))
client.GetStreamAsync("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip").Result.CopyTo(file);
- ZipFile.ExtractToDirectory(STEAMCMD_ZIP, STEAMCMD_DIR);
+ ZipFile.ExtractToDirectory(STEAMCMD_ZIP, path);
File.Delete(STEAMCMD_ZIP);
log.Info("SteamCMD downloaded successfully!");
}
catch (Exception e)
{
- log.Error("Failed to download SteamCMD, unable to update the DS.");
- log.Error(e);
+ log.Error(e, "Failed to download SteamCMD, unable to update the DS.");
return;
}
}
log.Info("Checking for DS updates.");
- var steamCmdProc = new ProcessStartInfo(STEAMCMD_PATH, "+runscript runscript.txt")
+ var steamCmdProc = new ProcessStartInfo(steamCmdExePath, "+runscript runscript.txt")
{
- WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), STEAMCMD_DIR),
+ WorkingDirectory = path,
UseShellExecute = false,
RedirectStandardOutput = true,
StandardOutputEncoding = Encoding.ASCII
@@ -230,29 +182,5 @@ quit";
Thread.Sleep(100);
}
}
-
- private void HandleException(object sender, UnhandledExceptionEventArgs e)
- {
- _server.FatalException = true;
- if (Debugger.IsAttached)
- return;
- var ex = (Exception)e.ExceptionObject;
- Log.Fatal(ex.ToStringDemystified());
- LogManager.Flush();
- if (Config.RestartOnCrash)
- {
- Console.WriteLine("Restarting in 5 seconds.");
- Thread.Sleep(5000);
- var exe = typeof(Program).Assembly.Location;
- Config.WaitForPID = Environment.ProcessId.ToString();
- Process.Start(exe, Config.ToString());
- }
- else
- {
- MessageBox.Show("Torch encountered a fatal error and needs to close. Please check the logs for details.");
- }
-
- Environment.Exit(1);
- }
}
}
diff --git a/Torch.Server/Managers/InstanceManager.cs b/Torch.Server/Managers/InstanceManager.cs
index 05fbbdc..5e63b77 100644
--- a/Torch.Server/Managers/InstanceManager.cs
+++ b/Torch.Server/Managers/InstanceManager.cs
@@ -41,9 +41,11 @@ namespace Torch.Server.Managers
[Dependency]
private FilesystemManager _filesystemManager;
- public InstanceManager(ITorchBase torchInstance) : base(torchInstance)
+ private new ITorchServer Torch { get; }
+
+ public InstanceManager(ITorchServer torchInstance) : base(torchInstance)
{
-
+ Torch = torchInstance;
}
public IWorld SelectedWorld => DedicatedConfig.SelectedWorld;
@@ -74,7 +76,7 @@ namespace Torch.Server.Managers
DedicatedConfig = new ConfigDedicatedViewModel((MyConfigDedicated) MySandboxGame.ConfigDedicated);
- var worldFolders = Directory.EnumerateDirectories(Path.Combine(Torch.Config.InstancePath, "Saves"));
+ var worldFolders = Directory.EnumerateDirectories(Path.Combine(Torch.InstancePath, "Saves"));
foreach (var f in worldFolders)
{
@@ -226,7 +228,7 @@ namespace Torch.Server.Managers
{
if (!((TorchServer)Torch).HasRun)
{
- DedicatedConfig.Save(Path.Combine(Torch.Config.InstancePath, CONFIG_NAME));
+ DedicatedConfig.Save(Path.Combine(Torch.InstancePath, CONFIG_NAME));
Log.Info("Saved dedicated config.");
}
diff --git a/Torch.Server/Program.cs b/Torch.Server/Program.cs
index a51ff6e..179bf8d 100644
--- a/Torch.Server/Program.cs
+++ b/Torch.Server/Program.cs
@@ -1,17 +1,5 @@
using System;
-using System.Diagnostics;
using System.IO;
-using System.IO.Compression;
-using System.Linq;
-using System.Net;
-using System.ServiceProcess;
-using System.Text;
-using System.Threading;
-#if TORCH_SERVICE
-using Microsoft.VisualBasic.Devices;
-#endif
-using NLog;
-using NLog.Fluent;
using NLog.Targets;
using Torch.Utils;
@@ -19,19 +7,17 @@ namespace Torch.Server
{
internal static class Program
{
- ///
- /// This method must *NOT* load any types/assemblies from the vanilla game, otherwise automatic updates will fail.
- ///
- [STAThread]
public static void Main(string[] args)
{
+ var isService = Environment.GetEnvironmentVariable("TORCH_SERVICE")
+ ?.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase) ?? false;
Target.Register(nameof(LogViewerTarget));
//Ensures that all the files are downloaded in the Torch directory.
- var workingDir = new FileInfo(typeof(Program).Assembly.Location).Directory!.FullName;
- var binDir = Path.Combine(workingDir, "DedicatedServer64");
- Directory.SetCurrentDirectory(workingDir);
+ var workingDir = AppContext.BaseDirectory;
+ var binDir = Path.Combine(Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? workingDir, "DedicatedServer64");
+ Directory.SetCurrentDirectory(Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? workingDir);
- if (Directory.Exists(binDir))
+ if (!isService && Directory.Exists(binDir))
foreach (var file in Directory.GetFiles(binDir, "System.*.dll"))
{
File.Delete(file);
@@ -49,11 +35,71 @@ namespace Torch.Server
}
#endif
- var initializer = new Initializer(workingDir);
- if (!initializer.Initialize(args))
- return;
+ var instanceName = Environment.GetEnvironmentVariable("TORCH_INSTANCE") ?? "Instance";
+ string instancePath;
+
+ if (Path.IsPathRooted(instanceName))
+ {
+ instancePath = instanceName;
+ instanceName = Path.GetDirectoryName(instanceName);
+ }
+ else
+ {
+ instancePath = Path.GetFullPath(instanceName);
+ }
- initializer.Run();
+ var oldTorchCfg = Path.Combine(workingDir, "Torch.cfg");
+ var torchCfg = Path.Combine(instancePath, "Torch.cfg");
+
+ if (File.Exists(oldTorchCfg))
+ File.Move(oldTorchCfg, torchCfg, true);
+
+ var config = Persistent.Load(torchCfg);
+ config.Data.InstanceName = instanceName;
+ config.Data.InstancePath = instancePath;
+ if (!config.Data.Parse(args))
+ {
+ Console.WriteLine("Invalid arguments");
+ Environment.Exit(1);
+ }
+
+ var handler = new UnhandledExceptionHandler(config.Data, isService);
+ AppDomain.CurrentDomain.UnhandledException += handler.OnUnhandledException;
+
+ var initializer = new Initializer(workingDir, config);
+ if (!initializer.Initialize(args))
+ Environment.Exit(1);
+
+ CopyNative(binDir);
+ initializer.Run(isService, instanceName, instancePath);
+ }
+
+ private static void CopyNative(string binPath)
+ {
+ var apiSource = Path.Combine(binPath, "steam_api64.dll");
+ var apiTarget = Path.Combine(AppContext.BaseDirectory, "steam_api64.dll");
+ if (!File.Exists(apiTarget))
+ {
+ File.Copy(apiSource, apiTarget);
+ }
+ else if (File.GetLastWriteTime(apiTarget) < File.GetLastWriteTime(binPath))
+ {
+ File.Delete(apiTarget);
+ File.Copy(apiSource, apiTarget);
+ }
+
+ var havokSource = Path.Combine(binPath, "Havok.dll");
+ var havokTarget = Path.Combine(AppContext.BaseDirectory, "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);
+ }
}
}
}
diff --git a/Torch.Server/Torch.Server.csproj b/Torch.Server/Torch.Server.csproj
index d6e2bbc..ca88df6 100644
--- a/Torch.Server/Torch.Server.csproj
+++ b/Torch.Server/Torch.Server.csproj
@@ -5,31 +5,22 @@
{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
true
publish\
- true
- Disk
- false
- Foreground
- 7
- Days
- false
- false
- true
0
1.0.0.%2a
- false
false
- true
Torch Server
Torch
Copyright © Torch API 2017
false
- $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ ..\bin\$(Platform)\$(Configuration)\
true
False
en
x64
Debug;Release
AnyCPU
+ false
+ en
Torch.Server.Program
@@ -169,8 +160,7 @@
+
+
-
-
-
\ No newline at end of file
diff --git a/Torch.Server/Torch.Server.csproj.DotSettings b/Torch.Server/Torch.Server.csproj.DotSettings
new file mode 100644
index 0000000..6e7fff8
--- /dev/null
+++ b/Torch.Server/Torch.Server.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ No
\ No newline at end of file
diff --git a/Torch.Server/TorchConfig.cs b/Torch.Server/TorchConfig.cs
index fa0cc52..9068afe 100644
--- a/Torch.Server/TorchConfig.cs
+++ b/Torch.Server/TorchConfig.cs
@@ -17,9 +17,7 @@ namespace Torch.Server
public bool ShouldUpdatePlugins => (GetPluginUpdates && !NoUpdate) || ForceUpdate;
public bool ShouldUpdateTorch => (GetTorchUpdates && !NoUpdate) || ForceUpdate;
-
- private string _instancePath = Path.GetFullPath("Instance");
- private string _instanceName = "Instance";
+
private bool _autostart;
private bool _restartOnCrash;
private bool _noGui;
@@ -40,21 +38,6 @@ namespace Torch.Server
private UGCServiceType _ugcServiceType = UGCServiceType.Steam;
private bool _entityManagerEnabled = true;
-
- ///
- [Arg("instancename", "The name of the Torch instance.")]
- [Display(Name = "Instance Name", Description = "The name of the Torch instance.", GroupName = "Server")]
- public string InstanceName { get => _instanceName; set => Set(value, ref _instanceName); }
-
- ///
- [Arg("instancepath", "Server data folder where saves and mods are stored.")]
- [Display(Name = "Instance Path", Description = "Server data folder where saves and mods are stored.", GroupName = "Server")]
- public string InstancePath
- {
- get => _instancePath;
- set => Set(value, ref _instancePath);
- }
-
///
[XmlIgnore, Arg("noupdate", "Disable automatically downloading game and plugin updates.")]
public bool NoUpdate { get; set; }
@@ -81,6 +64,8 @@ namespace Torch.Server
[Display(Name = "Restart On Crash", Description = "Automatically restart the server if it crashes.", GroupName = "Server")]
public bool RestartOnCrash { get => _restartOnCrash; set => Set(value, ref _restartOnCrash); }
+ public string InstancePath { get; set; }
+
///
[Arg("nogui", "Do not show the Torch UI.")]
[Display(Name = "No GUI", Description = "Do not show the Torch UI.", GroupName = "Window")]
@@ -94,6 +79,8 @@ namespace Torch.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 string InstanceName { get; set; }
+
///
[Display(Name = "Update Plugins", Description = "Check every start for new versions of plugins.", GroupName = "Server")]
public bool GetPluginUpdates { get => _getPluginUpdates; set => Set(value, ref _getPluginUpdates); }
diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs
index e2d3ab1..47529fa 100644
--- a/Torch.Server/TorchServer.cs
+++ b/Torch.Server/TorchServer.cs
@@ -55,8 +55,10 @@ namespace Torch.Server
//Here to trigger rebuild
///
- public TorchServer(TorchConfig config) : base(config)
+ public TorchServer(ITorchConfig config, string instancePath, string instanceName) : base(config)
{
+ InstancePath = instancePath;
+ InstanceName = instanceName;
DedicatedInstance = new InstanceManager(this);
AddManager(DedicatedInstance);
if (config.EntityManagerEnabled)
@@ -116,7 +118,7 @@ namespace Torch.Server
public InstanceManager DedicatedInstance { get; }
///
- public string InstanceName => Config?.InstanceName;
+ public string InstanceName { get; }
///
protected override uint SteamAppId => 244850;
@@ -130,7 +132,7 @@ namespace Torch.Server
public event Action Initialized;
///
- public string InstancePath => Config?.InstancePath;
+ public string InstancePath { get; }
public int OnlinePlayers { get => _players; private set => SetValue(ref _players, value); }
@@ -141,10 +143,10 @@ namespace Torch.Server
MySandboxGame.IsDedicated = true;
base.Init();
Managers.GetManager().SessionStateChanged += OnSessionStateChanged;
- GetManager().LoadInstance(Config.InstancePath);
+ GetManager().LoadInstance(InstancePath);
CanRun = true;
Initialized?.Invoke(this);
- Log.Info($"Initialized server '{Config.InstanceName}' at '{Config.InstancePath}'");
+ Log.Info($"Initialized server '{InstanceName}' at '{InstancePath}'");
}
///
diff --git a/Torch.Server/UnhandledExceptionHandler.cs b/Torch.Server/UnhandledExceptionHandler.cs
new file mode 100644
index 0000000..86a831d
--- /dev/null
+++ b/Torch.Server/UnhandledExceptionHandler.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Diagnostics;
+using System.Threading;
+using NLog;
+using VRage;
+
+namespace Torch.Server;
+
+internal class UnhandledExceptionHandler
+{
+ private readonly TorchConfig _config;
+ private readonly bool _isService;
+ private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
+
+ public UnhandledExceptionHandler(TorchConfig config, bool isService)
+ {
+ _config = config;
+ _isService = isService;
+ }
+
+ internal void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ if (Debugger.IsAttached)
+ return;
+ var ex = (Exception)e.ExceptionObject;
+ Log.Fatal(ex.ToStringDemystified());
+ LogManager.Flush();
+
+ if (_isService)
+ Environment.Exit(1);
+
+ if (_config.RestartOnCrash)
+ {
+ Console.WriteLine("Restarting in 5 seconds.");
+ Thread.Sleep(5000);
+ var exe = typeof(Program).Assembly.Location;
+ _config.WaitForPID = Environment.ProcessId.ToString();
+ Process.Start(exe, _config.ToString());
+ }
+ else
+ {
+ MyVRage.Platform.Windows.MessageBox(
+ "Torch encountered a fatal error and needs to close. Please check the logs for details.",
+ "Fatal exception", MessageBoxOptions.OkOnly);
+ }
+
+ Environment.Exit(1);
+ }
+}
\ No newline at end of file
diff --git a/Torch.sln b/Torch.sln
index e44265d..b1cf872 100644
--- a/Torch.sln
+++ b/Torch.sln
@@ -12,6 +12,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7AD02A71-1D4C-48F9-A8C1-789A5512424F}"
ProjectSection(SolutionItems) = preProject
NLog.config = NLog.config
+ Dockerfile = Dockerfile
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Tests", "Torch.Tests\Torch.Tests.csproj", "{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}"
diff --git a/Torch/Patches/KeenLogPatch.cs b/Torch/Patches/KeenLogPatch.cs
index c6e6e8c..4bfc23c 100644
--- a/Torch/Patches/KeenLogPatch.cs
+++ b/Torch/Patches/KeenLogPatch.cs
@@ -46,6 +46,9 @@ namespace Torch.Patches
[ReflectedMethodInfo(typeof(MyLog), nameof(MyLog.Init))]
private static MethodInfo _logInit;
+
+ [ReflectedMethodInfo(typeof(MyLog), nameof(MyLog.Close))]
+ private static MethodInfo _logClose;
#pragma warning restore 649
@@ -64,6 +67,7 @@ namespace Torch.Patches
context.GetPattern(_logWriteLineOptions).AddPrefix(nameof(PrefixWriteLineOptions));
context.GetPattern(_logInit).AddPrefix(nameof(PrefixInit));
+ context.GetPattern(_logClose).AddPrefix(nameof(PrefixClose));
}
[ReflectedMethod(Name = "GetIdentByThread")]
@@ -81,6 +85,8 @@ namespace Torch.Patches
return _getIndentByThread(MyLog.Default, Environment.CurrentManagedThreadId);
}
+ private static bool PrefixClose() => false;
+
private static bool PrefixInit(MyLog __instance, StringBuilder appVersionString)
{
__instance.WriteLine("Log Started");
diff --git a/Torch/Persistent.cs b/Torch/Persistent.cs
index 9bbd641..050c730 100644
--- a/Torch/Persistent.cs
+++ b/Torch/Persistent.cs
@@ -26,7 +26,7 @@ namespace Torch
public T Data
{
get => _data;
- private set
+ private init
{
if (_data is INotifyPropertyChanged npc1)
npc1.PropertyChanged -= OnPropertyChanged;
diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj
index a7d20f7..a5eac3c 100644
--- a/Torch/Torch.csproj
+++ b/Torch/Torch.csproj
@@ -6,7 +6,7 @@
Copyright © Torch API 2017
false
true
- $(SolutionDir)\bin\$(Platform)\$(Configuration)\
+ ..\bin\$(Platform)\$(Configuration)\
True
False
x64
diff --git a/Versioning/version.ps1 b/Versioning/version.ps1
deleted file mode 100644
index 184a208..0000000
--- a/Versioning/version.ps1
+++ /dev/null
@@ -1,17 +0,0 @@
-$buildSalt = $Env:BUILD_NUMBER
-$branchName = $Env:BRANCH_NAME
-$gitSimpleVersion = git describe --tags --abbrev=0
-$simpleVersionStandard = echo $gitSimpleVersion | Select-String -Pattern "([0-9]+)\.([0-9]+)\.([0-9]+)" | % {$_.Matches} | %{$_.Groups[1].Value+"."+$_.Groups[2].Value+"."+$_.Groups[3].Value}
-$dotNetVersion = "$simpleVersionStandard.$buildSalt"
-$infoVersion = -join(("$gitSimpleVersion" -replace "([0-9]+)\.([0-9]+)\.([0-9]+)","$dotNetVersion"), "-", "$branchName")
-
-$fileContent = @"
-using System.Reflection;
-
-[assembly: AssemblyVersion("$dotNetVersion")]
-[assembly: AssemblyInformationalVersion("$infoVersion")]
-"@
-
-echo $fileContent | Set-Content "$PSScriptRoot/AssemblyVersion.cs"
-
-echo "$infoVersion"
\ No newline at end of file