Compare commits
4 Commits
v1.0.43-ma
...
v1.0.47-ma
Author | SHA1 | Date | |
---|---|---|---|
![]() |
15be85b4f5 | ||
![]() |
cf5c00ce0e | ||
![]() |
9c185d5577 | ||
![]() |
8b6c401531 |
5
Jenkins/get-version.ps1
Normal file
5
Jenkins/get-version.ps1
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
$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}
|
||||||
|
Write-Host "$simpleVersionStandard.$buildSalt"
|
26
Jenkins/jenkins-grab-se.ps1
Normal file
26
Jenkins/jenkins-grab-se.ps1
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
pushd
|
||||||
|
|
||||||
|
$steamData = "C:/Steam/Data/"
|
||||||
|
$steamCMDPath = "C:/Steam/steamcmd/"
|
||||||
|
$steamCMDZip = "C:/Steam/steamcmd.zip"
|
||||||
|
|
||||||
|
if (!(Test-Path $steamData)) {
|
||||||
|
mkdir "$steamData"
|
||||||
|
}
|
||||||
|
if (!(Test-Path $steamCMDPath)) {
|
||||||
|
if (!(Test-Path $steamCMDZip)) {
|
||||||
|
Invoke-WebRequest -OutFile $steamCMDZip https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip
|
||||||
|
}
|
||||||
|
Expand-Archive $steamCMDZip -DestinationPath $steamCMDPath
|
||||||
|
}
|
||||||
|
& "$steamCMDPath/steamcmd.exe" "+login anonymous" "+force_install_dir $steamData" "+app_update 298740" "+quit"
|
||||||
|
|
||||||
|
$dataPath = $steamData.Replace("/", "\");
|
||||||
|
$contentPath = "$dataPath\Content";
|
||||||
|
if (Test-Path $contentPath) {
|
||||||
|
Remove-Item -LiteralPath $contentPath -Force -Recurse
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd /S /C mklink /J .\GameBinaries $dataPath\DedicatedServer64
|
||||||
|
|
||||||
|
popd
|
55
Jenkinsfile
vendored
Normal file
55
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
def packageAndArchive(buildMode, packageName) {
|
||||||
|
zipFile = "bin\\${packageName}.zip"
|
||||||
|
packageDir = "publish"
|
||||||
|
|
||||||
|
bat 'powershell -Command { Compress-Archive -Path ${packageDir}\\* -DestinationPath ${zipFile} }'
|
||||||
|
archiveArtifacts artifacts: zipFile, caseSensitive: false, onlyIfSuccessful: true
|
||||||
|
}
|
||||||
|
|
||||||
|
node('windows') {
|
||||||
|
stage('Checkout') {
|
||||||
|
checkout scm
|
||||||
|
bat 'git pull https://github.com/TorchAPI/Torch/ ${env.BRANCH_NAME} --tags'
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Acquire SE') {
|
||||||
|
bat 'powershell -File Jenkins/jenkins-grab-se.ps1'
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Build') {
|
||||||
|
dotnetVersion = bat(returnStdout: true, script: '@powershell -NonInteractive -NoLogo -NoProfile -File Jenkins/get-version.ps1').trim()
|
||||||
|
infoVersion = "${dotnetVersion}-${env.BRANCH_NAME}"
|
||||||
|
currentBuild.description = infoVersion
|
||||||
|
|
||||||
|
bat 'dotnet publish .\\Torch.Server\\Torch.Server.csproj -p:PackageVersion=${dotnetVersion} -p:InformationalVersion=${infoVersion} --self-contained -f net6-windows -r win-x64 -c Release -o .\\publish\\'
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
]]
|
||||||
|
])
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
30
Torch.API/IApplicationContext.cs
Normal file
30
Torch.API/IApplicationContext.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System.IO;
|
||||||
|
namespace Torch.API;
|
||||||
|
|
||||||
|
public interface IApplicationContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Directory contains torch binaries.
|
||||||
|
/// </summary>
|
||||||
|
public DirectoryInfo TorchDirectory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Root directory for all game files.
|
||||||
|
/// </summary>
|
||||||
|
public DirectoryInfo GameFilesDirectory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Directory contains game binaries.
|
||||||
|
/// </summary>
|
||||||
|
public DirectoryInfo GameBinariesDirectory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Current instance directory.
|
||||||
|
/// </summary>
|
||||||
|
public DirectoryInfo InstanceDirectory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Current instance name.
|
||||||
|
/// </summary>
|
||||||
|
public string InstanceName { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Application running in service mode.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsService { get; }
|
||||||
|
}
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch API")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -1,13 +1,13 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net6-windows</TargetFramework>
|
||||||
|
<LangVersion>10</LangVersion>
|
||||||
<AssemblyTitle>Torch API</AssemblyTitle>
|
<AssemblyTitle>Torch API</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
<Copyright>Copyright © Torch API 2017</Copyright>
|
<Copyright>Copyright © Torch API 2017</Copyright>
|
||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||||
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||||
<UseWpf>True</UseWpf>
|
<UseWpf>True</UseWpf>
|
||||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Platforms>AnyCPU</Platforms>
|
<Platforms>AnyCPU</Platforms>
|
||||||
@@ -19,6 +19,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
<PackageReference Include="NLog" Version="5.0.0-rc2" />
|
||||||
<PackageReference Include="SemanticVersioning" Version="2.0.0" />
|
<PackageReference Include="SemanticVersioning" Version="2.0.0" />
|
||||||
|
<PackageReference Include="System.Text.Json" Version="6.0.2" Condition="$(TargetFramework) == 'net48'" />
|
||||||
|
<PackageReference Include="System.Net.Http" Version="4.3.4" Condition="$(TargetFramework) == 'net48'" />
|
||||||
|
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" Condition="$(TargetFramework) == 'net48'" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="HavokWrapper, Version=1.0.6278.22649, Culture=neutral, processorArchitecture=AMD64">
|
<Reference Include="HavokWrapper, Version=1.0.6278.22649, Culture=neutral, processorArchitecture=AMD64">
|
||||||
@@ -99,7 +102,4 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
8
Torch.API/Utils/IsExternalInit.cs
Normal file
8
Torch.API/Utils/IsExternalInit.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#if NETFRAMEWORK
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
public class IsExternalInit
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
@@ -68,7 +68,11 @@ namespace Torch.API.WebAPI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var s = await h.Content.ReadAsStreamAsync();
|
var s = await h.Content.ReadAsStreamAsync();
|
||||||
|
#if !NETFRAMEWORK
|
||||||
await using var fs = new FileStream(path, FileMode.Create);
|
await using var fs = new FileStream(path, FileMode.Create);
|
||||||
|
#else
|
||||||
|
using var fs = new FileStream(path, FileMode.Create);
|
||||||
|
#endif
|
||||||
await s.CopyToAsync(fs);
|
await s.CopyToAsync(fs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -78,7 +78,11 @@ namespace Torch.API.WebAPI
|
|||||||
if(File.Exists(path))
|
if(File.Exists(path))
|
||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
|
|
||||||
|
#if NETFRAMEWORK
|
||||||
|
using var f = File.Create(path);
|
||||||
|
#else
|
||||||
await using var f = File.Create(path);
|
await using var f = File.Create(path);
|
||||||
|
#endif
|
||||||
await s.CopyToAsync(f);
|
await s.CopyToAsync(f);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch Server Tests")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -1,6 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net6-windows</TargetFramework>
|
||||||
|
<LangVersion>10</LangVersion>
|
||||||
<NoWarn>1591,0649</NoWarn>
|
<NoWarn>1591,0649</NoWarn>
|
||||||
<AssemblyTitle>Torch Server Tests</AssemblyTitle>
|
<AssemblyTitle>Torch Server Tests</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
@@ -27,9 +28,6 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties\AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
||||||
<ProjectReference Include="..\Torch.Server\Torch.Server.csproj" />
|
<ProjectReference Include="..\Torch.Server\Torch.Server.csproj" />
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<runtime>
|
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity name="protobuf-net" publicKeyToken="257b51d87d2e4d67" culture="neutral"/>
|
|
||||||
<bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0"/>
|
|
||||||
</dependentAssembly>
|
|
||||||
</assemblyBinding>
|
|
||||||
</runtime>
|
|
||||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
|
|
@@ -29,19 +29,14 @@ namespace Torch.Server
|
|||||||
private const string STEAMCMD_DIR = "steamcmd";
|
private const string STEAMCMD_DIR = "steamcmd";
|
||||||
private const string STEAMCMD_ZIP = "temp.zip";
|
private const string STEAMCMD_ZIP = "temp.zip";
|
||||||
private static readonly string STEAMCMD_EXE = "steamcmd.exe";
|
private static readonly string STEAMCMD_EXE = "steamcmd.exe";
|
||||||
private static readonly string RUNSCRIPT_FILE = "runscript.txt";
|
private const string STEAMCMD_ARGS = "+force_install_dir \"{0}\" +login anonymous +app_update 298740 +quit";
|
||||||
|
|
||||||
private const string RUNSCRIPT = @"force_install_dir ../
|
|
||||||
login anonymous
|
|
||||||
app_update 298740
|
|
||||||
quit";
|
|
||||||
private TorchServer _server;
|
private TorchServer _server;
|
||||||
|
|
||||||
internal Persistent<TorchConfig> ConfigPersistent { get; }
|
internal Persistent<TorchConfig> ConfigPersistent { get; }
|
||||||
public TorchConfig Config => ConfigPersistent?.Data;
|
public TorchConfig Config => ConfigPersistent?.Data;
|
||||||
public TorchServer Server => _server;
|
public TorchServer Server => _server;
|
||||||
|
|
||||||
public Initializer(string basePath, Persistent<TorchConfig> torchConfig)
|
public Initializer(Persistent<TorchConfig> torchConfig)
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
ConfigPersistent = torchConfig;
|
ConfigPersistent = torchConfig;
|
||||||
@@ -88,11 +83,11 @@ quit";
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run(bool isService, string instanceName, string instancePath)
|
public void Run()
|
||||||
{
|
{
|
||||||
_server = new TorchServer(Config, instancePath, instanceName);
|
_server = new TorchServer(Config, ApplicationContext.Current.InstanceDirectory.FullName, ApplicationContext.Current.InstanceName);
|
||||||
|
|
||||||
if (isService || Config.NoGui)
|
if (ApplicationContext.Current.IsService || Config.NoGui)
|
||||||
{
|
{
|
||||||
_server.Init();
|
_server.Init();
|
||||||
_server.Start();
|
_server.Start();
|
||||||
@@ -140,10 +135,6 @@ quit";
|
|||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
var runScriptPath = Path.Combine(path, RUNSCRIPT_FILE);
|
|
||||||
if (!File.Exists(runScriptPath))
|
|
||||||
File.WriteAllText(runScriptPath, RUNSCRIPT);
|
|
||||||
|
|
||||||
var steamCmdExePath = Path.Combine(path, STEAMCMD_EXE);
|
var steamCmdExePath = Path.Combine(path, STEAMCMD_EXE);
|
||||||
if (!File.Exists(steamCmdExePath))
|
if (!File.Exists(steamCmdExePath))
|
||||||
{
|
{
|
||||||
@@ -166,8 +157,9 @@ quit";
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Checking for DS updates.");
|
log.Info("Checking for DS updates.");
|
||||||
var steamCmdProc = new ProcessStartInfo(steamCmdExePath, "+runscript runscript.txt")
|
var steamCmdProc = new ProcessStartInfo(steamCmdExePath)
|
||||||
{
|
{
|
||||||
|
Arguments = string.Format(STEAMCMD_ARGS, Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? "../"),
|
||||||
WorkingDirectory = path,
|
WorkingDirectory = path,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
|
@@ -40,7 +40,13 @@ namespace Torch.Server.Managers
|
|||||||
|
|
||||||
protected abstract EntityControlViewModel Create(EntityViewModel evm);
|
protected abstract EntityControlViewModel Create(EntityViewModel evm);
|
||||||
|
|
||||||
|
#if NETFRAMEWORK
|
||||||
|
[ReflectedGetter(Name = "Keys")]
|
||||||
|
private static readonly Func<ConditionalWeakTable<EntityViewModel, EntityControlViewModel>, ICollection<EntityViewModel>> WeakTableKeys = null!;
|
||||||
|
internal IEnumerable<EntityViewModel> Keys => WeakTableKeys(_models);
|
||||||
|
#else
|
||||||
internal IEnumerable<EntityViewModel> Keys => _models.Select(b => b.Key);
|
internal IEnumerable<EntityViewModel> Keys => _models.Select(b => b.Key);
|
||||||
|
#endif
|
||||||
|
|
||||||
internal EntityControlViewModel GetOrCreate(EntityViewModel evm)
|
internal EntityControlViewModel GetOrCreate(EntityViewModel evm)
|
||||||
{
|
{
|
||||||
|
@@ -3,6 +3,7 @@ using System.IO;
|
|||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Config;
|
using NLog.Config;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
|
using Torch.API;
|
||||||
using Torch.Utils;
|
using Torch.Utils;
|
||||||
|
|
||||||
namespace Torch.Server
|
namespace Torch.Server
|
||||||
@@ -12,112 +13,71 @@ namespace Torch.Server
|
|||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var isService = Environment.GetEnvironmentVariable("TORCH_SERVICE")
|
var context = CreateApplicationContext();
|
||||||
?.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase) ?? false;
|
|
||||||
//Ensures that all the files are downloaded in the Torch directory.
|
|
||||||
var workingDir = AppContext.BaseDirectory;
|
|
||||||
var binDir = Path.Combine(Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? workingDir, "DedicatedServer64");
|
|
||||||
Directory.SetCurrentDirectory(Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? workingDir);
|
|
||||||
|
|
||||||
if (!isService && Directory.Exists(binDir))
|
|
||||||
foreach (var file in Directory.GetFiles(binDir, "System.*.dll"))
|
|
||||||
{
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Breaks on Windows Server 2019
|
SetupLogging();
|
||||||
#if TORCH_SERVICE
|
|
||||||
if (!new ComputerInfo().OSFullName.Contains("Server 2019") && !Environment.UserInteractive)
|
|
||||||
{
|
|
||||||
using (var service = new TorchService(args))
|
|
||||||
ServiceBase.Run(service);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var instanceName = Environment.GetEnvironmentVariable("TORCH_INSTANCE") ?? "Instance";
|
var oldTorchCfg = Path.Combine(context.TorchDirectory.FullName, "Torch.cfg");
|
||||||
string instancePath;
|
var torchCfg = Path.Combine(context.InstanceDirectory.FullName, "Torch.cfg");
|
||||||
|
|
||||||
if (Path.IsPathRooted(instanceName))
|
|
||||||
{
|
|
||||||
instancePath = instanceName;
|
|
||||||
instanceName = Path.GetDirectoryName(instanceName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
instancePath = Directory.CreateDirectory(instanceName).FullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
var oldNlog = Path.Combine(workingDir, "NLog.config");
|
|
||||||
var newNlog = Path.Combine(instancePath, "NLog.config");
|
|
||||||
if (File.Exists(oldNlog) && !File.ReadAllText(oldNlog).Contains("FlowDocument", StringComparison.Ordinal))
|
|
||||||
File.Move(oldNlog, newNlog, true);
|
|
||||||
else if (!File.Exists(newNlog))
|
|
||||||
using (var f = File.Create(newNlog))
|
|
||||||
typeof(Program).Assembly.GetManifestResourceStream("Torch.Server.NLog.config")!.CopyTo(f);
|
|
||||||
|
|
||||||
var oldTorchCfg = Path.Combine(workingDir, "Torch.cfg");
|
|
||||||
var torchCfg = Path.Combine(instancePath, "Torch.cfg");
|
|
||||||
|
|
||||||
if (File.Exists(oldTorchCfg))
|
if (File.Exists(oldTorchCfg))
|
||||||
File.Move(oldTorchCfg, torchCfg, true);
|
File.Move(oldTorchCfg, torchCfg);
|
||||||
|
|
||||||
var config = Persistent<TorchConfig>.Load(torchCfg);
|
var config = Persistent<TorchConfig>.Load(torchCfg);
|
||||||
config.Data.InstanceName = instanceName;
|
config.Data.InstanceName = context.InstanceName;
|
||||||
config.Data.InstancePath = instancePath;
|
config.Data.InstancePath = context.InstanceDirectory.FullName;
|
||||||
|
|
||||||
if (!config.Data.Parse(args))
|
if (!config.Data.Parse(args))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Invalid arguments");
|
Console.WriteLine("Invalid arguments");
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var handler = new UnhandledExceptionHandler(config.Data, isService);
|
var handler = new UnhandledExceptionHandler(config.Data);
|
||||||
AppDomain.CurrentDomain.UnhandledException += handler.OnUnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += handler.OnUnhandledException;
|
||||||
|
|
||||||
Target.Register<LogViewerTarget>(nameof(LogViewerTarget));
|
|
||||||
TorchLogManager.RegisterTargets(Environment.GetEnvironmentVariable("TORCH_LOG_EXTENSIONS_PATH") ??
|
|
||||||
Path.Combine(instancePath, "LoggingExtensions"));
|
|
||||||
|
|
||||||
TorchLogManager.SetConfiguration(new XmlLoggingConfiguration(newNlog));
|
|
||||||
|
|
||||||
var initializer = new Initializer(workingDir, config);
|
var initializer = new Initializer(config);
|
||||||
if (!initializer.Initialize(args))
|
if (!initializer.Initialize(args))
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
|
|
||||||
TorchLauncher.Launch(workingDir, binDir);
|
#if DEBUG
|
||||||
|
TorchLauncher.Launch(context.TorchDirectory.FullName, context.GameBinariesDirectory.FullName);
|
||||||
|
#else
|
||||||
|
TorchLauncher.Launch(context.TorchDirectory.FullName, Path.Combine(context.TorchDirectory.FullName, "torch64"),
|
||||||
|
context.GameBinariesDirectory.FullName);
|
||||||
|
#endif
|
||||||
|
|
||||||
CopyNative(binDir);
|
CopyNative();
|
||||||
|
|
||||||
initializer.Run(isService, instanceName, instancePath);
|
initializer.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyNative(string binPath)
|
private static void CopyNative()
|
||||||
{
|
{
|
||||||
var log = LogManager.GetLogger("TorchLauncher");
|
var log = LogManager.GetLogger("TorchLauncher");
|
||||||
|
|
||||||
var workingDir = new DirectoryInfo(Directory.GetCurrentDirectory());
|
if (ApplicationContext.Current.GameFilesDirectory.Attributes.HasFlag(FileAttributes.ReadOnly))
|
||||||
if (workingDir.Attributes.HasFlag(FileAttributes.ReadOnly))
|
|
||||||
{
|
{
|
||||||
log.Warn("Game directory is readonly. You should copy steam_api64.dll, Havok.dll from bin manually");
|
log.Warn("Torch directory is readonly. You should copy steam_api64.dll, Havok.dll from bin manually");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var apiSource = Path.Combine(binPath, "steam_api64.dll");
|
var apiSource = Path.Combine(ApplicationContext.Current.GameBinariesDirectory.FullName, "steam_api64.dll");
|
||||||
var apiTarget = Path.Combine(workingDir.FullName, "steam_api64.dll");
|
var apiTarget = Path.Combine(ApplicationContext.Current.GameFilesDirectory.FullName, "steam_api64.dll");
|
||||||
if (!File.Exists(apiTarget))
|
if (!File.Exists(apiTarget))
|
||||||
{
|
{
|
||||||
File.Copy(apiSource, apiTarget);
|
File.Copy(apiSource, apiTarget);
|
||||||
}
|
}
|
||||||
else if (File.GetLastWriteTime(apiTarget) < File.GetLastWriteTime(binPath))
|
else if (File.GetLastWriteTime(apiTarget) < ApplicationContext.Current.GameBinariesDirectory.LastWriteTime)
|
||||||
{
|
{
|
||||||
File.Delete(apiTarget);
|
File.Delete(apiTarget);
|
||||||
File.Copy(apiSource, apiTarget);
|
File.Copy(apiSource, apiTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
var havokSource = Path.Combine(binPath, "Havok.dll");
|
var havokSource = Path.Combine(ApplicationContext.Current.GameBinariesDirectory.FullName, "Havok.dll");
|
||||||
var havokTarget = Path.Combine(workingDir.FullName, "Havok.dll");
|
var havokTarget = Path.Combine(ApplicationContext.Current.GameFilesDirectory.FullName, "Havok.dll");
|
||||||
|
|
||||||
if (!File.Exists(havokTarget))
|
if (!File.Exists(havokTarget))
|
||||||
{
|
{
|
||||||
@@ -138,5 +98,49 @@ namespace Torch.Server
|
|||||||
log.Error(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"))
|
||||||
|
File.Move(oldNlog, newNlog);
|
||||||
|
else if (!File.Exists(newNlog))
|
||||||
|
using (var f = File.Create(newNlog))
|
||||||
|
typeof(Program).Assembly.GetManifestResourceStream("Torch.Server.NLog.config")!.CopyTo(f);
|
||||||
|
|
||||||
|
Target.Register<LogViewerTarget>(nameof(LogViewerTarget));
|
||||||
|
TorchLogManager.RegisterTargets(Environment.GetEnvironmentVariable("TORCH_LOG_EXTENSIONS_PATH") ??
|
||||||
|
Path.Combine(ApplicationContext.Current.InstanceDirectory.FullName, "LoggingExtensions"));
|
||||||
|
|
||||||
|
TorchLogManager.SetConfiguration(new XmlLoggingConfiguration(newNlog));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IApplicationContext CreateApplicationContext()
|
||||||
|
{
|
||||||
|
var isService = Environment.GetEnvironmentVariable("TORCH_SERVICE")
|
||||||
|
?.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase) ?? false;
|
||||||
|
|
||||||
|
var workingDir = AppContext.BaseDirectory;
|
||||||
|
var gamePath = Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? workingDir;
|
||||||
|
var binDir = Path.Combine(gamePath, "DedicatedServer64");
|
||||||
|
Directory.SetCurrentDirectory(gamePath);
|
||||||
|
|
||||||
|
var instanceName = Environment.GetEnvironmentVariable("TORCH_INSTANCE") ?? "Instance";
|
||||||
|
string instancePath;
|
||||||
|
|
||||||
|
if (Path.IsPathRooted(instanceName))
|
||||||
|
{
|
||||||
|
instancePath = instanceName;
|
||||||
|
instanceName = Path.GetDirectoryName(instanceName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instancePath = Directory.CreateDirectory(instanceName).FullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ApplicationContext(new(workingDir), new(gamePath), new(binDir),
|
||||||
|
new(instancePath), instanceName, isService);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch Server")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -2,11 +2,10 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net6-windows</TargetFramework>
|
||||||
|
<LangVersion>10</LangVersion>
|
||||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
<PublishUrl>publish\</PublishUrl>
|
<PublishUrl>publish\</PublishUrl>
|
||||||
<ApplicationRevision>0</ApplicationRevision>
|
|
||||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
|
||||||
<UseApplicationTrust>false</UseApplicationTrust>
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
<AssemblyTitle>Torch Server</AssemblyTitle>
|
<AssemblyTitle>Torch Server</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
@@ -14,13 +13,16 @@
|
|||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||||
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
|
||||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Platforms>AnyCPU</Platforms>
|
<Platforms>AnyCPU</Platforms>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<NeutralLanguage>en</NeutralLanguage>
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
|
|
||||||
|
<BeautyLibsDir>torch64</BeautyLibsDir>
|
||||||
|
<NoBeautyFlag>True</NoBeautyFlag>
|
||||||
|
<ForceBeauty>True</ForceBeauty>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<StartupObject>Torch.Server.Program</StartupObject>
|
<StartupObject>Torch.Server.Program</StartupObject>
|
||||||
@@ -40,6 +42,7 @@
|
|||||||
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" PrivateAssets="all" />
|
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Management" Version="6.0.0" />
|
<PackageReference Include="System.Management" Version="6.0.0" />
|
||||||
|
<PackageReference Include="nulastudio.NetCoreBeauty" Version="1.2.9.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="HavokWrapper, Version=1.0.6051.28726, Culture=neutral, processorArchitecture=AMD64">
|
<Reference Include="HavokWrapper, Version=1.0.6051.28726, Culture=neutral, processorArchitecture=AMD64">
|
||||||
@@ -143,7 +146,6 @@
|
|||||||
<Compile Remove="ServerManager.cs" />
|
<Compile Remove="ServerManager.cs" />
|
||||||
<Compile Remove="ViewModels\SessionSettingsViewModel1.cs" />
|
<Compile Remove="ViewModels\SessionSettingsViewModel1.cs" />
|
||||||
<Compile Remove="Views\WorldSelectControl.xaml.cs" />
|
<Compile Remove="Views\WorldSelectControl.xaml.cs" />
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
||||||
|
@@ -221,7 +221,11 @@ namespace Torch.Server
|
|||||||
LogManager.Flush();
|
LogManager.Flush();
|
||||||
|
|
||||||
string exe = Assembly.GetExecutingAssembly().Location.Replace("dll", "exe");
|
string exe = Assembly.GetExecutingAssembly().Location.Replace("dll", "exe");
|
||||||
|
#if NETFRAMEWORK
|
||||||
|
config.WaitForPID = Process.GetCurrentProcess().Id.ToString();
|
||||||
|
#else
|
||||||
config.WaitForPID = Environment.ProcessId.ToString();
|
config.WaitForPID = Environment.ProcessId.ToString();
|
||||||
|
#endif
|
||||||
config.TempAutostart = true;
|
config.TempAutostart = true;
|
||||||
Process.Start(exe, config.ToString());
|
Process.Start(exe, config.ToString());
|
||||||
|
|
||||||
@@ -370,35 +374,37 @@ namespace Torch.Server
|
|||||||
// return stack.ToString();
|
// return stack.ToString();
|
||||||
|
|
||||||
// Modified from https://www.examplefiles.net/cs/579311
|
// Modified from https://www.examplefiles.net/cs/579311
|
||||||
using (var target = DataTarget.CreateSnapshotAndAttach(Environment.ProcessId))
|
#if NETFRAMEWORK
|
||||||
{
|
using var target = DataTarget.CreateSnapshotAndAttach(Process.GetCurrentProcess().Id);
|
||||||
var runtime = target.ClrVersions[0].CreateRuntime();
|
#else
|
||||||
|
using var target = DataTarget.CreateSnapshotAndAttach(Environment.ProcessId);
|
||||||
|
#endif
|
||||||
|
var runtime = target.ClrVersions[0].CreateRuntime();
|
||||||
|
|
||||||
var clrThread = runtime.Threads.First(b => b.ManagedThreadId == thread.ManagedThreadId);
|
var clrThread = runtime.Threads.First(b => b.ManagedThreadId == thread.ManagedThreadId);
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
foreach (var frame in clrThread.EnumerateStackTrace())
|
foreach (var frame in clrThread.EnumerateStackTrace())
|
||||||
|
{
|
||||||
|
sb.Append('\t');
|
||||||
|
switch (frame.Kind)
|
||||||
{
|
{
|
||||||
sb.Append('\t');
|
case ClrStackFrameKind.Unknown:
|
||||||
switch (frame.Kind)
|
sb.AppendLine("[Unknown]");
|
||||||
{
|
break;
|
||||||
case ClrStackFrameKind.Unknown:
|
case ClrStackFrameKind.ManagedMethod:
|
||||||
sb.AppendLine("[Unknown]");
|
sb.AppendLine(frame.Method?.Signature ?? "[Unable to get method signature]");
|
||||||
break;
|
break;
|
||||||
case ClrStackFrameKind.ManagedMethod:
|
case ClrStackFrameKind.Runtime:
|
||||||
sb.AppendLine(frame.Method?.Signature ?? "[Unable to get method signature]");
|
sb.AppendLine("[CLR Runtime]");
|
||||||
break;
|
break;
|
||||||
case ClrStackFrameKind.Runtime:
|
default:
|
||||||
sb.AppendLine("[CLR Runtime]");
|
throw new ArgumentOutOfRangeException(nameof(frame.Kind), frame.Kind, "Incorrect value in EnumerateStackTrace");
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(frame.Kind), frame.Kind, "Incorrect value in EnumerateStackTrace");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@@ -9,13 +9,11 @@ namespace Torch.Server;
|
|||||||
internal class UnhandledExceptionHandler
|
internal class UnhandledExceptionHandler
|
||||||
{
|
{
|
||||||
private readonly TorchConfig _config;
|
private readonly TorchConfig _config;
|
||||||
private readonly bool _isService;
|
|
||||||
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
public UnhandledExceptionHandler(TorchConfig config, bool isService)
|
public UnhandledExceptionHandler(TorchConfig config)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_isService = isService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
internal void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
@@ -26,7 +24,7 @@ internal class UnhandledExceptionHandler
|
|||||||
Log.Fatal(ex.ToStringDemystified());
|
Log.Fatal(ex.ToStringDemystified());
|
||||||
LogManager.Flush();
|
LogManager.Flush();
|
||||||
|
|
||||||
if (_isService)
|
if (ApplicationContext.Current.IsService)
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
|
|
||||||
if (_config.RestartOnCrash)
|
if (_config.RestartOnCrash)
|
||||||
@@ -34,7 +32,11 @@ internal class UnhandledExceptionHandler
|
|||||||
Console.WriteLine("Restarting in 5 seconds.");
|
Console.WriteLine("Restarting in 5 seconds.");
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
var exe = typeof(Program).Assembly.Location;
|
var exe = typeof(Program).Assembly.Location;
|
||||||
|
#if NETFRAMEWORK
|
||||||
|
_config.WaitForPID = Process.GetCurrentProcess().Id.ToString();
|
||||||
|
#else
|
||||||
_config.WaitForPID = Environment.ProcessId.ToString();
|
_config.WaitForPID = Environment.ProcessId.ToString();
|
||||||
|
#endif
|
||||||
Process.Start(exe, _config.ToString());
|
Process.Start(exe, _config.ToString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -32,7 +32,7 @@ public class CommandSuggestionsProvider : ISuggestionProvider
|
|||||||
{
|
{
|
||||||
if (_commandManager is null || !_commandManager.IsCommand(filter))
|
if (_commandManager is null || !_commandManager.IsCommand(filter))
|
||||||
yield break;
|
yield break;
|
||||||
var args = filter[1..].Split(' ').ToList();
|
var args = filter.Substring(1).Split(' ').ToList();
|
||||||
var skip = _commandManager.Commands.GetNode(args, out var node);
|
var skip = _commandManager.Commands.GetNode(args, out var node);
|
||||||
if (skip == -1)
|
if (skip == -1)
|
||||||
yield break;
|
yield break;
|
||||||
@@ -42,7 +42,7 @@ public class CommandSuggestionsProvider : ISuggestionProvider
|
|||||||
{
|
{
|
||||||
if (lastArg != node.Name && !subcommandsKey.Contains(lastArg))
|
if (lastArg != node.Name && !subcommandsKey.Contains(lastArg))
|
||||||
continue;
|
continue;
|
||||||
yield return $"!{string.Join(' ', node.GetPath())} {subcommandsKey}";
|
yield return $"!{string.Join(" ", node.GetPath())} {subcommandsKey}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -130,17 +130,17 @@ namespace Torch.Server.Views
|
|||||||
//blocking
|
//blocking
|
||||||
editor.Edit<string>(idList, "Mods");
|
editor.Edit<string>(idList, "Mods");
|
||||||
|
|
||||||
modList.RemoveAll(m =>
|
modList.Clear();
|
||||||
{
|
|
||||||
var mod = m.ToString();
|
|
||||||
return idList.Any(mod.Equals);
|
|
||||||
});
|
|
||||||
modList.AddRange(idList.Select(id =>
|
modList.AddRange(idList.Select(id =>
|
||||||
{
|
{
|
||||||
var info = new ModItemInfo(ModItemUtils.Create(id));
|
if (!ModItemUtils.TryParse(id, out var item))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var info = new ModItemInfo(item);
|
||||||
tasks.Add(Task.Run(info.UpdateModInfoAsync));
|
tasks.Add(Task.Run(info.UpdateModInfoAsync));
|
||||||
return info;
|
return info;
|
||||||
}));
|
}).Where(b => b is not null));
|
||||||
|
|
||||||
_instanceManager.DedicatedConfig.Mods.Clear();
|
_instanceManager.DedicatedConfig.Mods.Clear();
|
||||||
foreach (var mod in modList)
|
foreach (var mod in modList)
|
||||||
_instanceManager.DedicatedConfig.Mods.Add(mod);
|
_instanceManager.DedicatedConfig.Mods.Add(mod);
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch Tests")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -1,6 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net6-windows</TargetFramework>
|
||||||
|
<LangVersion>10</LangVersion>
|
||||||
<NoWarn>1591,0649</NoWarn>
|
<NoWarn>1591,0649</NoWarn>
|
||||||
<AssemblyTitle>Torch Tests</AssemblyTitle>
|
<AssemblyTitle>Torch Tests</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
@@ -8,7 +9,6 @@
|
|||||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
<OutputPath>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\</OutputPath>
|
<OutputPath>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\</OutputPath>
|
||||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Platforms>AnyCPU</Platforms>
|
<Platforms>AnyCPU</Platforms>
|
||||||
@@ -27,13 +27,6 @@
|
|||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="mscorlib" />
|
|
||||||
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
|
||||||
<ProjectReference Include="..\Torch\Torch.csproj" />
|
<ProjectReference Include="..\Torch\Torch.csproj" />
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<runtime>
|
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity name="protobuf-net" publicKeyToken="257b51d87d2e4d67" culture="neutral"/>
|
|
||||||
<bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0"/>
|
|
||||||
</dependentAssembly>
|
|
||||||
</assemblyBinding>
|
|
||||||
</runtime>
|
|
||||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
|
|
@@ -12,17 +12,13 @@ EndProject
|
|||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7AD02A71-1D4C-48F9-A8C1-789A5512424F}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7AD02A71-1D4C-48F9-A8C1-789A5512424F}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
NLog.config = NLog.config
|
NLog.config = NLog.config
|
||||||
|
Jenkinsfile = Jenkinsfile
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Tests", "Torch.Tests\Torch.Tests.csproj", "{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Tests", "Torch.Tests\Torch.Tests.csproj", "{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Server.Tests", "Torch.Server.Tests\Torch.Server.Tests.csproj", "{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Server.Tests", "Torch.Server.Tests\Torch.Server.Tests.csproj", "{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Versioning", "Versioning", "{762F6A0D-55EF-4173-8CDE-309D183F40C4}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
Versioning\AssemblyVersion.cs = Versioning\AssemblyVersion.cs
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Torch.Mod", "Torch.Mod\Torch.Mod.shproj", "{3CE4D2E9-B461-4F19-8233-F87E0DFDDD74}"
|
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Torch.Mod", "Torch.Mod\Torch.Mod.shproj", "{3CE4D2E9-B461-4F19-8233-F87E0DFDDD74}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
@@ -56,7 +52,6 @@ Global
|
|||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{762F6A0D-55EF-4173-8CDE-309D183F40C4} = {7AD02A71-1D4C-48F9-A8C1-789A5512424F}
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {BB51D91F-958D-4B63-A897-3C40642ACD3E}
|
SolutionGuid = {BB51D91F-958D-4B63-A897-3C40642ACD3E}
|
||||||
|
32
Torch/ApplicationContext.cs
Normal file
32
Torch/ApplicationContext.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System.IO;
|
||||||
|
using Torch.API;
|
||||||
|
namespace Torch;
|
||||||
|
|
||||||
|
public class ApplicationContext : IApplicationContext
|
||||||
|
{
|
||||||
|
public static IApplicationContext Current { get; private set; }
|
||||||
|
public ApplicationContext(DirectoryInfo torchDirectory, DirectoryInfo gameFilesDirectory, DirectoryInfo gameBinariesDirectory,
|
||||||
|
DirectoryInfo instanceDirectory, string instanceName, bool isService)
|
||||||
|
{
|
||||||
|
TorchDirectory = torchDirectory;
|
||||||
|
GameFilesDirectory = gameFilesDirectory;
|
||||||
|
GameBinariesDirectory = gameBinariesDirectory;
|
||||||
|
InstanceDirectory = instanceDirectory;
|
||||||
|
InstanceName = instanceName;
|
||||||
|
IsService = isService;
|
||||||
|
Current = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DirectoryInfo TorchDirectory { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DirectoryInfo GameFilesDirectory { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DirectoryInfo GameBinariesDirectory { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DirectoryInfo InstanceDirectory { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string InstanceName { get; }
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsService { get; }
|
||||||
|
}
|
@@ -1,8 +1,10 @@
|
|||||||
using System;
|
#if !NETFRAMEWORK
|
||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -11,6 +13,8 @@ using System.Reflection.Emit;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
|
using ProtoBuf;
|
||||||
|
using ProtoBuf.Meta;
|
||||||
using Torch.Managers.PatchManager;
|
using Torch.Managers.PatchManager;
|
||||||
using Torch.Managers.PatchManager.MSIL;
|
using Torch.Managers.PatchManager.MSIL;
|
||||||
using Torch.Utils;
|
using Torch.Utils;
|
||||||
@@ -55,9 +59,9 @@ namespace Torch.Patches
|
|||||||
typeof(ImmutableArray).Assembly.Location,
|
typeof(ImmutableArray).Assembly.Location,
|
||||||
typeof(PropertyChangedEventArgs).Assembly.Location,
|
typeof(PropertyChangedEventArgs).Assembly.Location,
|
||||||
typeof(TypeConverter).Assembly.Location,
|
typeof(TypeConverter).Assembly.Location,
|
||||||
typeof(System.Diagnostics.TraceSource).Assembly.Location,
|
typeof(TraceSource).Assembly.Location,
|
||||||
typeof(ProtoBuf.Meta.RuntimeTypeModel).Assembly.Location,
|
typeof(RuntimeTypeModel).Assembly.Location,
|
||||||
typeof(ProtoBuf.ProtoMemberAttribute).Assembly.Location,
|
typeof(ProtoMemberAttribute).Assembly.Location,
|
||||||
Path.Combine(MyFileSystem.ExePath, "Sandbox.Game.dll"),
|
Path.Combine(MyFileSystem.ExePath, "Sandbox.Game.dll"),
|
||||||
Path.Combine(MyFileSystem.ExePath, "Sandbox.Common.dll"),
|
Path.Combine(MyFileSystem.ExePath, "Sandbox.Common.dll"),
|
||||||
Path.Combine(MyFileSystem.ExePath, "Sandbox.Graphics.dll"),
|
Path.Combine(MyFileSystem.ExePath, "Sandbox.Graphics.dll"),
|
||||||
@@ -107,4 +111,5 @@ namespace Torch.Patches
|
|||||||
return ins;
|
return ins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
@@ -1,34 +1,52 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
using NLog;
|
|
||||||
|
|
||||||
namespace Torch.Plugins;
|
namespace Torch.Plugins;
|
||||||
|
|
||||||
internal static class AssemblyRewriter
|
internal static class AssemblyRewriter
|
||||||
{
|
{
|
||||||
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
|
private static readonly ZipResolver _zipResolver;
|
||||||
|
private static readonly DefaultAssemblyResolver _defaultResolver;
|
||||||
private static readonly IAssemblyResolver Resolver;
|
|
||||||
|
|
||||||
static AssemblyRewriter()
|
static AssemblyRewriter()
|
||||||
{
|
{
|
||||||
var resolver = new DefaultAssemblyResolver();
|
_defaultResolver = new();
|
||||||
Resolver = resolver;
|
_zipResolver = new(_defaultResolver);
|
||||||
resolver.AddSearchDirectory(Directory.GetCurrentDirectory());
|
_defaultResolver.AddSearchDirectory(Directory.GetCurrentDirectory());
|
||||||
resolver.AddSearchDirectory(Path.Combine(Directory.GetCurrentDirectory(), "DedicatedServer64"));
|
_defaultResolver.AddSearchDirectory(Path.Combine(Directory.GetCurrentDirectory(), "DedicatedServer64"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Assembly ProcessWeavers(this Stream stream)
|
public static Assembly ProcessWeavers(this Stream stream, ZipArchive archive)
|
||||||
{
|
{
|
||||||
|
_zipResolver.Archive = archive;
|
||||||
using var assStream = new MemoryStream();
|
using var assStream = new MemoryStream();
|
||||||
stream.CopyTo(assStream);
|
stream.CopyTo(assStream);
|
||||||
assStream.Position = 0;
|
assStream.Position = 0;
|
||||||
using var module = ModuleDefinition.ReadModule(assStream, new()
|
var ass = ProcessInternal(assStream, _zipResolver);
|
||||||
|
_zipResolver.Archive = null;
|
||||||
|
return ass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Assembly ProcessWeavers(this Stream stream, string path)
|
||||||
|
{
|
||||||
|
_defaultResolver.AddSearchDirectory(path);
|
||||||
|
using var assStream = new MemoryStream();
|
||||||
|
stream.CopyTo(assStream);
|
||||||
|
assStream.Position = 0;
|
||||||
|
var ass = ProcessInternal(assStream, _defaultResolver);
|
||||||
|
_defaultResolver.RemoveSearchDirectory(path);
|
||||||
|
return ass;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Assembly ProcessInternal(Stream inputStream, IAssemblyResolver resolver)
|
||||||
|
{
|
||||||
|
using var module = ModuleDefinition.ReadModule(inputStream, new()
|
||||||
{
|
{
|
||||||
AssemblyResolver = Resolver
|
AssemblyResolver = _zipResolver
|
||||||
});
|
});
|
||||||
foreach (var fieldDefinition in FindAllToRewrite(module))
|
foreach (var fieldDefinition in FindAllToRewrite(module))
|
||||||
{
|
{
|
||||||
@@ -47,4 +65,40 @@ internal static class AssemblyRewriter
|
|||||||
|
|
||||||
private static bool HasValidAttributes(FieldDefinition definition) =>
|
private static bool HasValidAttributes(FieldDefinition definition) =>
|
||||||
definition.CustomAttributes.Any(b => b.AttributeType.Name.Contains("Reflected") || b.AttributeType.Name == "DependencyAttribute");
|
definition.CustomAttributes.Any(b => b.AttributeType.Name.Contains("Reflected") || b.AttributeType.Name == "DependencyAttribute");
|
||||||
|
|
||||||
|
private class ZipResolver : IAssemblyResolver
|
||||||
|
{
|
||||||
|
private readonly IAssemblyResolver _fallbackResolver;
|
||||||
|
public ZipArchive Archive { get; set; }
|
||||||
|
|
||||||
|
public ZipResolver(IAssemblyResolver fallbackResolver)
|
||||||
|
{
|
||||||
|
_fallbackResolver = fallbackResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_fallbackResolver.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssemblyDefinition Resolve(AssemblyNameReference name)
|
||||||
|
{
|
||||||
|
return Resolve(name, new());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
|
||||||
|
{
|
||||||
|
var fileName = $"{name.Name}.dll";
|
||||||
|
|
||||||
|
if (Archive.Entries.FirstOrDefault(entry => entry.Name == fileName) is not { } archiveEntry)
|
||||||
|
return _fallbackResolver.Resolve(name, parameters);
|
||||||
|
|
||||||
|
using var stream = archiveEntry.Open();
|
||||||
|
using var memStream = new MemoryStream();
|
||||||
|
stream.CopyTo(memStream);
|
||||||
|
memStream.Position = 0;
|
||||||
|
|
||||||
|
return AssemblyDefinition.ReadAssembly(memStream, parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -360,7 +360,7 @@ namespace Torch.Managers
|
|||||||
|
|
||||||
|
|
||||||
using var stream = entry.Open();
|
using var stream = entry.Open();
|
||||||
assemblies.Add(stream.ProcessWeavers());
|
assemblies.Add(stream.ProcessWeavers(zipFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -378,7 +378,7 @@ namespace Torch.Managers
|
|||||||
// continue;
|
// continue;
|
||||||
|
|
||||||
using var stream = File.OpenRead(file);
|
using var stream = File.OpenRead(file);
|
||||||
assemblies.Add(stream.ProcessWeavers());
|
assemblies.Add(stream.ProcessWeavers(item.Path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[assembly: AssemblyTitle("Torch")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Torch")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Torch API 2017")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
[assembly: AssemblyConfiguration("Debug")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyConfiguration("Release")]
|
|
||||||
#endif
|
|
@@ -1,6 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6-windows</TargetFramework>
|
<TargetFramework>net6-windows</TargetFramework>
|
||||||
|
<LangVersion>10</LangVersion>
|
||||||
<AssemblyTitle>Torch</AssemblyTitle>
|
<AssemblyTitle>Torch</AssemblyTitle>
|
||||||
<Product>Torch</Product>
|
<Product>Torch</Product>
|
||||||
<Copyright>Copyright © Torch API 2017</Copyright>
|
<Copyright>Copyright © Torch API 2017</Copyright>
|
||||||
@@ -8,7 +9,6 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
<OutputPath>..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||||
<UseWpf>True</UseWpf>
|
<UseWpf>True</UseWpf>
|
||||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Platforms>AnyCPU</Platforms>
|
<Platforms>AnyCPU</Platforms>
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Sandbox.Engine.Networking;
|
using Sandbox.Engine.Networking;
|
||||||
using Torch.API;
|
using Torch.API;
|
||||||
@@ -18,6 +19,43 @@ namespace Torch.Utils
|
|||||||
var arr = str.Split('-');
|
var arr = str.Split('-');
|
||||||
return new MyObjectBuilder_Checkpoint.ModItem(ulong.Parse(arr[0]), arr[1]);
|
return new MyObjectBuilder_Checkpoint.ModItem(ulong.Parse(arr[0]), arr[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool TryParse(string str, out MyObjectBuilder_Checkpoint.ModItem item)
|
||||||
|
{
|
||||||
|
item = default;
|
||||||
|
|
||||||
|
var arr = str.Split('-');
|
||||||
|
|
||||||
|
if (arr.Length is 0 or > 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ulong.TryParse(arr[0], out var id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (arr.Length == 1 || !TryParseServiceName(arr[1], out var serviceName))
|
||||||
|
serviceName = GetDefaultServiceName();
|
||||||
|
|
||||||
|
item = new(id, serviceName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryParseServiceName(string str, out string serviceName)
|
||||||
|
{
|
||||||
|
if (str.Equals("steam", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
serviceName = "Steam";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (str.Equals("mod.io", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
str.Equals("eos", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
serviceName = "mod.io";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceName = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//because KEEEN!
|
//because KEEEN!
|
||||||
public static string GetDefaultServiceName()
|
public static string GetDefaultServiceName()
|
||||||
|
@@ -1,14 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using ProtoBuf;
|
|
||||||
using Torch.API;
|
|
||||||
|
|
||||||
namespace Torch.Utils
|
namespace Torch.Utils
|
||||||
{
|
{
|
||||||
@@ -23,7 +17,13 @@ namespace Torch.Utils
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var name = AssemblyName.GetAssemblyName(file);
|
var name = AssemblyName.GetAssemblyName(file);
|
||||||
Assemblies.TryAdd(name.Name ?? name.FullName.Split(',')[0], file);
|
var key = name.Name ?? name.FullName.Split(',')[0];
|
||||||
|
#if NETFRAMEWORK
|
||||||
|
if (!Assemblies.ContainsKey(key))
|
||||||
|
Assemblies.Add(key, file);
|
||||||
|
#else
|
||||||
|
Assemblies.TryAdd(key, file);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch (BadImageFormatException)
|
catch (BadImageFormatException)
|
||||||
{
|
{
|
||||||
@@ -37,7 +37,7 @@ namespace Torch.Utils
|
|||||||
private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
|
private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
|
||||||
{
|
{
|
||||||
var name = args.Name;
|
var name = args.Name;
|
||||||
return Assemblies.TryGetValue(name[..name.IndexOf(',')], out var path) ? Assembly.LoadFrom(path) : null;
|
return Assemblies.TryGetValue(name.IndexOf(',') > 0 ? name.Substring(0, name.IndexOf(',')) : name, out var path) ? Assembly.LoadFrom(path) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,9 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
#if !NETFRAMEWORK
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
|
#endif
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Config;
|
using NLog.Config;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
@@ -11,7 +13,9 @@ namespace Torch.Utils;
|
|||||||
|
|
||||||
public static class TorchLogManager
|
public static class TorchLogManager
|
||||||
{
|
{
|
||||||
|
#if !NETFRAMEWORK
|
||||||
private static AssemblyLoadContext LoadContext = new("TorchLog");
|
private static AssemblyLoadContext LoadContext = new("TorchLog");
|
||||||
|
#endif
|
||||||
|
|
||||||
public static LoggingConfiguration Configuration { get; private set; }
|
public static LoggingConfiguration Configuration { get; private set; }
|
||||||
|
|
||||||
@@ -26,7 +30,12 @@ public static class TorchLogManager
|
|||||||
{
|
{
|
||||||
if (!Directory.Exists(dir)) return;
|
if (!Directory.Exists(dir)) return;
|
||||||
|
|
||||||
foreach (var type in Directory.EnumerateFiles(dir, "*.dll").Select(LoadContext.LoadFromAssemblyPath)
|
foreach (var type in Directory.EnumerateFiles(dir, "*.dll")
|
||||||
|
#if NETFRAMEWORK
|
||||||
|
.Select(Assembly.LoadFile)
|
||||||
|
#else
|
||||||
|
.Select(LoadContext.LoadFromAssemblyPath)
|
||||||
|
#endif
|
||||||
.SelectMany(b => b.ExportedTypes)
|
.SelectMany(b => b.ExportedTypes)
|
||||||
.Where(b => b.GetCustomAttribute<TargetAttribute>() is { }))
|
.Where(b => b.GetCustomAttribute<TargetAttribute>() is { }))
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
|
|
||||||
[assembly: AssemblyVersion("0.0.0.0")]
|
|
||||||
[assembly: AssemblyInformationalVersion("v0.0.0-dev")]
|
|
Reference in New Issue
Block a user